Compare commits

...

345 Commits

Author SHA1 Message Date
Uwe Kindler
60d915a99f Changed SideTab check in AutoHideDockContainer::eventFilter to improve performance a little bit 2022-11-23 08:43:45 +01:00
Uwe Kindler
47e4a6065a Fixed some issues in AutoHideDockContainer eventFilter function 2022-11-22 21:36:43 +01:00
Uwe Kindler
a2a328e3c7 Ensure that auto hide widget will be closed if user starts dragging floating widget or docked widget 2022-11-22 11:11:49 +01:00
Uwe Kindler
dba6e6c869 Create ActiveX widget only if OpaqueUndocking is not active - it will cause jerking dragging of floating widget 2022-11-22 10:25:44 +01:00
Uwe Kindler
aee68c167a Fixed hiding of AutoHideContainer when clicking outside context menu 2022-11-22 09:01:16 +01:00
Uwe Kindler
5a185268c4 Fixed missing source files in demo/CMakeLists.txt 2022-11-21 08:00:42 +01:00
Uwe Kindler
8bc2236f4f Updated release badge 2022-11-18 23:16:53 +01:00
Uwe Kindler
f39b3095aa Added release and contributor badges 2022-11-18 23:09:26 +01:00
Uwe Kindler
384e29dcec Updated README.md 2022-11-18 22:19:31 +01:00
Uwe Kindler
e060d99d96 Merged master 2022-11-18 21:50:38 +01:00
Uwe Kindler
8d30fc9c3c Fix various clazy warnings 2022-11-18 21:36:31 +01:00
Uwe Kindler
ca1d3fcd38 normalize SIGNAL(),SLOT() signatures 2022-11-18 21:22:44 +01:00
Uwe Kindler
b82d23e59c Guard against null pointer access 2022-11-18 21:15:06 +01:00
Uwe Kindler
6d8e396e92 Prevent null pointer access 2022-11-18 21:12:17 +01:00
Uwe Kindler
0b5840309f Added support for runtime switching of CAutoHideDockContainer sidebar location 2022-11-15 15:08:52 +01:00
Uwe Kindler
ac1a0962d3 Removed QRandomNumberGenerator for Qt versions < 5.10 2022-11-15 14:35:52 +01:00
Uwe Kindler
260a2ddb24 Fixed restoreSideBar function and dropping floating widget with auto hide widgets 2022-11-15 14:21:24 +01:00
Uwe Kindler
7b9f9e10e5 Added function to add / remove CAutoHideDockContainer from SideBar 2022-11-15 14:16:01 +01:00
Uwe Kindler
3fded82f26 Merge branch 'master' into auto_hide_feature 2022-11-15 11:22:14 +01:00
Uwe Kindler
07d0bdc8ed Improved CAutoHideDockContainer::eventFilter function to collapse the auto hide widget if someone clicks into another window 2022-11-15 10:46:15 +01:00
Uwe Kindler
5caa5db273 Added some comment 2022-11-15 09:50:39 +01:00
Uwe Kindler
f554df9e7a Fixed FloatingDockContainer.cpp to properly post the dragging start event 2022-11-15 09:28:23 +01:00
Uwe
7f58877a47 Added FloatingWidgetDragStartEvent to hide AutoHideContainer if user drags floating widget 2022-11-15 08:44:07 +01:00
Uwe Kindler
b50e2017e6 Removed superfluous includes and fixed use of deprecates globalPositionOf() function 2022-11-14 22:16:03 +01:00
Uwe Kindler
e4a71982d9 Added support for inserting a dock widget with a given tab index and added test case 2022-11-14 19:54:12 +01:00
Uwe Kindler
7dee00f89b Removed QColorSpace to fix Ubuntu build 2022-11-14 15:23:08 +01:00
Uwe Kindler
3b8775fd86 Added tab icon 2022-11-14 14:56:18 +01:00
Uwe Kindler
d5ffd8f6a7 Removed debug output 2022-11-14 14:56:06 +01:00
Uwe Kindler
296c7edbd0 Added support for tab index when inserting dockwidgets into area 2022-11-14 14:49:58 +01:00
Uwe Kindler
2563b9e874 Added auto hide contributor name to README.md 2022-11-13 17:20:26 +01:00
Uwe Kindler
f304ed7f70 Added AutoHide feature to README.md 2022-11-11 17:18:58 +01:00
Uwe Kindler
9174339b68 Added Auto-Hide functionality to README.md 2022-11-11 16:45:19 +01:00
Uwe Kindler
407c70a8c5 Fixed insertion of resize handle in AutoHideDockContainer.cpp 2022-11-11 16:43:31 +01:00
Uwe Kindler
87f5b6127b Fixed restoreSideBar() function to prevent multiple side tabs for the same dock widget 2022-11-11 16:33:12 +01:00
Uwe Kindler
d010fe7a95 Fixed bug in AutoHidedockContainer that causes warnings and resizing issues
The bug caused ""setGeometry: Unable to set geometry XxY+Width+Height on QWidgetWindow/'WidgetClassWindow" warnings for OpenGL and QAxWidgets and causes resizing issues for AutoHideDockContainers that contained theses widgets
2022-11-11 15:29:12 +01:00
Uwe Kindler
8e7b7f536e Fixed CAutoHideDockContainer::addDockWidget to prevent OldDockArea->removeDockWidget(DockWidget) call when restoring state 2022-11-09 11:15:42 +01:00
Uwe Kindler
38dfd519c9 Merge branch 'master' into auto_hide_feature 2022-11-08 22:25:08 +01:00
Uwe Kindler
4600af712b Moved Alternative Dock System implementation to the end of README.md 2022-11-08 22:17:59 +01:00
Uwe Kindler
21d8a3dcdb Removed developers section in README.md 2022-11-08 22:10:24 +01:00
Uwe Kindler
0c9773ab54 Added dockingpanes docking library to alternative docking systems 2022-11-08 22:06:49 +01:00
Uwe Kindler
65a645b2cc Merge branch 'master' of https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System 2022-11-08 21:41:20 +01:00
Uwe Kindler
a61d5bd8c0 Updated Python binding documentation with new PySide6 bindings 2022-11-08 21:40:39 +01:00
Uwe Kindler
c646d13b14 Updated ads_logo.svg to fix size for mobile page 2022-11-08 21:12:56 +01:00
Uwe Kindler
f132255492 Added app icon for demo app 2022-11-08 20:38:51 +01:00
Uwe Kindler
208c804db1 User rootSplitter() function instead of searching for child widget 2022-11-08 20:37:48 +01:00
Uwe Kindler
89cca4c36a Reverted file version change for saved state data because the file is backward compatible 2022-11-08 16:33:13 +01:00
Uwe Kindler
64bd9021d9 Fixed bug in dropIntoSection() caused by the addition of AutoHideSideBars to dock container 2022-11-08 16:32:35 +01:00
Uwe Kindler
5a9f23a9ad Fixed emission of top level event in DockContainerWidget 2022-11-07 16:28:27 +01:00
Uwe Kindler
0073870480 Added documentation for Auto-Hide feature 2022-11-07 14:36:19 +01:00
Uwe Kindler
6cdea82a40 Fixed wrong image filename in demo application 2022-11-07 10:15:39 +01:00
Uwe Kindler
95b627e83e Prevent accidental hiding collapsing of an auto hide widget by a mouse click shortly after a mouse over collapse event 2022-11-07 10:15:14 +01:00
Uwe Kindler
2569e0aa05 Dynamically created image viewer now loads random image in demo 2022-11-07 09:50:28 +01:00
Uwe Kindler
be86a772ce Implemented custom close handling for dynamically created image viewers 2022-11-07 08:19:00 +01:00
Uwe Kindler
eda610409a Added actions to demo applications to create floating, docked and auto hide image viewers 2022-11-07 08:11:50 +01:00
Uwe Kindler
44a5873415 Fixed emission of missing top level event when redocking a auto hide widget 2022-11-07 08:11:00 +01:00
Uwe Kindler
e1368be645 Added missing render widget to demo application 2022-11-05 10:14:40 +01:00
Uwe Kindler
1b2b90396a Auto Hide Tab now shows text as tooltip - for icon only buttons to help the user 2022-11-05 10:14:01 +01:00
Uwe Kindler
bd0b2ad483 Improved title bar button tooltips and made naming consistend with context menu 2022-11-05 10:11:09 +01:00
Uwe Kindler
9c537340c5 Added a small image viewer to the demo application 2022-11-04 20:14:04 +01:00
Uwe Kindler
1bf698478d Added feature to apply a Visual Studio like light theme via ToolBar 2022-11-04 13:44:30 +01:00
Uwe Kindler
a79abbdb48 Fixed hiding of sidebar if Auto Hide Tab is closed 2022-11-04 13:43:59 +01:00
Uwe Kindler
a8783084f9 Merge branch 'auto_hide_feature' of https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System into auto_hide_feature 2022-11-04 12:11:00 +01:00
Uwe Kindler
3f11f74324 Some cleanup 2022-11-04 12:10:52 +01:00
Uwe
99854f686e Update linux stylesheet files to support icon only auto hide sidebars 2022-11-04 11:24:15 +01:00
Uwe Kindler
35f212a788 Fixed Qt6 build 2022-11-04 10:45:09 +01:00
Uwe Kindler
32eaf93692 Removed some whitespace from focus_highlighting.css 2022-11-04 10:23:40 +01:00
Uwe Kindler
6f5e33a2ad Added CSS styling for AutoHideTab that is iconOnly 2022-11-04 10:22:10 +01:00
Uwe Kindler
279a9d7df9 Fixed delayed hiding of CAutoHideDockContainer on mouse leave when resizing 2022-11-04 09:41:00 +01:00
Uwe Kindler
c0247fc02a Added option ShowAutoHideOnMouseOver that enables showing of auto hide widgets by hovering over auto hide tab 2022-11-04 08:51:17 +01:00
Uwe Kindler
27d71eecac Fixed restoreDockWidgetsOpenState() function to delete legacy auto hide widgets 2022-11-03 20:00:03 +01:00
Uwe Kindler
5e59a6dc3a Removed debug output 2022-11-03 16:49:20 +01:00
Uwe Kindler
409d4489cc Added support for auto hiding a dock area / widget to a specific border via context menu 2022-11-03 16:44:40 +01:00
Uwe Kindler
04ea1c68a7 Added option to auto hide a DockWidget or a DockArea to a specific sidebar location 2022-11-03 15:28:01 +01:00
Uwe
1922395b4b Improved linux auto hide specific css code 2022-11-03 12:00:52 +01:00
Uwe Kindler
3b97fdc2ce Improved AutoHideSidebar to provide better resize behavior if parent widget is resized 2022-11-03 11:34:04 +01:00
Uwe Kindler
716207f600 Removed superfluous deleteAutoHideWidgets() function from CDockContainerWidget 2022-11-02 14:41:41 +01:00
Uwe Kindler
159579fb48 Fixed some auto hide specific bugs 2022-11-02 14:29:23 +01:00
Uwe Kindler
d2c08aca70 Improved context menu of DockAreaWidget 2022-11-02 13:06:42 +01:00
Uwe Kindler
b5a179555a Added context menu actions for titleBar and dock widget tab auto hide 2022-11-02 12:45:45 +01:00
Uwe Kindler
9c14c62637 Added setAutoHide() and toggleAutoHide() function to CDockWidget 2022-11-02 08:27:23 +01:00
Uwe Kindler
7c1d04f7be Move calculateSideTabBarArea() function from DockContainerWidget into DockAreaWidget because it is only required there and it depends on dock area position 2022-11-02 08:16:56 +01:00
Uwe Kindler
9f153af5bb Changed MainWindow to enable ActiveX only for non opaque configuration and if AutoHide is disabled 2022-11-02 08:08:44 +01:00
Uwe Kindler
7d79ea2770 Fixed crash by access to invalid dock parent container in CAutoHideDockContainer::updateSize() function 2022-11-02 07:46:02 +01:00
Uwe Kindler
983afc4d1e Fixed wrong size calculation in CAutoHideDockContainer updateSize() function 2022-11-02 07:29:45 +01:00
Uwe Kindler
540961b8dd Renamed toggleAutoHide to setAutoHide and added toggleAutoHide function 2022-11-01 21:31:27 +01:00
Uwe Kindler
fda5887d50 Removed AutoHideInsertOrder enum - new side tabs are always appended. 2022-11-01 20:42:52 +01:00
githubuser0xFFFF
22f609cfa6 Fixed README.md 2022-11-01 19:40:49 +01:00
Uwe Kindler
0d78303713 Fixed typo 2022-11-01 17:41:47 +01:00
Uwe Kindler
fbd25a83f1 Improved auto hide config flags 2022-11-01 17:31:47 +01:00
Uwe Kindler
28745fa2f8 Some small improvements and execute auto hide code only if config is enabled 2022-11-01 17:17:58 +01:00
Uwe Kindler
8e46431b35 Merge branch 'master' into auto_hide_feature 2022-11-01 16:51:17 +01:00
Uwe Kindler
225b1ff2bb Fixed original repository link in README.md 2022-11-01 16:12:42 +01:00
Uwe Kindler
08714ddc3f Properly evaluate pinnable flag 2022-11-01 16:11:45 +01:00
Uwe Kindler
94b80423d7 Made naming of auto hide config flags explicit 2022-11-01 14:36:09 +01:00
Uwe Kindler
bfad80c540 Some code cleanup 2022-11-01 13:41:36 +01:00
Uwe Kindler
da6bf2b9ab Fixed typo 2022-11-01 13:36:32 +01:00
Uwe Kindler
075ef6187f Refactoring: renamed CDockWidgetSideTab to CAutoHideTab and CSideTabBar top CAutoHideSideBar 2022-11-01 13:34:08 +01:00
Uwe Kindler
782af9a1fc Renamed SideTabBar and DockWidgetSideTab into AutoHideSideBar and AutoHideTab for consistent naming 2022-11-01 12:06:59 +01:00
Uwe Kindler
2370d79ca6 Removed debug code from DockManager saveState function 2022-11-01 11:39:34 +01:00
Uwe Kindler
760c0365e0 Use explicit naming for functions to configure auto hide flags and disable auto hide feature by default 2022-11-01 11:35:07 +01:00
Uwe Kindler
fba9c7ce5d Create auto hide sidebars only if config flag is set 2022-11-01 11:22:15 +01:00
Uwe Kindler
44790307d8 Properly implemented restore functionality for auto hide container 2022-11-01 11:02:01 +01:00
Uwe Kindler
d1d801cf16 Moved dock area restore code into CDockAreaWidget 2022-10-30 19:44:33 +01:00
Uwe Kindler
8d670577a9 Moved creation of SideTabWidget into AutoHideDockContainer.cpp 2022-10-28 16:28:23 +02:00
Uwe Kindler
af4a3ef2a8 Removed config flag CDockManager::AutoHideDockAreaHasTitle - this should not be configurable 2022-10-28 15:52:52 +02:00
Uwe
1189945ef1 Updated Linux css files to properly support new auto hide feature 2022-10-28 15:21:21 +02:00
Uwe
f4bfa0f3c5 Changed type of sideTabBarArea properties to int to fix non working Linux stylesheet selectors 2022-10-28 15:20:56 +02:00
Uwe
6adce7337b Some restructuring in default.css and default_linux.css to improve readibility 2022-10-28 13:35:52 +02:00
Uwe Kindler
1eaeed6c56 Changed root index of file system model to prevent lagging UI if network folders are missing 2022-10-28 13:20:27 +02:00
Uwe Kindler
ae5a75bc3f Removed DockWidget->sideTabWidget()->setProperty("focused", Focused), DockWidget->sideTabWidget()->updateStyle() because it is not required 2022-10-28 13:19:38 +02:00
Uwe Kindler
b70fc7b3e8 Added some SideBar documentation 2022-10-28 11:22:42 +02:00
Uwe Kindler
38ee87f762 Merge branch 'duerr-ndt-auto_hide_feature' into auto_hide_feature_refactor 2022-10-28 11:17:13 +02:00
Uwe Kindler
b85a6b55d9 Removed debug output 2022-10-28 11:14:04 +02:00
Uwe Kindler
6cf05c3438 Removed debug output 2022-10-28 11:13:18 +02:00
Uwe Kindler
f6b77f5c3c Implemented showing and hiding of side bar when it does not contain any visible tab 2022-10-28 11:11:35 +02:00
Syarif Fakhri
a012426f9b cleanup - remove unused code, fix comments, add const 2022-10-28 14:26:55 +08:00
Syarif Fakhri
ee2ef8ac69 Use resize margin - disallow users from resizing to the size of the parent container 2022-10-28 14:24:44 +08:00
Syarif Fakhri
2a97833d02 fix cmakelists and remove setDefaultDockProportion from dock widget 2022-10-28 14:21:12 +08:00
Syarif Fakhri
c2bd56e2e9 add set size to allow the user to set a size for the pinned widget manually 2022-10-28 14:20:30 +08:00
Syarif Fakhri
85da93c2fe fix crash when adding auto hide dock container without a previous dock area 2022-10-28 14:19:12 +08:00
Uwe Kindler
c80174e7e5 Removed superfluous code and simplified some things 2022-10-27 15:59:08 +02:00
Uwe Kindler
3f256f7249 Some small renamings 2022-10-27 13:39:00 +02:00
Uwe Kindler
85d7b3047c Changed AutoHide save and restore code 2022-10-27 13:25:40 +02:00
Uwe Kindler
2d67e9e1e5 Some small changes 2022-10-27 11:53:15 +02:00
Uwe Kindler
da9062ef62 Fixed wrong rendering of DockWidgetSideTab if orientation changed when loading perspective 2022-10-27 10:56:42 +02:00
Uwe Kindler
f20c3bc63a Fixed wrong position of AutoHideDockContainer when uncollapsing 2022-10-27 10:52:05 +02:00
Uwe Kindler
11223bf664 Prevent deletion of DockWidgetSideTabs if SideTabBar is deleted - the DockWidget is the real owner 2022-10-27 10:23:11 +02:00
Uwe Kindler
c94155fb06 Moved SideBarLocation enum out of CDockWidgetSideTab into global ads namespace 2022-10-27 10:22:28 +02:00
Uwe Kindler
822ad48152 Code cleanup 2022-10-26 15:40:35 +02:00
Uwe Kindler
ea8e442153 Updated default.css to support the new auto hide functionality 2022-10-26 15:36:17 +02:00
Uwe Kindler
eb008be404 Cleanup of focus_highlighting.css 2022-10-26 15:14:32 +02:00
Uwe Kindler
f5ac29c19e Implemented support for Opaque / Non Opaque auto hide container resizing 2022-10-26 15:06:23 +02:00
Uwe Kindler
f22d62a85b Implemented non opaque resizing for ResizeHandle 2022-10-26 14:35:11 +02:00
Uwe Kindler
5199fa45d1 Implemented save and restore function in AutoHideDockContainer 2022-10-26 11:17:05 +02:00
Uwe Kindler
b2399bb279 Removed superfluous code from AutoHideDockContainer.cpp 2022-10-26 10:57:50 +02:00
Uwe Kindler
b14d3ff30f Added auto hide styling to focus_highlighting.css 2022-10-26 09:51:58 +02:00
Uwe Kindler
b43770de37 Added properties to auto hide widgets to improve CSS styling options 2022-10-26 09:51:37 +02:00
Uwe Kindler
875a358600 Ensure the SideTab is hidden if empty 2022-10-26 09:50:16 +02:00
Uwe Kindler
cd58e6e9b5 Reverted stylesheets to initial code to restart with styling 2022-10-26 07:29:58 +02:00
Uwe Kindler
43c8d69281 Restored initial implementation of ElidingLabel because vertical label is not required anymore - SideBarButton implements orientation feature 2022-10-26 07:28:58 +02:00
Uwe Kindler
293bf9b74f Updated stylesheet to default 2022-10-25 21:10:20 +02:00
Uwe Kindler
00e4dc14ba fixed some documentation typos 2022-10-25 19:57:40 +02:00
Uwe Kindler
8ef696f6f2 Updated README.md 2022-10-25 19:49:36 +02:00
Uwe Kindler
c3aefff3b4 Added missing exports for ResizeHandle and PushButton 2022-10-25 16:05:08 +02:00
Uwe Kindler
44bfc56471 Removed superfluous function setDockSizeProportion() 2022-10-25 15:58:47 +02:00
Uwe Kindler
a74d8acb42 Improved visual_studio_light.css 2022-10-25 15:51:38 +02:00
Syarif Fakhri
fafa52a1ba fix bug where "right click -> detach group" would of an overlay dock would not remove the dockwidget side tab 2022-10-25 18:03:41 +08:00
Syarif Fakhri
54c7c7e2a5 iconsize -> iconSize in css 2022-10-25 18:00:36 +08:00
Syarif Fakhri
314ed4bbf2 fix missing case statement 2022-10-25 17:37:54 +08:00
Uwe Kindler
0fbbef7609 Fixed initial size of AutoHideDockContainer 2022-10-25 11:09:13 +02:00
Uwe Kindler
6eb46250b1 Improved visual_studio_light.css theme 2022-10-25 10:59:01 +02:00
Uwe Kindler
14acd0fe4a Fixed updateResizeHandleSizeLimitMax() function to work properly with all dock containers 2022-10-25 10:01:51 +02:00
Uwe Kindler
7774aaa75a Fixed calculateSideTabBarArea function to work properly with every dock container 2022-10-25 09:58:15 +02:00
Uwe Kindler
ebdd950b4e Removed supefluous onAutoHideToggleRequested() function 2022-10-25 09:52:57 +02:00
Uwe Kindler
8e8ead0b4f Improved visual_studio_light.css 2022-10-25 09:11:10 +02:00
Uwe Kindler
ff0b32a8e0 Added new Visual Studio Light theme 2022-10-24 20:34:09 +02:00
Uwe Kindler
f549a92c01 Added resize support for new QFrame based AutoHideDockContainer 2022-10-24 16:21:26 +02:00
Uwe Kindler
93d0d4b1c2 Merge branch 'master' into auto_hide_dockcontainer 2022-10-24 09:21:30 +02:00
Uwe Kindler
b6d7f868ac Improved showcase section in README.md 2022-10-23 20:18:01 +02:00
Uwe Kindler
bc1f12ba93 Implemented experimental mouse event handling 2022-10-23 16:42:14 +02:00
tytan652
537828ef3d Allow to set a custom title for all FloatingContainer (#454) 2022-10-20 21:35:31 +02:00
Chnossos
6444e7424f fix: DockFocusController doesn't pick up on previous dock deletion outside of view (#453)
Co-authored-by: Pierre Caissial <pierre.caissial@vivoka.com>
2022-10-19 20:39:19 +02:00
Syarif Fakhri
10a75b0413 remove unused and cleanup 2022-10-19 17:44:55 +08:00
Syarif Fakhri
9eb9ee4071 fix icon only config for side tab bars 2022-10-19 17:35:36 +08:00
Syarif Fakhri
7ed3f8b2d1 Remove all dock widget focusable constraint on auto hide button 2022-10-19 17:30:08 +08:00
Syarif Fakhri
7319c52d4d FIxed CMakeLists 2022-10-19 17:13:34 +08:00
Syarif Fakhri
8974b1a299 Merge branch 'auto_hide_feature_original_f' into auto_hide_feature 2022-10-19 17:11:45 +08:00
Uwe Kindler
63fed89f26 Removed individual config flags for each sidebar with the global AutoHideFeatureEnabled flag 2022-10-18 17:00:42 +02:00
Uwe Kindler
866ccb2c4e Reimplemented DockWidgetSideTab based on QPushButton 2022-10-18 16:43:39 +02:00
Uwe Kindler
cbc43e5e0e Added PushButton to test new CDockWidgetSideTab 2022-10-18 15:47:34 +02:00
Uwe Kindler
3a3c3a96d6 Fixed namespace comment in ElidingLabel 2022-10-18 15:46:53 +02:00
Uwe Kindler
0cbc810a5a Renamed SideTabIconLabel - added C prefix CSideTabIconLabel 2022-10-18 15:29:31 +02:00
Syarif Fakhri
d83ec7c66f Add config to make auto hide button optionally checkable for styling purposes 2022-10-18 17:21:10 +08:00
Syarif Fakhri
118e79e7ec Remove config flag 2022-10-18 10:33:35 +08:00
Syarif Fakhri
1c69685257 Update css 2022-10-18 10:33:03 +08:00
Syarif Fakhri
fde8007174 reduce margin a little bit for the horizontal component 2022-10-18 10:22:56 +08:00
Uwe Kindler
60e0201060 Added new auto hide config flag CDockManager::AutoHideButtonTogglesArea 2022-10-17 18:16:20 +02:00
Uwe Kindler
90b92900a1 Move autohide related CSS into a separate block to have all settings in one place 2022-10-17 17:41:56 +02:00
Uwe Kindler
96a5443a02 Added alternative auto hide button svg icon and modified stylesheet to show pinned icon for autohide widgets 2022-10-17 14:52:53 +02:00
Uwe Kindler
ffe6eccb05 Improved logic for finding the auto hide side location 2022-10-17 14:22:12 +02:00
Uwe Kindler
14312442db Replaced tab bar areas LeftTop, LeftBottom, RightTop, RightBottom with Left and Right to reduce complexity 2022-10-17 11:34:59 +02:00
Uwe Kindler
bb630ca605 Changed toggleAutoHideArea)= logic - only the current dock widget is pinned and not all dock widgets of this area 2022-10-17 09:59:40 +02:00
Uwe Kindler
e3117121cc Changed moveContentsToParent() logic when disabling auto dock for a certain widget 2022-10-17 09:52:00 +02:00
Uwe Kindler
a8a40f0bee Merge branch 'duerr-ndt-auto_hide_feature' into auto_hide_feature 2022-10-17 08:54:17 +02:00
Uwe Kindler
9f9d9792aa Added sideTabBarArea property to CAutoHideDockContainer to improve CSS styling options 2022-10-15 14:24:19 +02:00
Syarif Fakhri
4399f6ea29 Update css 2022-10-14 21:49:53 +08:00
Syarif Fakhri
754a41d118 Formatting and cleanup
- Update user-guide.md
- Remove incorrect configuration from dock manager.h
- Fix spacing
2022-10-14 21:41:39 +08:00
Syarif Fakhri
b0544be068 Added activeTab property 2022-10-14 21:32:05 +08:00
Syarif Fakhri
f9b62234b0 Add top area 2022-10-14 21:13:32 +08:00
Syarif Fakhri
ac8cf863a0 remove unused css 2022-10-14 21:07:58 +08:00
Syarif Fakhri
91190e8744 cleaner dock widget side tab click handling 2022-10-14 17:47:41 +08:00
Syarif Fakhri
efb87c868b update size then mask 2022-10-14 16:20:32 +08:00
Syarif Fakhri
ad0c2103bf fix crash when using widgets that delete on close 2022-10-14 16:09:13 +08:00
Syarif Fakhri
5b3ad7e5db fix typo 2022-10-13 15:41:15 +08:00
Syarif Fakhri
589a62fe15 update user guide 2022-10-13 15:24:11 +08:00
Syarif Fakhri
b51c56e286 Fix bug where left and bottom overlay splitters cannot be clicked 2022-10-13 14:56:25 +08:00
Syarif Fakhri
84ca7b18a0 fix side tab not hiding when double clicking dock title bar 2022-10-13 14:37:39 +08:00
Syarif Fakhri
8610a64b51 Rename overlayDockContainer -> AutoHideDockContainer 2022-10-13 14:26:54 +08:00
Syarif Fakhri
ae55013566 Merge branch 'auto_hide_feature' of github.com:githubuser0xFFFF/Qt-Advanced-Docking-System into auto_hide_feature 2022-10-13 11:11:58 +08:00
Uwe Kindler
60526f2293 Fixed some typos 2022-10-12 11:47:54 +02:00
Uwe Kindler
6c27115de8 Ignore MouseButtonPress events of SideTabWidget in event filter 2022-10-12 11:32:55 +02:00
Uwe Kindler
62d3d73651 Made Auto Hide Feature independent from Focus Feature and renamed OverlayDockContainer to AutoHideDockContainer 2022-10-12 11:17:54 +02:00
Uwe Kindler
8fc333806a Pulled latest changes from duer autohide branch 2022-10-12 10:58:47 +02:00
Syarif Fakhri
412f24537b Dissallow non focusable dock widgets from being pinned 2022-10-06 17:00:29 +08:00
Syarif Fakhri
a74e03451f remove unused vars 2022-10-03 17:46:07 +08:00
Syarif Fakhri
3cd0265df6 - Fix crash caused by not removing dock area from parent container
- Fix strange behavior caused by not calling QSplitter::resizeEvent base
implementation
2022-10-03 17:29:56 +08:00
Syarif Fakhri
53e8010732 Merge branch 'auto_hide_feature' of github.com:duerr-ndt/Qt-Advanced-Docking-System into auto_hide_feature 2022-09-22 10:41:27 +08:00
Syarif Fakhri
880a7f13b5 add config flag in ads demo 2022-09-22 10:40:11 +08:00
syarif fakhri
7f6fa0c96c Fix linux styling 2022-09-22 09:53:14 +08:00
Syarif Fakhri
8ac8d63b96 Ensure that the closed state is consistent 2022-09-20 14:47:28 +08:00
Syarif Fakhri
0e6971e2ae Remove [[fallthrough]] 2022-09-20 09:41:02 +08:00
Syarif Fakhri
32f9b4664b Fix weird behavior when widget is overlayed 2022-09-19 18:11:47 +08:00
Syarif Fakhri
b567f6c5d2 Add documentation 2022-09-19 16:34:21 +08:00
Syarif Fakhri
c850e36025 Update css for qt-5 2022-09-19 16:33:45 +08:00
Syarif Fakhri
2bb1589ca2 Add missing check for bottom sidebar config 2022-09-19 16:02:32 +08:00
Syarif Fakhri
40dccdb5ae Remove testing code 2022-09-19 14:30:18 +08:00
Syarif Fakhri
3d4d677494 Bump XML version 2022-09-19 14:30:07 +08:00
Syarif Fakhri
6e143de09d Fix side tab widgets being the wrong size when being added to a layout 2022-09-19 14:19:31 +08:00
Syarif Fakhri
ea0eac0e38 Fix autohide example 2022-09-19 11:01:49 +08:00
Syarif Fakhri
f69b1e1ef8 Fix active X widgets not being rendered correctly 2022-09-19 10:49:07 +08:00
Syarif Fakhri
87324846cd Fix side tab widget resizing strangely on first add 2022-09-15 16:02:55 +08:00
Syarif Fakhri
060313c11f clear dock widget focus on repin 2022-09-15 13:04:49 +08:00
Syarif Fakhri
59108ed245 Add right bottom and left bottom 2022-09-15 12:51:59 +08:00
Syarif Fakhri
68a3bcde08 Add assert 2022-09-15 12:15:33 +08:00
Syarif Fakhri
68e5aec912 add rais 2022-09-15 11:51:56 +08:00
Syarif Fakhri
6998c0e585 double -> float 2022-09-15 09:43:15 +08:00
Syarif Fakhri
4d3328e468 Fix side tab widget ordering
Now is fixed based on the side tab widget
2022-09-14 17:39:57 +08:00
Syarif Fakhri
06bcf2cd48 Add insert order for overlayed widget to the side tab bar
- Set the default insert order to append
2022-09-14 15:52:34 +08:00
Nick D'Ademo
5df2467592 add orientation prop to SideTabBar. 2022-09-14 14:25:11 +08:00
Nick D'Ademo
48163d2679 add paintEvent override for styling purposes. 2022-09-14 14:17:28 +08:00
Syarif Fakhri
f3305b95d2 Remove old crash fix 2022-09-14 13:10:06 +08:00
Syarif Fakhri
8e5e974669 Remove event filter from dock area as well 2022-09-14 12:39:18 +08:00
Syarif Fakhri
773f186a7f Fix crash when restoring state but better
- Rather than having to check for nullptr, just make sure the slot isn't
called
2022-09-14 12:34:13 +08:00
Syarif Fakhri
6b85b2b505 Revert "Fix crash when restoring state"
This reverts commit ee97b03e53.
2022-09-14 12:32:32 +08:00
Syarif Fakhri
ee97b03e53 Fix crash when restoring state
- when restoring state, the old dock widgets would remove themselves
from their old dock areas and add themselves to the new dock areas. The
old dock areas that are empty would then delete themselves.
- That is a problem when the old overlay dock container would still try to
access the old dock areas, not knowing their deleted, causing a crash.
2022-09-14 12:16:36 +08:00
Syarif Fakhri
0e5329fd3e add comment 2022-09-13 17:27:13 +08:00
Syarif Fakhri
ac311d6d45 Fix moving content to parent on toggle view 2022-09-13 17:26:46 +08:00
Syarif Fakhri
f0f3caeb32 tweak spacing 2022-09-13 16:51:15 +08:00
Syarif Fakhri
d394930d74 Change splitter proportion from int to double
- Allows for fine grain control (can now set 0.75 or 0.6)
- Makes more sense
2022-09-13 16:29:39 +08:00
Syarif Fakhri
19192541f9 Fix central dock widget being pinnable
- Add config for dock widget being pinnable
2022-09-13 16:19:11 +08:00
Syarif Fakhri
8ddabc4cc8 Fix docking behavior when there is a central widget 2022-09-13 16:02:14 +08:00
Syarif Fakhri
42498b2021 Fixed some more spacing in DockWidgetSideTab 2022-09-13 14:57:24 +08:00
Syarif Fakhri
daa52e109e Add missing update style to dock widget side tab 2022-09-13 14:21:01 +08:00
Syarif Fakhri
263c73188a Add bottom side icon config 2022-09-13 14:16:12 +08:00
Syarif Fakhri
9a69955124 Simplify logic when restoring state 2022-09-13 13:10:29 +08:00
Syarif Fakhri
b950b8a209 Fix overlayed containers able to drag into the center
of the central widget
2022-09-13 12:45:26 +08:00
Syarif Fakhri
dfc2714d3b Fix invalid state on restore
- Overlayed dock areas should not be added to the d->DockArea list
- As they are not treated like normal dock areas
2022-09-13 12:44:48 +08:00
Syarif Fakhri
4841d9b896 Set splitter sizes based on proportion settable in the dock widget 2022-09-13 11:20:46 +08:00
Syarif Fakhri
214c415fa2 Add Bottom side bar 2022-09-13 10:42:58 +08:00
Syarif Fakhri
489f72aa0c Add side tab widget icons
- Add config to prioritize icon only if it has one
2022-09-12 15:55:45 +08:00
Syarif Fakhri
883d5b5198 fix crash when sometimes restoring state 2022-09-09 15:38:31 +08:00
Syarif Fakhri
3ef1ac97c2 Fix splitter size being saved incorrectly if the overlay widget is never opened 2022-09-09 15:24:33 +08:00
Syarif Fakhri
621e5e7789 fix tooltips for auto hide button and close button 2022-09-09 14:43:59 +08:00
Syarif Fakhri
22402e79f5 Added support for delete on close to overlayed widgets 2022-09-09 13:57:43 +08:00
Syarif Fakhri
54b9a8dc50 Merge branch 'auto_hide_feature' of github.com:duerr-ndt/Qt-Advanced-Docking-System into auto_hide_feature 2022-09-09 13:37:14 +08:00
Syarif Fakhri
dc05ec3acf Add nullptr check when restoring state with overlayed widgets 2022-09-09 13:33:42 +08:00
Syarif Fakhri
84c6afa428 Reworked toggle view
Previous:
- It would just hide the overlay dock widget and leave the side tabs
still visible
- Close button, toggle view action would simply collapse the dock widget
intsead of completely hiding it

Current:
- Now toggle view and collapse functionality are separated.
- Toggle view will now hide the side tab bars completely
- Close button and toggle view action will completely hide it
- Collapse view will simply hide the overlay dock container without
hiding the side tabs
- Handled logic for floating widgets and toggling view
2022-09-09 12:18:41 +08:00
Nick D'Ademo
1097d65959 fix elision for vertical eliding label. 2022-09-09 09:34:45 +08:00
Syarif Fakhri
6ae14fada3 add comment regarding empty widget in overlay dock container 2022-09-08 17:42:24 +08:00
Syarif Fakhri
a2e9c1aa9c Add config flag for enabling the overlay dock area title
Changed the config name from DefaultDockContainerConfig->DefaultAutoHideConfig
2022-09-08 16:58:40 +08:00
Syarif Fakhri
60c22000a8 Add hover styling 2022-09-08 16:49:32 +08:00
Syarif Fakhri
3ec395fe79 update default stylesheet 2022-09-08 16:41:00 +08:00
Syarif Fakhri
fac81265bf Whitespace changes only 2022-09-08 16:30:07 +08:00
Syarif Fakhri
c1df05b55d Fix bug where undock button would be show incorrectly in floating dock
widgets when toggling overlay

Also centralized and simplified the logic for the title bar button
visibility
2022-09-08 16:08:20 +08:00
Syarif Fakhri
af549d8ca9 Add title label to the overlayed dock area 2022-09-08 14:43:18 +08:00
Syarif Fakhri
9bfd77a206 Remove None and Bottom from the SideTabBarArea enum 2022-09-08 14:13:45 +08:00
Syarif Fakhri
37edf47c4b Fix the side tab widget not updating style when its restored from XML 2022-09-08 14:04:18 +08:00
Syarif Fakhri
be4e5a88a6 Change the styling - Now the dock widget side tab has a gray left/right
edge border when not selected
2022-09-08 14:01:52 +08:00
Syarif Fakhri
a279e71535 Fix side tab bar area name being saved wrong in the XML 2022-09-08 13:10:46 +08:00
Syarif Fakhri
5ddb02cc8e fix the border styling of the dock widget side tab when not focused 2022-09-08 11:45:30 +08:00
Syarif Fakhri
ecccba4536 Add overlay splitter object name 2022-09-08 11:31:54 +08:00
Syarif Fakhri
0087a1b360 Add left right styling to the dock widget side tab 2022-09-08 11:30:56 +08:00
Syarif Fakhri
8bfb98ea20 Remove auto hide feature being set by default. Add config for the default auto hide feature. 2022-09-08 11:23:45 +08:00
Syarif Fakhri
de4a59d45a Re added back in CentralWidgetExample after mistakenly removing it 2022-09-08 11:18:38 +08:00
Uwe Kindler
068797dbb0 Fixed build issues of original pull request 2022-09-07 10:56:17 +02:00
Syarif Fakhri
302fcd1435 Fix bug where dragging an overlayed widget would cause it to be empty
Fix bug where pin and unpin doesn't work
2022-09-07 15:50:53 +08:00
Syarif Fakhri
1d9902b690 Make tabs menu hidden when overlayed 2022-09-07 13:31:44 +08:00
Syarif Fakhri
9735f41b1a Fix toggle view through the actions menu not working correctly 2022-09-07 12:13:46 +08:00
Syarif Fakhri
4a77580b07 swap position of auto hide button and detach group button 2022-09-07 11:54:32 +08:00
Syarif Fakhri
1a903e74f2 add pin icon 2022-09-07 11:54:03 +08:00
Syarif Fakhri
e4565034fb Merge branch 'master' into auto_hide_feature 2022-09-07 10:12:57 +08:00
Syarif Fakhri
052d3cecb9 Fix check state of the auto hide button
when dragging the container into a floating window
2022-09-06 17:59:56 +08:00
Syarif Fakhri
fde133c25e Fix a bug where overlay widgets from another container widget
would not be correctly transferred into the container widget that it's
dragged into.
2022-09-06 17:42:26 +08:00
Syarif Fakhri
6e35a9e7a7 - Add an example folder for auto hide functionality
Note: this does not include the py file, To be added in a different
commit
- Added a better API to programatically add the overlay areas in the
CDockManager
2022-09-06 15:35:18 +08:00
Syarif Fakhri
bfab7e495a Move logic for enabling auto hide into the public toggle method 2022-09-06 13:49:11 +08:00
Syarif Fakhri
3e9dc7f4d6 Add initial functionality for Auto hide
- Add left and right side tab widgets
- Add overlay dock and overlay dock widget behavior
2022-09-06 13:30:26 +08:00
Syarif Fakhri
da8f17cce2 Fix perspective for central widget demo 2022-09-05 17:04:41 +08:00
Uwe Kindler
3cd6d766f8 Added some documentation for Linux modal dialog fix 2022-09-05 09:06:29 +02:00
Uwe
82c98a3f91 Merge branch 'linux_modal_dialog_fix' 2022-09-05 09:02:02 +02:00
Uwe
c11a496278 Change to ensure that modal widgets are always on top of floating widgets 2022-09-05 09:01:40 +02:00
Uwe
d27783e2f1 Added check for model widget for Linux
Prevent painting of drop overlays when model widget is active
2022-09-02 14:54:48 +02:00
Uwe Kindler
efd88565a9 Small change to fix issue #445 2022-08-29 11:11:08 +02:00
Doug Smith
f3bb1b17d0 Add link to xcb on Linux (#446) 2022-08-29 08:20:47 +02:00
Sebastian Büttner
518cee9d0a Remove version check for qt 5.x to fix conan qt6 compatibility (#447)
Qt6 compatibility is broken in some cases when building with conan. This is due to the find_package version check against 5.5 rejecting the Qt6 version (e.g. 6.3.1).
This patch removed the version check.
2022-08-29 08:20:30 +02:00
Sebastian Büttner
6302ab03d8 Set required C++ standard depending on Qt version (#444)
Qt6 requires C++17 for building. ADS however only requires C++14 so far. Now when building using Conon for example the packages are built independently and ADS is built using the C++-14 flag which in turn causes the included Qt6 headers to fail the compile process. This patch bumps the required C++ standard to C++17 for builds targeting Qt6 only.
2022-08-14 22:17:42 +02:00
Uwe Kindler
2afca346b0 Added some info about PyQtAds contribution 2022-08-08 08:55:04 +02:00
Uwe Kindler
89ff0ad311 Added PRE Workbench to Showcase section 2022-07-29 13:57:08 +02:00
Uwe Kindler
6caeac2cb4 Merge branch 'master' of https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System 2022-07-29 13:26:23 +02:00
Uwe Kindler
a0f0640c9f Fixed CustomCloseHandling for floating widgets 2022-07-29 13:25:14 +02:00
Mira Weller
d3f5879119 upgrade PyQt build (#404)
* Add new flags from 3.7 and 3.8

* remove unnecessarily deep namespace for Python module

* Update PyQt5 bindings build to new build system

* fix opening tabbed dockWidgets

* fix RESOURCES configuration for sip build

* increment build version

* remove leftovers

* add file names explicitly

* Update pyproject.toml
2022-07-19 13:17:45 +02:00
bjb-work
df74686287 call CDockWidget::closeDockWidgetInternal when close attempt and CustomCloseHandling (#438)
Co-authored-by: bjb-work <N/A>
2022-07-15 14:47:20 +02:00
Uwe Kindler
75d58b3ea3 Fixed #433 - Link issue of debug library with MSVC19 2022-07-04 07:41:26 +02:00
Uwe Kindler
bedd25021c Fixed issue #429 - Raise floating widget on toggleView() request 2022-06-17 08:31:24 +02:00
Uwe Kindler
0e566cb8a3 Fixed #420 - Floating docks title doesn't update
added tests for DockWidget->setWindowTitle() in demo application
2022-05-10 13:41:19 +02:00
Mira Weller
23f80334f6 Fix issue #415 (#416) 2022-05-03 08:47:31 +02:00
Uwe Kindler
7063909cee Added MetGem to showcase section 2022-04-21 16:29:55 +02:00
Igor Sirotin
a284e3bd65 CMake bugfixes [target alias, license install] (#412)
* Added alias to cmake library target

* Fixed CMake license install

Co-authored-by: Igor Sirotin <i.sirotin@1440.space>
2022-04-18 23:07:48 +02:00
ARSanderson
823887daf8 Tidy/doc updates (#410)
* minor updates to clarify when the dock manager should be created

* fixed typos
2022-04-12 07:58:18 +02:00
Uwe Kindler
78a4166e42 Updated CFloatingDockContainer::closeEvent() function to delete all dock widgets with DockWidgetDeleteOnClose flag set 2022-03-25 13:31:40 +01:00
tytan652
3d3b694040 Avoid calling XCB functions under non-XCB Linux platform (#405) 2022-03-24 19:43:39 +01:00
ruffianhy
ad06241c9d fix(issue-350): on RedHat/CentOS, sometimes there will be one more move event after user release their mouse which will cause the floating overlay can not be hide. Here we use the WindowActivate and WindowDeactivate event to check whether user release their mouse. (#401) 2022-03-13 21:22:07 +01:00
Uwe Kindler
6a1ea6c7de Fixed examples/sidebar bug 2022-03-04 13:43:21 +01:00
Uwe Kindler
931719c474 Updated README.md 2022-03-04 08:04:21 +01:00
Uwe Kindler
70ef00932a Updated marketplace description 2022-03-02 11:52:38 +01:00
Uwe Kindler
a1bc4a063b Updated qt_markectplace files 2022-03-02 11:48:51 +01:00
Uwe Kindler
abf7224582 Updated ads logo and icon 2022-03-02 11:31:25 +01:00
Uwe Kindler
7ab4c9af2e Handle StyleChange event in DockWidgetTab to update icon 2022-02-25 21:41:46 +01:00
kzl
d5fefaa35f while dockManager.removeDockWidget , the dockManager() returns null (#399) 2022-02-18 19:33:55 +01:00
Ben Hetherington
3c4af9c6af Add method to add dock widget to dock container (#398)
This adds a `addDockWidgetToContainer()` method to `CDockManager`, which allows a dock widget to be registered with the dock manager, and added to a specific container, even if that container doesn't currently have any `DockAreaWidget`s.

This is pretty much just a clone of `addDockWidget()`, but with the ability to specify a container widget instead of a dock area.
2022-02-06 08:21:43 +01:00
githubuser0xFFFF
12ec819aeb Update README.md
Updated CETONI Elements showcase
2022-01-02 21:55:00 +01:00
Uwe Kindler
e6fc1c14bd Added NotepadNext to the showcase section 2021-12-22 07:47:24 +01:00
SleepProgger
6fb45c055c Removed ContentMargin in DockContainer (#387) 2021-12-20 07:46:26 +01:00
Ralph Minderhoud
535b926095 CMake: Allow version to be explicitly set without requiring git (#384)
The main CMakeLists.txt was updated to allow explicitly setting the
version for the project by setting the `ADS_VERSION` variable (e.g.
cmake .. -DADS_VERSION=1.0.0).

The default behavior is to determine the version by reading the
information from git. Adding the option to override this variable at
configure time allows the library to be built outside of its git
repository, such as when the code is vendored directly into another
project and added using `add_subdirectory`.
2021-12-13 08:36:53 +01:00
Uwe Kindler
b15bc26a63 Some small coding style fixes 2021-12-12 17:28:11 +01:00
Uwe Kindler
1d90e8e823 Merge branch 'fix_issue_380' of https://github.com/jporcher/Qt-Advanced-Docking-System into jporcher-fix_issue_380 2021-12-12 17:19:27 +01:00
Jean Porcherot
6b3027401d Fix issue #380 and add example 2021-12-09 10:11:05 +01:00
githubuser0xFFFF
e35bd65a91 Update README.md 2021-12-07 11:01:26 +01:00
githubuser0xFFFF
8888f6800b Update README.md 2021-12-07 11:00:52 +01:00
Uwe Kindler
2afe62ec77 Fixed issue #378 - Don't show empty floating containers on startup 2021-12-06 09:42:12 +01:00
jporcher
4b27af959b Merge branch 'githubuser0xFFFF:master' into master 2021-12-06 07:57:29 +01:00
Ben Hetherington
0df1a41a1d Fix potential crash when restoring container state (#381)
This fixes a crash which could occur when restoring the state of a floating container to a non-floating container.

This was because `ads::CDockContainerWidget::RestoreState()` will unconditionally assume this is floating if the XML has the `Floating` boolean set, and will dereference `floatingWidget()`. If this isn't floating, `floatingWidget()` will return `nullptr`, leading to a crash when it's subsequently used.

Fixes #379.
2021-12-03 17:01:16 +01:00
anoy
21badd592e add QFlag operators (#376) 2021-11-26 19:09:09 +01:00
Uwe Kindler
a110d53a53 Fixed crash in DockFocusController
DockWidget pointers are now wrapped into QPointer to detect deleted
DockWidgets
2021-11-18 22:10:11 +01:00
Uwe Kindler
0270993782 Fixed error caused by broken merge request 2021-11-17 07:51:14 +01:00
Uwe Kindler
2c0d899b2a Fixed pixmap warning in ElidingLabel 2021-11-17 07:50:46 +01:00
Ben Hetherington
1abe101ef7 Prevent middle-click from closing unclosable tabs (#372)
This fixes a bug whereby you could close a dock widget by middle-clicking its tab, even if its `CDockWidget::DockWidgetClosable` flag is set to `false`.
2021-11-16 06:24:39 +01:00
Uwe Kindler
0ebc170cfa Fixed doc link to issue 365 2021-10-29 10:36:09 +02:00
Uwe Kindler
ee6ddfadc3 Documented DockWidget feature flags 2021-10-29 10:32:58 +02:00
Uwe Kindler
720b5f0c72 Added Plot Juggler to the showcase section 2021-10-29 10:02:09 +02:00
Uwe Kindler
aceabd8455 Added new and noteworthy for 3.8 release 2021-10-28 10:30:49 +02:00
Jean Porcherot
d0c100995e Fix crash when dockindock example is closed. Due to code in dockindock supposed to fix memory leaks: now leaks were fixed in CDockManager (https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/307), the code from dockindock ends up deleting objects already deleted by parent. 2021-04-27 10:05:07 +02:00
Jean Porcherot
f54e4c8ac2 Merge remote-tracking branch 'upstream/master' 2021-04-27 09:12:56 +02:00
Jean Porcherot
2c7b5982b5 Replace dockdepth1 by dockindock 2021-04-14 15:36:00 +02:00
Jean Porcherot
bac0698581 Fix compilation (include assert.h) 2021-04-09 13:36:51 +02:00
Jean Porcherot
be3180df6f Add dockdepth1 example 2021-04-07 16:51:46 +02:00
129 changed files with 8524 additions and 1203 deletions

View File

@@ -1,20 +1,41 @@
cmake_minimum_required(VERSION 3.5)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
include(GetGitRevisionDescription)
git_describe(GitTagVersion --tags)
string(REGEX REPLACE "^([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GitTagVersion}")
string(REGEX REPLACE "^[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GitTagVersion}")
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GitTagVersion}")
set(VERSION_SHORT "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
# By default, the version information is extracted from the git index. However,
# we can override this behavior by explicitly setting ADS_VERSION and
# skipping the git checks. This is useful for cases where this project is being
# used independently of its original git repo (e.g. vendored in another project)
if(NOT ADS_VERSION)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
include(GetGitRevisionDescription)
git_describe(GitTagVersion --tags)
string(REGEX REPLACE "^([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GitTagVersion}")
string(REGEX REPLACE "^[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GitTagVersion}")
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GitTagVersion}")
set(VERSION_SHORT "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
else()
string(REGEX MATCHALL "[\.]" VERSION_DOT_MATCHES ${ADS_VERSION})
list(LENGTH VERSION_DOT_MATCHES VERSION_DOT_COUNT)
if(VERSION_DOT_COUNT EQUAL 2)
set(VERSION_SHORT ${ADS_VERSION})
else()
message(FATAL_ERROR "ADS_VERSION must be in major.minor.patch format, e.g. 3.8.1. Got ${ADS_VERSION}")
endif()
endif()
project(QtADS LANGUAGES CXX VERSION ${VERSION_SHORT})
option(BUILD_STATIC "Build the static library" OFF)
option(BUILD_EXAMPLES "Build the examples" ON)
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
set(ads_PlatformDir "x86")
else()
set(ads_PlatformDir "x64")
endif()
add_subdirectory(src)
if(BUILD_EXAMPLES)
add_subdirectory(examples)
add_subdirectory(demo)

View File

@@ -1,10 +0,0 @@
from .ads import ads
from .._version import *
import inspect
for name, member in inspect.getmembers(ads):
if not name.startswith('_'):
globals()[name] = member
del ads

View File

@@ -1,9 +0,0 @@
from .rc import *
from ._version import get_versions
__version__ = get_versions()['version']
short_version = __version__
version = __version__
full_version = __version__
git_revision = get_versions()['full-revisionid']
release = not get_versions()['dirty']
del get_versions

View File

@@ -1,520 +0,0 @@
# This file helps to compute a version number in source trees obtained from
# git-archive tarball (such as those provided by githubs download-from-tag
# feature). Distribution tarballs (built by setup.py sdist) and build
# directories (produced by setup.py build) will contain a much shorter file
# that just contains the computed version number.
# This file is released into the public domain. Generated by
# versioneer-0.18 (https://github.com/warner/python-versioneer)
"""Git implementation of _version.py."""
import errno
import os
import re
import subprocess
import sys
def get_keywords():
"""Get the keywords needed to look up the version information."""
# these strings will be replaced by git during git-archive.
# setup.py/versioneer.py will grep for the variable names, so they must
# each be defined on a line of their own. _version.py will just call
# get_keywords().
git_refnames = "$Format:%d$"
git_full = "$Format:%H$"
git_date = "$Format:%ci$"
keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
return keywords
class VersioneerConfig:
"""Container for Versioneer configuration parameters."""
def get_config():
"""Create, populate and return the VersioneerConfig() object."""
# these strings are filled in when 'setup.py versioneer' creates
# _version.py
cfg = VersioneerConfig()
cfg.VCS = "git"
cfg.style = "pep440"
cfg.tag_prefix = ""
cfg.parentdir_prefix = "None"
cfg.versionfile_source = "PyQtAds/_version.py"
cfg.verbose = False
return cfg
class NotThisMethod(Exception):
"""Exception raised if a method is not valid for the current scenario."""
LONG_VERSION_PY = {}
HANDLERS = {}
def register_vcs_handler(vcs, method): # decorator
"""Create decorator to mark a method as the handler of a VCS."""
def decorate(f):
"""Store f in HANDLERS[vcs][method]."""
if vcs not in HANDLERS:
HANDLERS[vcs] = {}
HANDLERS[vcs][method] = f
return f
return decorate
def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
env=None):
"""Call the given command(s)."""
assert isinstance(commands, list)
p = None
for c in commands:
try:
dispcmd = str([c] + args)
# remember shell=False, so use git.cmd on windows, not just git
p = subprocess.Popen([c] + args, cwd=cwd, env=env,
stdout=subprocess.PIPE,
stderr=(subprocess.PIPE if hide_stderr
else None))
break
except EnvironmentError:
e = sys.exc_info()[1]
if e.errno == errno.ENOENT:
continue
if verbose:
print("unable to run %s" % dispcmd)
print(e)
return None, None
else:
if verbose:
print("unable to find command, tried %s" % (commands,))
return None, None
stdout = p.communicate()[0].strip()
if sys.version_info[0] >= 3:
stdout = stdout.decode()
if p.returncode != 0:
if verbose:
print("unable to run %s (error)" % dispcmd)
print("stdout was %s" % stdout)
return None, p.returncode
return stdout, p.returncode
def versions_from_parentdir(parentdir_prefix, root, verbose):
"""Try to determine the version from the parent directory name.
Source tarballs conventionally unpack into a directory that includes both
the project name and a version string. We will also support searching up
two directory levels for an appropriately named parent directory
"""
rootdirs = []
for i in range(3):
dirname = os.path.basename(root)
if dirname.startswith(parentdir_prefix):
return {"version": dirname[len(parentdir_prefix):],
"full-revisionid": None,
"dirty": False, "error": None, "date": None}
else:
rootdirs.append(root)
root = os.path.dirname(root) # up a level
if verbose:
print("Tried directories %s but none started with prefix %s" %
(str(rootdirs), parentdir_prefix))
raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
@register_vcs_handler("git", "get_keywords")
def git_get_keywords(versionfile_abs):
"""Extract version information from the given file."""
# the code embedded in _version.py can just fetch the value of these
# keywords. When used from setup.py, we don't want to import _version.py,
# so we do it with a regexp instead. This function is not used from
# _version.py.
keywords = {}
try:
f = open(versionfile_abs, "r")
for line in f.readlines():
if line.strip().startswith("git_refnames ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
keywords["refnames"] = mo.group(1)
if line.strip().startswith("git_full ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
keywords["full"] = mo.group(1)
if line.strip().startswith("git_date ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
keywords["date"] = mo.group(1)
f.close()
except EnvironmentError:
pass
return keywords
@register_vcs_handler("git", "keywords")
def git_versions_from_keywords(keywords, tag_prefix, verbose):
"""Get version information from git keywords."""
if not keywords:
raise NotThisMethod("no keywords at all, weird")
date = keywords.get("date")
if date is not None:
# git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant
# datestamp. However we prefer "%ci" (which expands to an "ISO-8601
# -like" string, which we must then edit to make compliant), because
# it's been around since git-1.5.3, and it's too difficult to
# discover which version we're using, or to work around using an
# older one.
date = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
refnames = keywords["refnames"].strip()
if refnames.startswith("$Format"):
if verbose:
print("keywords are unexpanded, not using")
raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
refs = set([r.strip() for r in refnames.strip("()").split(",")])
# starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
# just "foo-1.0". If we see a "tag: " prefix, prefer those.
TAG = "tag: "
tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
if not tags:
# Either we're using git < 1.8.3, or there really are no tags. We use
# a heuristic: assume all version tags have a digit. The old git %d
# expansion behaves like git log --decorate=short and strips out the
# refs/heads/ and refs/tags/ prefixes that would let us distinguish
# between branches and tags. By ignoring refnames without digits, we
# filter out many common branch names like "release" and
# "stabilization", as well as "HEAD" and "master".
tags = set([r for r in refs if re.search(r'\d', r)])
if verbose:
print("discarding '%s', no digits" % ",".join(refs - tags))
if verbose:
print("likely tags: %s" % ",".join(sorted(tags)))
for ref in sorted(tags):
# sorting will prefer e.g. "2.0" over "2.0rc1"
if ref.startswith(tag_prefix):
r = ref[len(tag_prefix):]
if verbose:
print("picking %s" % r)
return {"version": r,
"full-revisionid": keywords["full"].strip(),
"dirty": False, "error": None,
"date": date}
# no suitable tags, so version is "0+unknown", but full hex is still there
if verbose:
print("no suitable tags, using unknown + full revision id")
return {"version": "0+unknown",
"full-revisionid": keywords["full"].strip(),
"dirty": False, "error": "no suitable tags", "date": None}
@register_vcs_handler("git", "pieces_from_vcs")
def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
"""Get version from 'git describe' in the root of the source tree.
This only gets called if the git-archive 'subst' keywords were *not*
expanded, and _version.py hasn't already been rewritten with a short
version string, meaning we're inside a checked out source tree.
"""
GITS = ["git"]
if sys.platform == "win32":
GITS = ["git.cmd", "git.exe"]
out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root,
hide_stderr=True)
if rc != 0:
if verbose:
print("Directory %s not under git control" % root)
raise NotThisMethod("'git rev-parse --git-dir' returned error")
# if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
# if there isn't one, this yields HEX[-dirty] (no NUM)
describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty",
"--always", "--long",
"--match", "%s*" % tag_prefix],
cwd=root)
# --long was added in git-1.5.5
if describe_out is None:
raise NotThisMethod("'git describe' failed")
describe_out = describe_out.strip()
full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
if full_out is None:
raise NotThisMethod("'git rev-parse' failed")
full_out = full_out.strip()
pieces = {}
pieces["long"] = full_out
pieces["short"] = full_out[:7] # maybe improved later
pieces["error"] = None
# parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
# TAG might have hyphens.
git_describe = describe_out
# look for -dirty suffix
dirty = git_describe.endswith("-dirty")
pieces["dirty"] = dirty
if dirty:
git_describe = git_describe[:git_describe.rindex("-dirty")]
# now we have TAG-NUM-gHEX or HEX
if "-" in git_describe:
# TAG-NUM-gHEX
mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
if not mo:
# unparseable. Maybe git-describe is misbehaving?
pieces["error"] = ("unable to parse git-describe output: '%s'"
% describe_out)
return pieces
# tag
full_tag = mo.group(1)
if not full_tag.startswith(tag_prefix):
if verbose:
fmt = "tag '%s' doesn't start with prefix '%s'"
print(fmt % (full_tag, tag_prefix))
pieces["error"] = ("tag '%s' doesn't start with prefix '%s'"
% (full_tag, tag_prefix))
return pieces
pieces["closest-tag"] = full_tag[len(tag_prefix):]
# distance: number of commits since tag
pieces["distance"] = int(mo.group(2))
# commit: short hex revision ID
pieces["short"] = mo.group(3)
else:
# HEX: no tags
pieces["closest-tag"] = None
count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"],
cwd=root)
pieces["distance"] = int(count_out) # total number of commits
# commit date: see ISO-8601 comment in git_versions_from_keywords()
date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"],
cwd=root)[0].strip()
pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
return pieces
def plus_or_dot(pieces):
"""Return a + if we don't already have one, else return a ."""
if "+" in pieces.get("closest-tag", ""):
return "."
return "+"
def render_pep440(pieces):
"""Build up version string, with post-release "local version identifier".
Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
Exceptions:
1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
"""
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
rendered += plus_or_dot(pieces)
rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
if pieces["dirty"]:
rendered += ".dirty"
else:
# exception #1
rendered = "0+untagged.%d.g%s" % (pieces["distance"],
pieces["short"])
if pieces["dirty"]:
rendered += ".dirty"
return rendered
def render_pep440_pre(pieces):
"""TAG[.post.devDISTANCE] -- No -dirty.
Exceptions:
1: no tags. 0.post.devDISTANCE
"""
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"]:
rendered += ".post.dev%d" % pieces["distance"]
else:
# exception #1
rendered = "0.post.dev%d" % pieces["distance"]
return rendered
def render_pep440_post(pieces):
"""TAG[.postDISTANCE[.dev0]+gHEX] .
The ".dev0" means dirty. Note that .dev0 sorts backwards
(a dirty tree will appear "older" than the corresponding clean one),
but you shouldn't be releasing software with -dirty anyways.
Exceptions:
1: no tags. 0.postDISTANCE[.dev0]
"""
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
rendered += ".post%d" % pieces["distance"]
if pieces["dirty"]:
rendered += ".dev0"
rendered += plus_or_dot(pieces)
rendered += "g%s" % pieces["short"]
else:
# exception #1
rendered = "0.post%d" % pieces["distance"]
if pieces["dirty"]:
rendered += ".dev0"
rendered += "+g%s" % pieces["short"]
return rendered
def render_pep440_old(pieces):
"""TAG[.postDISTANCE[.dev0]] .
The ".dev0" means dirty.
Exceptions:
1: no tags. 0.postDISTANCE[.dev0]
"""
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
rendered += ".post%d" % pieces["distance"]
if pieces["dirty"]:
rendered += ".dev0"
else:
# exception #1
rendered = "0.post%d" % pieces["distance"]
if pieces["dirty"]:
rendered += ".dev0"
return rendered
def render_git_describe(pieces):
"""TAG[-DISTANCE-gHEX][-dirty].
Like 'git describe --tags --dirty --always'.
Exceptions:
1: no tags. HEX[-dirty] (note: no 'g' prefix)
"""
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"]:
rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
else:
# exception #1
rendered = pieces["short"]
if pieces["dirty"]:
rendered += "-dirty"
return rendered
def render_git_describe_long(pieces):
"""TAG-DISTANCE-gHEX[-dirty].
Like 'git describe --tags --dirty --always -long'.
The distance/hash is unconditional.
Exceptions:
1: no tags. HEX[-dirty] (note: no 'g' prefix)
"""
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
else:
# exception #1
rendered = pieces["short"]
if pieces["dirty"]:
rendered += "-dirty"
return rendered
def render(pieces, style):
"""Render the given version pieces into the requested style."""
if pieces["error"]:
return {"version": "unknown",
"full-revisionid": pieces.get("long"),
"dirty": None,
"error": pieces["error"],
"date": None}
if not style or style == "default":
style = "pep440" # the default
if style == "pep440":
rendered = render_pep440(pieces)
elif style == "pep440-pre":
rendered = render_pep440_pre(pieces)
elif style == "pep440-post":
rendered = render_pep440_post(pieces)
elif style == "pep440-old":
rendered = render_pep440_old(pieces)
elif style == "git-describe":
rendered = render_git_describe(pieces)
elif style == "git-describe-long":
rendered = render_git_describe_long(pieces)
else:
raise ValueError("unknown style '%s'" % style)
return {"version": rendered, "full-revisionid": pieces["long"],
"dirty": pieces["dirty"], "error": None,
"date": pieces.get("date")}
def get_versions():
"""Get version information or return default if unable to do so."""
# I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
# __file__, we can work backwards from there to the root. Some
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
# case we can only use expanded keywords.
cfg = get_config()
verbose = cfg.verbose
try:
return git_versions_from_keywords(get_keywords(), cfg.tag_prefix,
verbose)
except NotThisMethod:
pass
try:
root = os.path.realpath(__file__)
# versionfile_source is the relative path from the top of the source
# tree (where the .git directory might live) to this file. Invert
# this to find the root from __file__.
for i in cfg.versionfile_source.split('/'):
root = os.path.dirname(root)
except NameError:
return {"version": "0+unknown", "full-revisionid": None,
"dirty": None,
"error": "unable to find root of source tree",
"date": None}
try:
pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose)
return render(pieces, cfg.style)
except NotThisMethod:
pass
try:
if cfg.parentdir_prefix:
return versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
except NotThisMethod:
pass
return {"version": "0+unknown", "full-revisionid": None,
"dirty": None,
"error": "unable to compute version", "date": None}

249
README.md
View File

@@ -1,27 +1,49 @@
# Advanced Docking System for Qt
![ukraine](doc/ukraine.jpg)
![logo](doc/ads_logo.svg)
------------------
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/githubuser0xFFFF/Qt-Advanced-Docking-System?color=%23ff9833)](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/latest)
[![Build status](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/workflows/linux-builds/badge.svg)](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/actions?query=workflow%3Alinux-builds)
[![Build status](https://ci.appveyor.com/api/projects/status/qcfb3cy932jw9mpy/branch/master?svg=true)](https://ci.appveyor.com/project/githubuser0xFFFF/qt-advanced-docking-system/branch/master)
[![License: LGPL v2.1](https://img.shields.io/badge/License-LGPL%20v2.1-blue.svg)](gnu-lgpl-v2.1.md)
[What's new](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/latest) •
[Documentation](doc/user-guide.md)
[![GitHub contributors](https://img.shields.io/github/contributors/githubuser0xFFFF/Qt-Advanced-Docking-System?color=ffdf00)](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/graphs/contributors)
Qt Advanced Docking System lets you create customizable layouts using a full
featured window docking system similar to what is found in many popular
integrated development environments (IDEs) such as Visual Studio.
- [What's new...](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/latest)
- [Documentation](doc/user-guide.md)
- Original Repository: https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System
[![Video Advanced Docking](doc/advanced-docking_video.png)](https://www.youtube.com/watch?v=7pdNfafg3Qc)
## New and Noteworthy
The [release 3.7](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.7.0)
The [release 4.0](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/latest)
adds the following features:
- Auto-Hide functionality ([read more...](#auto-hide-functionality))
- improved demo application with new image viewer dock widgets
- Visual Studio like CSS theme in demo application
The [release 3.8](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/3.8.3)
adds the following features:
- option to close tabs with the middle mouse button
- `DeleteContentOnClose` flag for dynamic deletion and creation of dock widget
content
- improved focus highlighting functionality
The [release 3.7](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.7.2)
adds the following features:
- support for **Qt6.**
- support for [empty dock area](doc/user-guide.md#empty-dock-area)
The [release 3.6](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.6.0)
The [release 3.6](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.6.3)
adds some nice new features:
- support for [central widget](doc/user-guide.md#central-widget) concept
@@ -60,7 +82,10 @@ know it from Visual Studio.
- [Tab-menu for easy handling of many tabbed dock widgets](#tab-menu-for-easy-handling-of-many-tabbed-dock-widgets)
- [Many different ways to detach dock widgets](#many-different-ways-to-detach-dock-widgets)
- [Supports deletion of dynamically created dock widgets](#supports-deletion-of-dynamically-created-dock-widgets)
- [Python PyQt5 Bindings](#python-pyqt5-bindings)
- [Auto-Hide Functionality](#auto-hide-functionality)
- [Python Bindings](#python-bindings)
- [PySide6](#pyside6)
- [PyQt5](#pyqt5)
- [Tested Compatible Environments](#tested-compatible-environments)
- [Supported Qt Versions](#supported-qt-versions)
- [Windows](#windows)
@@ -68,20 +93,24 @@ know it from Visual Studio.
- [Linux](#linux)
- [Build](#build)
- [Getting started / Example](#getting-started--example)
- [Developers](#developers)
- [License information](#license-information)
- [Alternative Docking System Implementations](#alternative-docking-system-implementations)
- [KDDockWidgets](#kddockwidgets)
- [QtitanDocking](#qtitandocking)
- [Donation](#donation)
- [Showcase](#showcase)
- [Qt Creator IDE](#qt-creator-ide)
- [Qt Design Studio](#qt-design-studio)
- [QmixElements](#qmixelements)
- [CETONI Elements](#cetoni-elements)
- [ezEditor](#ezeditor)
- [D-Tect X](#d-tect-x)
- [HiveWE](#hivewe)
- [Ramses Composer](#ramses-composer)
- [Plot Juggler](#plot-juggler)
- [Notepad Next](#notepad-next)
- [MetGem](#metgem)
- [PRE Workbench](#pre-workbench)
- [Alternative Docking System Implementations](#alternative-docking-system-implementations)
- [KDDockWidgets](#kddockwidgets)
- [QtitanDocking](#qtitandocking)
- [DockingPanes](#dockingpanes)
### Docking everywhere - no central widget
@@ -136,7 +165,7 @@ If this flag is cleared, the widget resizing is deferred until the mouse button
### Opaque and non-opaque undocking
By default, opaque undocking is active. That means, as soon as you drag a dock widget or a dock area with a number of dock widgets it will be undocked and moved into a floating widget and then the floating widget will be dragged around. That means undocking will take place immediatelly. You can compare this with opaque splitter resizing. If the flag `OpaqueUndocking` is cleared, then non-opaque undocking is active. In this mode, undocking is more like a standard drag and drop operation. That means, the dragged dock widget or dock area is not undocked immediatelly. Instead, a drag preview widget is created and dragged around to indicate the future position of the dock widget or dock area. The actual dock operation is only executed when the mouse button is released. That makes it possible, to cancel an active drag operation with the escape key.
By default, opaque undocking is active. That means, as soon as you drag a dock widget or a dock area with a number of dock widgets it will be undocked and moved into a floating widget and then the floating widget will be dragged around. That means undocking will take place immediately. You can compare this with opaque splitter resizing. If the flag `OpaqueUndocking` is cleared, then non-opaque undocking is active. In this mode, undocking is more like a standard drag and drop operation. That means, the dragged dock widget or dock area is not undocked immediately. Instead, a drag preview widget is created and dragged around to indicate the future position of the dock widget or dock area. The actual dock operation is only executed when the mouse button is released. That makes it possible, to cancel an active drag operation with the escape key.
The drag preview widget can be configured by a number of global dock manager flags:
- `DragPreviewIsDynamic`: if this flag is enabled, the preview will be adjusted dynamically to the drop area
@@ -163,19 +192,74 @@ You can detach dock widgets and also dock areas in the following ways:
Normally clicking the close button of a dock widget will just hide the widget and the user can show it again using the toggleView() action of the dock widget. This is meant for user interfaces with a static amount of widgets. But the advanced docking system also supports dynamic dock widgets that will get deleted on close. If you set the dock widget flag `DockWidgetDeleteOnClose` for a certain dock widget, then it will be deleted as soon as you close this dock widget. This enables the implementation of user interfaces with dynamically created editors, like in word processing applications or source code development tools.
### Python PyQt5 Bindings
### Auto-Hide Functionality
The 4.0 release of ADS added the new **Auto-Hide** feature. Thanks to the
[initial contribution](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/pull/452) by [Ahmad Syarifuddin](https://github.com/SyarifFakhri) it was
possible to close this long standing [feature request](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/147). The "Auto Hide" feature
allows to display more information using less screen space by hiding or showing
windows pinned to one of the four dock container borders.
![Auto-Hide Movie](doc/AutoHide_Movie.gif)
The Advanced Docking
System supports "Auto-Hide" functionality for **all** dock containers - that means,
for the main window and for each floating widget. Here is short list of all
auto hide features:
- supported for the main window and all floating dock containers
- supports showing and hiding via mouse click or mouse hover
- respects opaque / non opaque splitter resizing flag
- context menu for pinning a dock widget or a complete dock area to a certain border
- configuration option to configure if the pin button should pin the current
dock widget tab or a complete dock area
- click the pin button holding the Ctrl key to pin a complete dock area
- fully CSS styleable
- backward compatible state file format - is is possible to load older dock manager
state files without auto hide support and older versions can load the new state
files with Auto-Hide state information
More about the auto hide configuration options in the [online documentation...](doc/user-guide.md#auto-hide-configuration-flags)
## Python Bindings
![Python Logo](doc/python_logo.png)
The Advanced Docking System comes with a complete Python integration based on
PyQt5 bindings. The package is available via [conda-forge](https://github.com/conda-forge/pyqtads-feedstock). The python integration has been contributed to this project
by the following people:
Thanks to the contribution of several users, the Advanced Docking System comes
with a complete Python integration. Python bindings are available for **PyQt5** and
**PySide6**.
### PySide6
A PySide6 ADS package is available via PyPi and can be installed on Windows,
macOS, and Linux with:
```bash
pip install PySide6-QtAds
```
Sample code is available [here](https://github.com/mborgerson/Qt-Advanced-Docking-System/tree/pyside6/examples). To run the samples, you'll also need to install latest qtpy
from source (pip install https://github.com/spyder-ide/qtpy/archive/refs/heads/master.zip).
The PySide6 bindings were contributed by:
- [mborgerson](https://github.com/mborgerson)
For more information about the PySide6 bindings read [this](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/298) issue.
### PyQt5
A package is available via [conda-forge](https://github.com/conda-forge/pyqtads-feedstock).
The python integration has been contributed to this project by the following people:
- [n-elie](https://github.com/n-elie)
- [Hugo Slepicka](https://github.com/hhslepicka)
- [K Lauer](https://github.com/klauer)
Latest working version: [3.5.2](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.5.2)
A Python integration is also available via PyPi. You can install the
[PyQtAds](https://pypi.org/project/PyQtAds/) package via pip. This feature has been
contributed to this project by:
- [Mira Weller](https://github.com/luelista)
## Tested Compatible Environments
@@ -273,8 +357,9 @@ MainWindow::MainWindow(QWidget *parent) :
{
ui->setupUi(this);
// Create the dock manager. Because the parent parameter is a QMainWindow
// the dock manager registers itself as the central widget.
// Create the dock manager after the ui is setup. Because the
// parent parameter is a QMainWindow the dock manager registers
// itself as the central widget as such the ui must be set up first.
m_DockManager = new ads::CDockManager(this);
// Create example content label - this can be any application specific
@@ -303,41 +388,11 @@ MainWindow::~MainWindow()
}
```
## Developers
- Uwe Kindler, Project Maintainer
- Manuel Freiholz
This work is based on and inspired by the
[Advanced Docking System for Qt](https://github.com/mfreiholz/Qt-Advanced-Docking-System)
from Manuel Freiholz. I did an almost complete rewrite of his code to improve
code quality, readibility and to fix all issues from the issue tracker
of his docking system project.
## License information
[![License: LGPL v2.1](https://img.shields.io/badge/License-LGPL%20v2.1-blue.svg)](gnu-lgpl-v2.1.md)
This project uses the [LGPLv2.1 license](gnu-lgpl-v2.1.md)
## Alternative Docking System Implementations
If this Qt Advanced Docking System does not fit to your needs you may consider some of the alternative docking system solutions for Qt.
### KDDockWidgets
This is an advanced docking framework for Qt from [KDAB](https://www.kdab.com/). The interesting thing is, that they separated GUI code from logic, so they can easily provide a QtQuick backend in the future.
- [Blog post about KDDockWidgets](https://www.kdab.com/kddockwidgets/)
- [GitHub project](https://github.com/KDAB/KDDockWidgets)
### QtitanDocking
This is a commercial component from [Developer Machines](https://www.devmachines.com/) for Qt Framework that allows to create a Microsoft like dockable user interface. They also offer a lot of other interesting and useful components for Qt.
- [Product page](https://www.devmachines.com/qtitandocking-overview.html)
## Donation
If this project help you reduce time to develop or if you just like it, you can give me a cup of coffee :coffee::wink:.
@@ -363,13 +418,14 @@ Taken from the [Qt Blog](https://www.qt.io/blog/qt-design-studio-1.5-beta-releas
[![Qt Design Studio](doc/showcase_qt_design_studio_video.png)](https://youtu.be/za9KBWcFXEw?t=84)
### [QmixElements](https://www.cetoni.com/products/qmixelements/)
### [CETONI Elements](https://cetoni.com/cetoni-elements/)
The QmixElements software from [CETONI](https://www.cetoni.com) is a comprehensive,
plugin-based and modular laboratory automation software for controlling CETONI devices using a joint graphical user interface. The software features a powerful script system to automate processes. This [blog post](https://www.cetoni.com/blog/qmixelements-advanced-docking-system/) gives a nice overview about the use of the Qt
Advanced Docking System in the QmixElements sofware.
The CETONI Elements software from [CETONI](https://www.cetoni.com) is a comprehensive,
plugin-based and modular laboratory automation software for controlling CETONI devices using a joint graphical user interface. The software features a powerful script system to automate processes. The software uses the advanced docking system to give the user the freedom to arrange all the views and windows that are provided by the various plugins.
![QmixElements](doc/showcase_qmix_elements.png)
[learn more...](https://cetoni.com/cetoni-elements/)
[![CETONI_Elements](doc/showcase_qmix_elements.png)](https://www.youtube.com/watch?v=7pdNfafg3Qc)
### [ezEditor](https://github.com/ezEngine/ezEngine)
@@ -385,13 +441,13 @@ D-Tect X is a X-ray inspection software for industrial radiography. It is a stat
[learn more...](https://www.duerr-ndt.com/products/ndt-software/d-tect-xray-inspection-software.html)
![D-TectX](doc/showcase_d-tect-x.jpg)
[![D-TectX](doc/showcase_d-tect-x.png)](https://youtu.be/mOor7GmmIJo?t=13)
### [HiveWE](https://github.com/stijnherfst/HiveWE)
HiveWE is a Warcraft III world editor. It focusses on speed and ease of use,
especially for large maps where the regular World Editor is often too slow and clunky.
It has a JASS editor with syntax hightlighting, tabs, code completion and more.
It has a JASS editor with syntax highlighting, tabs, code completion and more.
The JASS editor uses the Qt Advanced Docking System for the management and layout
of the open editor windows.
@@ -413,3 +469,82 @@ and digital portfolio.
[learn more...](https://github.com/GENIVI/ramses-composer)
![RamsesComposer](doc/showcase_ramses_composer.png)
### [Plot Juggler](https://github.com/facontidavide/PlotJuggler)
PlotJuggler is a fast, powerful and intuitive tool to visualize time series.
It makes it easy to visualize data but also to analyze it. You can manipulate
your time series using a simple and extendable Transform Editor. Some of the
highlights are:
- Simple Drag & Drop user interface.
- Load data from file.
- Connect to live streaming of data.
- Save the visualization layout and configurations to re-use them later.
- Fast OpenGL visualization.
- Can handle thousands of timeseries and millions of data points.
- Transform your data using a simple editor: derivative, moving average, integral, etc…
- PlotJuggler can be easily extended using plugins.
[read more...](https://github.com/facontidavide/PlotJuggler)
[![Plot Juggler](doc/showcase_plot_juggler.png)](https://vimeo.com/480588113#t=46s)
### [Notepad Next](https://github.com/dail8859/NotepadNext)
Notepad Next is a cross-platform reimplementation of Notepad++ that uses the
Advanced Docking System to arrange the open source files on the screen.
[read more...](https://github.com/dail8859/NotepadNext)
![NotepadNext](doc/showcase_notepad_next.png)
### [MetGem](https://metgem.github.io/)
MetGem is an open-source software for tandem mass-spectrometry data visualization.
It's key features are standalone molecular networking and t-SNE based projections.
MetGem uses the Qt-Advanced-Docking-System to manage docks and to create independent
molecular network views.
[read more...](https://metgem.github.io/)
![MetGem](doc/showcase_metgem.png)
### [PRE Workbench](https://luelista.github.io/pre_workbench/)
Protocol Reverse Engineering Workbench is a software to support researchers in reverse engineering protocols and documenting the results. It supports various sources to import protocol traffic from, helps the discovery process by displaying different views and heuristic-based highlighting on data, and aids in documenting and sharing findings.
PRE Workbench is a Python software and uses the ADS PyQt integration.
[read more...](https://luelista.github.io/pre_workbench/)
[![PRE Workbench](doc/showcase_pre_workbench.png)](https://youtu.be/U3op5UreV1Q)
## Alternative Docking System Implementations
If this Qt Advanced Docking System does not fit to your needs you may consider some of the alternative docking system solutions for Qt.
### KDDockWidgets
This is an advanced docking framework for Qt from [KDAB](https://www.kdab.com/). The interesting thing is, that they separated GUI code from logic, so they can easily provide a QtQuick backend in the future.
- [Blog post about KDDockWidgets](https://www.kdab.com/kddockwidgets/)
- [GitHub project](https://github.com/KDAB/KDDockWidgets)
**License:** dual-licensed, available under both commercial and GPL license.
### QtitanDocking
This is a commercial component from [Developer Machines](https://www.devmachines.com/) for Qt Framework that allows to create a Microsoft like dockable user interface. They also offer a lot of other interesting and useful components for Qt. The library is available
- [Product page](https://www.devmachines.com/qtitandocking-overview.html)
**License:** Commercial license
### DockingPanes
DockingPanes is a library for Qt Widgets that implements docking windows that have the look and feel of Visual Studio. It provides a simple API which allows an application to make use of docking windows with a few calls.
- [GitHub project](https://github.com/KestrelRadarSensors/dockingpanes)
**License:** GPL

View File

@@ -1,6 +1,6 @@
CONFIG(debug, debug|release){
win32 {
win32-g++ {
versionAtLeast(QT_VERSION, 5.15.0) {
LIBS += -lqtadvanceddocking
}
@@ -8,6 +8,9 @@ CONFIG(debug, debug|release){
LIBS += -lqtadvanceddockingd
}
}
else:msvc {
LIBS += -lqtadvanceddockingd
}
else:mac {
LIBS += -lqtadvanceddocking_debug
}

View File

@@ -13,6 +13,8 @@ set(ads_demo_SRCS
mainwindow.ui
StatusDialog.cpp
StatusDialog.ui
ImageViewer.cpp
RenderWidget.cpp
demo.qrc
)
add_executable(AdvancedDockingSystemDemo WIN32 ${ads_demo_SRCS})

280
demo/ImageViewer.cpp Normal file
View File

@@ -0,0 +1,280 @@
//============================================================================
/// \file ImageViewer.cpp
/// \author Uwe Kindler
/// \date 04.11.2022
/// \brief Implementation of CImageViewer
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include "ImageViewer.h"
#include <math.h>
#include <QLabel>
#include <QImageReader>
#include <QImageWriter>
#include <QMessageBox>
#include <QApplication>
#include <QDir>
#include <QFileDialog>
#include <QStandardPaths>
#include <QAction>
#include <QScrollBar>
#include <QPixmap>
#include <QPainter>
#include <QImage>
#include <QMouseEvent>
#include <QWheelEvent>
#include "RenderWidget.h"
/**
* Private image viewer data
*/
struct ImageViewerPrivate
{
CImageViewer* _this;
CRenderWidget* RenderWidget;///< renders the image to screen
bool AutoFit;///< automatically fit image to window size on resize events
QSize ImageSize;///< stores the image size to detect image size changes
QPoint MouseMoveStartPos;///< for calculation of mouse move vector
QLabel* ScalingLabel;///< label displays scaling factor
QList<QWidget*> OverlayTools;///< list of tool widget to overlay
ImageViewerPrivate(CImageViewer* _public) : _this(_public) {}
};
//============================================================================
CImageViewer::CImageViewer(QWidget *parent)
: Super(parent),
d(new ImageViewerPrivate(this))
{
d->AutoFit = true;
d->RenderWidget = new CRenderWidget(this);
this->setBackgroundRole(QPalette::Light);
this->setAlignment(Qt::AlignCenter);
this->setWidget(d->RenderWidget);
this->createActions();
this->setMouseTracking(false); // only produce mouse move events if mouse button pressed
}
//============================================================================
CImageViewer::~CImageViewer()
{
delete d;
}
//============================================================================
bool CImageViewer::loadFile(const QString& fileName)
{
QImageReader reader(fileName);
reader.setAutoTransform(true);
const QImage newImage = reader.read();
if (newImage.isNull())
{
QMessageBox::information(this, QGuiApplication::applicationDisplayName(),
tr("Cannot load %1: %2")
.arg(QDir::toNativeSeparators(fileName), reader.errorString()));
return false;
}
setImage(newImage);
setWindowFilePath(fileName);
return true;
}
//===========================================================================
void CImageViewer::setImage(const QImage &newImage)
{
d->RenderWidget->showImage(newImage);
this->adjustDisplaySize(newImage);
}
//============================================================================
void CImageViewer::adjustDisplaySize(const QImage& Image)
{
if (d->ImageSize == Image.size())
{
return;
}
d->ImageSize = Image.size();
if (d->AutoFit)
{
this->fitToWindow();
}
}
//===========================================================================
static void initializeImageFileDialog(QFileDialog &dialog, QFileDialog::AcceptMode acceptMode)
{
static bool firstDialog = true;
if (firstDialog) {
firstDialog = false;
const QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
dialog.setDirectory(picturesLocations.isEmpty() ? QDir::currentPath() : picturesLocations.last());
}
QStringList mimeTypeFilters;
const QByteArrayList supportedMimeTypes = acceptMode == QFileDialog::AcceptOpen
? QImageReader::supportedMimeTypes() : QImageWriter::supportedMimeTypes();
for (const QByteArray &mimeTypeName : supportedMimeTypes)
mimeTypeFilters.append(mimeTypeName);
mimeTypeFilters.sort();
dialog.setMimeTypeFilters(mimeTypeFilters);
dialog.selectMimeTypeFilter("image/jpeg");
if (acceptMode == QFileDialog::AcceptSave)
dialog.setDefaultSuffix("jpg");
}
//===========================================================================
void CImageViewer::open()
{
QFileDialog dialog(this, tr("Open File"));
initializeImageFileDialog(dialog, QFileDialog::AcceptOpen);
while (dialog.exec() == QDialog::Accepted && !loadFile(dialog.selectedFiles().first())) {}
}
//===========================================================================
void CImageViewer::createActions()
{
QAction* a;
a = new QAction(tr("&Open..."));
a->setIcon(QIcon(":/adsdemo/images/perm_media.svg"));
connect(a, &QAction::triggered, this, &CImageViewer::open);
a->setShortcut(QKeySequence::Open);;
this->addAction(a);
a = new QAction(tr("Fit on Screen"));
a->setIcon(QIcon(":/adsdemo/images/zoom_out_map.svg"));
connect(a, &QAction::triggered, this, &CImageViewer::fitToWindow);
this->addAction(a);
a = new QAction(tr("Actual Pixels"));
a->setIcon(QIcon(":/adsdemo/images/find_in_page.svg"));
connect(a, &QAction::triggered, this, &CImageViewer::normalSize);
this->addAction(a);
a = new QAction(this);
a->setSeparator(true);
this->addAction(a);
a = new QAction(tr("Zoom In (25%)"));
a->setIcon(QIcon(":/adsdemo/images/zoom_in.svg"));
connect(a, &QAction::triggered, this, &CImageViewer::zoomIn);
this->addAction(a);
a = new QAction(tr("Zoom Out (25%)"));
a->setIcon(QIcon(":/adsdemo/images/zoom_out.svg"));
connect(a, &QAction::triggered, this, &CImageViewer::zoomOut);
this->addAction(a);
this->setContextMenuPolicy(Qt::ActionsContextMenu);
}
//===========================================================================
void CImageViewer::zoomIn()
{
d->AutoFit = false;
d->RenderWidget->zoomIn();
}
//===========================================================================
void CImageViewer::zoomOut()
{
d->AutoFit = false;
d->RenderWidget->zoomOut();
}
//===========================================================================
void CImageViewer::normalSize()
{
d->AutoFit = false;
d->RenderWidget->normalSize();
}
//===========================================================================
void CImageViewer::fitToWindow()
{
d->AutoFit = true;
d->RenderWidget->scaleToSize(this->maximumViewportSize());
}
//============================================================================
void CImageViewer::resizeEvent(QResizeEvent* ResizeEvent)
{
Super::resizeEvent(ResizeEvent);
if (d->AutoFit)
{
this->fitToWindow();
}
}
//============================================================================
void CImageViewer::mousePressEvent(QMouseEvent* Event)
{
d->RenderWidget->setCursor(Qt::ClosedHandCursor);
d->MouseMoveStartPos = Event->pos();
Super::mousePressEvent(Event);
}
//============================================================================
void CImageViewer::mouseReleaseEvent(QMouseEvent* Event)
{
d->RenderWidget->setCursor(Qt::OpenHandCursor);
Super::mouseReleaseEvent(Event);
}
//============================================================================
void CImageViewer::mouseMoveEvent(QMouseEvent* Event)
{
QPoint MoveVector = Event->pos() - d->MouseMoveStartPos;
d->MouseMoveStartPos = Event->pos();
horizontalScrollBar()->setValue(horizontalScrollBar()->value()
- MoveVector.x());
verticalScrollBar()->setValue(verticalScrollBar()->value() - MoveVector.y());
}
//============================================================================
void CImageViewer::wheelEvent(QWheelEvent* Event)
{
double numDegrees = Event->angleDelta().y() / 8;
double numSteps = numDegrees / 15;
d->AutoFit = false;
double Zoom;
if (numSteps < 0)
{
Zoom = pow(0.9, 0 - numSteps);
}
else
{
Zoom = pow(1.10, numSteps);
}
d->RenderWidget->zoomByValue(Zoom);
}
#include "moc_ImageViewer.cpp"
//---------------------------------------------------------------------------
// EOF ImageViewer.cpp

88
demo/ImageViewer.h Normal file
View File

@@ -0,0 +1,88 @@
#ifndef ImageViewerH
#define ImageViewerH
//============================================================================
/// \file ImageViewer.h
/// \author Uwe Kindler
/// \date 04.11.2022
/// \brief Declaration of CImageViewer
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include <QScrollArea>
QT_BEGIN_NAMESPACE
class QLabel;
QT_END_NAMESPACE
struct ImageViewerPrivate;
/**
* Tiny simple image viewer for showing images in demo
*/
class CImageViewer : public QScrollArea
{
Q_OBJECT
public:
using Super = QScrollArea;
explicit CImageViewer(QWidget *parent = nullptr);
virtual ~CImageViewer();
bool loadFile(const QString& Filename);
void setImage(const QImage &newImage);
public Q_SLOTS:
void open();
void zoomIn();
void zoomOut();
void normalSize();
void fitToWindow();
protected:
/**
* @brief Reimplemented from QScrollArea to adjust image scaling if m_AutoFit is
* true.
*/
virtual void resizeEvent(QResizeEvent* ResizeEvent);
/**
* @brief Handle mouse press events.
*/
virtual void mousePressEvent(QMouseEvent* Event);
/**
* @brief Handles mouse release events.
*/
virtual void mouseReleaseEvent(QMouseEvent* Event);
/**
* @brief Handle mouse move events.
*/
virtual void mouseMoveEvent(QMouseEvent* Event);
/**
* @brief Use mouse wheel to change scaling of the image.
*/
virtual void wheelEvent(QWheelEvent* Event);
private:
/**
* @brief Create the wiget actions.
*/
void createActions();
/**
* @brief Adjust size of render widget in case of image size change.
* @param[in] Image The new image that may have a different image size.
*/
void adjustDisplaySize(const QImage& Image);
ImageViewerPrivate* d;
friend ImageViewerPrivate;
};
//---------------------------------------------------------------------------
#endif // ImageViewerH

View File

@@ -60,17 +60,20 @@
#include <QToolButton>
#include <QToolBar>
#include <QPointer>
#include <QMap>
#include <QElapsedTimer>
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
#include <QRandomGenerator>
#endif
#ifdef Q_OS_WIN
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <QAxWidget>
#endif
#endif
#include <QMap>
#include <QElapsedTimer>
#include "DockManager.h"
#include "DockWidget.h"
#include "DockAreaWidget.h"
@@ -80,6 +83,22 @@
#include "DockComponentsFactory.h"
#include "StatusDialog.h"
#include "DockSplitter.h"
#include "ImageViewer.h"
/**
* Returns a random number from 0 to highest - 1
*/
int randomNumberBounded(int highest)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
return QRandomGenerator::global()->bounded(highest);
#else
qsrand(QTime::currentTime().msec());
return qrand() % highest;
#endif
}
/**
@@ -216,9 +235,11 @@ struct MainWindowPrivate
QFileSystemModel* m = new QFileSystemModel(w);
m->setRootPath(QDir::currentPath());
w->setModel(m);
w->setRootIndex(m->index(QDir::currentPath()));
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Filesystem %1")
.arg(FileSystemCount++));
DockWidget->setWidget(w);
DockWidget->setIcon(svgIcon(":/adsdemo/images/folder_open.svg"));
ui.menuView->addAction(DockWidget->toggleViewAction());
// We disable focus to test focus highlighting if the dock widget content
// does not support focus
@@ -279,6 +300,7 @@ struct MainWindowPrivate
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Label %1").arg(LabelCount++));
DockWidget->setWidget(l);
DockWidget->setIcon(svgIcon(":/adsdemo/images/font_download.svg"));
ui.menuView->addAction(DockWidget->toggleViewAction());
return DockWidget;
}
@@ -316,6 +338,35 @@ struct MainWindowPrivate
return DockWidget;
}
/**
* Creates a simply image viewr
*/
ads::CDockWidget* createImageViewer()
{
static int ImageViewerCount = 0;
auto w = new CImageViewer();
auto ImageIndex = randomNumberBounded(4);
auto FileName = ":adsdemo/images/ads_logo.svg";
// Pick a random image from a number of images
switch (ImageIndex)
{
case 0: FileName = ":adsdemo/images/ads_tile_blue.svg"; break;
case 1: FileName = ":adsdemo/images/ads_tile_blue_light.svg"; break;
case 2: FileName = ":adsdemo/images/ads_tile_green.svg"; break;
case 3: FileName = ":adsdemo/images/ads_tile_orange.svg"; break;
}
auto Result = w->loadFile(FileName);
qDebug() << "loadFile result: " << Result;
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Image Viewer %1").arg(ImageViewerCount++));
DockWidget->setIcon(svgIcon(":/adsdemo/images/photo.svg"));
DockWidget->setWidget(w,ads:: CDockWidget::ForceNoScrollArea);
auto ToolBar = DockWidget->createDefaultToolBar();
ToolBar->addActions(w->actions());
return DockWidget;
}
/**
* Create a table widget
*/
@@ -433,6 +484,7 @@ void MainWindowPrivate::createContent()
int Width = Splitter->width();
Splitter->setSizes({Width * 2/3, Width * 1/3});
});
DockWidget->setWindowTitle(QString("My " + DockWidget->windowTitle()));
// Now we add a custom button to the dock area title bar that will create
// new editor widgets when clicked
@@ -457,7 +509,20 @@ void MainWindowPrivate::createContent()
DockManager->addDockWidget(ads::TopDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea);
auto BottomDockArea = DockManager->addDockWidget(ads::BottomDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea);
DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea);
DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(), BottomDockArea);
auto LabelDockWidget = createLongTextLabelDockWidget();
DockManager->addDockWidget(ads::CenterDockWidgetArea, LabelDockWidget, BottomDockArea);
// Tests CustomCloseHandling without DeleteOnClose
LabelDockWidget->setFeature(ads::CDockWidget::CustomCloseHandling, true);
QObject::connect(LabelDockWidget, &ads::CDockWidget::closeRequested, [LabelDockWidget, this]()
{
int Result = QMessageBox::question(_this, "Custom Close Request",
"Do you really want to close this dock widget?");
if (QMessageBox::Yes == Result)
{
LabelDockWidget->closeDockWidget();
}
});
Action = ui.menuTests->addAction(QString("Set %1 Floating").arg(DockWidget->windowTitle()));
DockWidget->connect(Action, SIGNAL(triggered()), SLOT(setFloating()));
@@ -466,9 +531,22 @@ void MainWindowPrivate::createContent()
Action = ui.menuTests->addAction(QString("Raise %1").arg(DockWidget->windowTitle()));
DockWidget->connect(Action, SIGNAL(triggered()), SLOT(raise()));
// Test hidden floating dock widget
DockWidget = createLongTextLabelDockWidget();
DockManager->addDockWidgetFloating(DockWidget);
DockWidget->toggleView(false);
// Test visible floating dock widget
DockWidget = createCalendarDockWidget();
DockManager->addDockWidgetFloating(DockWidget);
DockWidget->setWindowTitle(QString("My " + DockWidget->windowTitle()));
#ifdef Q_OS_WIN
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
// If opaque undocking is active, then undocking of widgets while
// active x widget is visible causes jerking while dragging a floating
// widget
if (!ads::CDockManager::testConfigFlag(ads::CDockManager::OpaqueUndocking))
{
DockManager->addDockWidget(ads::CenterDockWidgetArea, createActiveXWidget(), RighDockArea);
@@ -481,6 +559,10 @@ void MainWindowPrivate::createContent()
_this->connect(DockWidget, SIGNAL(viewToggled(bool)), SLOT(onViewToggled(bool)));
_this->connect(DockWidget, SIGNAL(visibilityChanged(bool)), SLOT(onViewVisibilityChanged(bool)));
}
// Create image viewer
DockWidget = createImageViewer();
DockManager->addDockWidget(ads::LeftDockWidgetArea, DockWidget);
}
@@ -519,12 +601,36 @@ void MainWindowPrivate::createActions()
_this->connect(a, SIGNAL(triggered()), SLOT(createEditor()));
ui.menuTests->addAction(a);
a = ui.toolBar->addAction("Create Editor Tab");
a->setProperty("Floating", false);
a->setToolTip("Creates a editor tab and inserts it as second tab into an area");
a->setIcon(svgIcon(":/adsdemo/images/tab.svg"));
a->setProperty("Tabbed", true);
_this->connect(a, SIGNAL(triggered()), SLOT(createEditor()));
ui.menuTests->addAction(a);
a = ui.toolBar->addAction("Create Floating Table");
a->setToolTip("Creates floating dynamic dockable table with millions of entries");
a->setIcon(svgIcon(":/adsdemo/images/grid_on.svg"));
_this->connect(a, SIGNAL(triggered()), SLOT(createTable()));
ui.menuTests->addAction(a);
a = ui.toolBar->addAction("Create Image Viewer");
auto ToolButton = qobject_cast<QToolButton*>(ui.toolBar->widgetForAction(a));
ToolButton->setPopupMode(QToolButton::InstantPopup);
a->setToolTip("Creates floating, docked or pinned image viewer");
a->setIcon(svgIcon(":/adsdemo/images/panorama.svg"));
ui.menuTests->addAction(a);
auto Menu = new QMenu();
ToolButton->setMenu(Menu);
a = Menu->addAction("Floating Image Viewer");
_this->connect(a, SIGNAL(triggered()), SLOT(createImageViewer()));
a = Menu->addAction("Docked Image Viewer");
_this->connect(a, SIGNAL(triggered()), SLOT(createImageViewer()));
a = Menu->addAction("Pinned Image Viewer");
_this->connect(a, SIGNAL(triggered()), SLOT(createImageViewer()));
ui.menuTests->addSeparator();
a = ui.menuTests->addAction("Show Status Dialog");
_this->connect(a, SIGNAL(triggered()), SLOT(showStatusDialog()));
@@ -532,6 +638,12 @@ void MainWindowPrivate::createActions()
a = ui.menuTests->addAction("Toggle Label 0 Window Title");
_this->connect(a, SIGNAL(triggered()), SLOT(toggleDockWidgetWindowTitle()));
ui.menuTests->addSeparator();
a = ui.toolBar->addAction("Apply VS Style");
a->setToolTip("Applies a Visual Studio light style (visual_studio_light.css)." );
a->setIcon(svgIcon(":/adsdemo/images/color_lens.svg"));
QObject::connect(a, &QAction::triggered, _this, &CMainWindow::applyVsStyle);
ui.menuTests->addAction(a);
}
@@ -591,7 +703,7 @@ CMainWindow::CMainWindow(QWidget *parent) :
// uncomment the following line if you want to use opaque undocking and
// opaque splitter resizing
// CDockManager::setConfigFlags(CDockManager::DefaultOpaqueConfig);
//CDockManager::setConfigFlags(CDockManager::DefaultOpaqueConfig);
// uncomment the following line if you want a fixed tab width that does
// not change if the visibility of the close button changes
@@ -621,11 +733,14 @@ CMainWindow::CMainWindow(QWidget *parent) :
// uncomment the following line if you want a central widget in the main dock container (the dock manager) without a titlebar
// If you enable this code, you can test it in the demo with the Calendar 0
// dock widget.
// CDockManager::setConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar, true);
//CDockManager::setConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar, true);
// uncomment the following line to enable focus highlighting of the dock
// widget that has the focus
CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true);
CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true);
// uncomment if you would like to enable dock widget auto hiding
CDockManager::setAutoHideConfigFlags(CDockManager::DefaultAutoHideConfig);
// uncomment if you would like to enable an equal distribution of the
// available size of a splitter to all contained dock widgets
@@ -638,11 +753,11 @@ CMainWindow::CMainWindow(QWidget *parent) :
d->DockManager = new CDockManager(this);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
connect(d->PerspectiveComboBox, SIGNAL(activated(const QString&)),
d->DockManager, SLOT(openPerspective(const QString&)));
connect(d->PerspectiveComboBox, SIGNAL(activated(QString)),
d->DockManager, SLOT(openPerspective(QString)));
#else
connect(d->PerspectiveComboBox, SIGNAL(textActivated(const QString&)),
d->DockManager, SLOT(openPerspective(const QString&)));
connect(d->PerspectiveComboBox, SIGNAL(textActivated(QString)),
d->DockManager, SLOT(openPerspective(QString)));
#endif
d->createContent();
@@ -714,13 +829,14 @@ void CMainWindow::savePerspective()
//============================================================================
void CMainWindow::onViewToggled(bool Open)
{
Q_UNUSED(Open);
auto DockWidget = qobject_cast<ads::CDockWidget*>(sender());
if (!DockWidget)
{
return;
}
qDebug() << DockWidget->objectName() << " viewToggled(" << Open << ")";
//qDebug() << DockWidget->objectName() << " viewToggled(" << Open << ")";
}
@@ -744,6 +860,8 @@ void CMainWindow::createEditor()
QObject* Sender = sender();
QVariant vFloating = Sender->property("Floating");
bool Floating = vFloating.isValid() ? vFloating.toBool() : true;
QVariant vTabbed = Sender->property("Tabbed");
bool Tabbed = vTabbed.isValid() ? vTabbed.toBool() : true;
auto DockWidget = d->createEditorWidget();
DockWidget->setFeature(ads::CDockWidget::DockWidgetDeleteOnClose, true);
DockWidget->setFeature(ads::CDockWidget::DockWidgetForceCloseWithArea, true);
@@ -755,31 +873,38 @@ void CMainWindow::createEditor()
FloatingWidget->move(QPoint(20, 20));
d->LastCreatedFloatingEditor = DockWidget;
d->LastDockedEditor.clear();
return;
}
else
{
ads::CDockAreaWidget* EditorArea = d->LastDockedEditor ? d->LastDockedEditor->dockAreaWidget() : nullptr;
if (EditorArea)
{
std::cout << "DockAreaCount before: " << EditorArea->dockContainer()->dockAreaCount() << std::endl;
d->DockManager->setConfigFlag(ads::CDockManager::EqualSplitOnInsertion, true);
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget, EditorArea);
std::cout << "DockAreaCount after: " << DockWidget->dockContainer()->dockAreaCount() << std::endl;
}
else
{
if (d->LastCreatedFloatingEditor)
{
std::cout << "LastCreated" << std::endl;
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget, d->LastCreatedFloatingEditor->dockAreaWidget());
}
else
{
d->DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);
}
}
d->LastDockedEditor = DockWidget;
}
ads::CDockAreaWidget* EditorArea = d->LastDockedEditor ? d->LastDockedEditor->dockAreaWidget() : nullptr;
if (EditorArea)
{
if (Tabbed)
{
// Test inserting the dock widget tab at a given position instead
// of appending it. This function inserts the new dock widget as
// first tab
d->DockManager->addDockWidgetTabToArea(DockWidget, EditorArea, 0);
}
else
{
d->DockManager->setConfigFlag(ads::CDockManager::EqualSplitOnInsertion, true);
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget, EditorArea);
}
}
else
{
if (d->LastCreatedFloatingEditor)
{
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget, d->LastCreatedFloatingEditor->dockAreaWidget());
}
else
{
d->DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);
}
}
d->LastDockedEditor = DockWidget;
}
@@ -797,6 +922,20 @@ void CMainWindow::onEditorCloseRequested()
}
//============================================================================
void CMainWindow::onImageViewerCloseRequested()
{
auto DockWidget = qobject_cast<ads::CDockWidget*>(sender());
int Result = QMessageBox::question(this, "Close Image Viewer", QString("%1 "
"contains unsaved changes? Would you like to close it?")
.arg(DockWidget->windowTitle()));
if (QMessageBox::Yes == Result)
{
DockWidget->closeDockWidget();
}
}
//============================================================================
void CMainWindow::createTable()
{
@@ -831,3 +970,45 @@ void CMainWindow::toggleDockWidgetWindowTitle()
d->WindowTitleTestDockWidget->setWindowTitle(Title);
}
//============================================================================
void CMainWindow::applyVsStyle()
{
QFile StyleSheetFile(":adsdemo/res/visual_studio_light.css");
StyleSheetFile.open(QIODevice::ReadOnly);
QTextStream StyleSheetStream(&StyleSheetFile);
auto Stylesheet = StyleSheetStream.readAll();
StyleSheetFile.close();
d->DockManager->setStyleSheet(Stylesheet);
}
//============================================================================
void CMainWindow::createImageViewer()
{
QAction* a = qobject_cast<QAction*>(sender());
qDebug() << "createImageViewer " << a->text();
auto DockWidget = d->createImageViewer();
DockWidget->setFeature(ads::CDockWidget::DockWidgetDeleteOnClose, true);
DockWidget->setFeature(ads::CDockWidget::DockWidgetForceCloseWithArea, true);
DockWidget->setFeature(ads::CDockWidget::CustomCloseHandling, true);
DockWidget->resize(QSize(640, 480));
connect(DockWidget, &ads::CDockWidget::closeRequested, this,
&CMainWindow::onImageViewerCloseRequested);
if (a->text().startsWith("Floating"))
{
auto FloatingWidget = d->DockManager->addDockWidgetFloating(DockWidget);
FloatingWidget->move(QPoint(20, 20));
}
else if (a->text().startsWith("Docked"))
{
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget);
}
else if (a->text().startsWith("Pinned"))
{
d->DockManager->addAutoHideDockWidget(ads::SideBarLeft, DockWidget);
}
}

View File

@@ -63,8 +63,11 @@ private slots:
void createEditor();
void createTable();
void onEditorCloseRequested();
void onImageViewerCloseRequested();
void showStatusDialog();
void toggleDockWidgetWindowTitle();
void applyVsStyle();
void createImageViewer();
};
#endif // MAINWINDOW_H

108
demo/RenderWidget.cpp Normal file
View File

@@ -0,0 +1,108 @@
//============================================================================
/// \file RenderWidget.cpp
/// \author Uwe Kindler
/// \date 04.11.2022
/// \brief Implementation of CRenderWidget
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include "RenderWidget.h"
#include <QPainter>
#include <math.h>
//===========================================================================
CRenderWidget::CRenderWidget(QWidget* Parent) :
QWidget(Parent), m_ScaleFactor(1)
{
this->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
this->setCursor(Qt::OpenHandCursor);
}
//===========================================================================
CRenderWidget::~CRenderWidget()
{
}
//===========================================================================
void CRenderWidget::showImage(const QImage& Image)
{
m_Image = QPixmap::fromImage(Image);
this->adjustWidgetSize();
this->repaint();
}
//===========================================================================
void CRenderWidget::paintEvent(QPaintEvent* Event)
{
Q_UNUSED(Event);
QPainter Painter(this);
Painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
Painter.setRenderHint(QPainter::Antialiasing, true);
Painter.scale(m_ScaleFactor, m_ScaleFactor);
Painter.drawPixmap(QPoint(0, 0), m_Image);
}
//============================================================================
void CRenderWidget::zoomIn()
{
scaleImage(1.25);
}
//============================================================================
void CRenderWidget::zoomOut()
{
scaleImage(0.8);
}
//============================================================================
void CRenderWidget::zoomByValue(double ZoomValue)
{
scaleImage(ZoomValue);
}
//============================================================================
void CRenderWidget::normalSize()
{
m_ScaleFactor = 1;
this->adjustWidgetSize();
}
//============================================================================
void CRenderWidget::scaleImage(double ScaleFactor)
{
m_ScaleFactor *= ScaleFactor;
this->adjustWidgetSize();
}
//============================================================================
void CRenderWidget::adjustWidgetSize()
{
QSize ScaledImageSize = m_Image.size() * m_ScaleFactor;
if (ScaledImageSize != this->size())
{
this->setFixedSize(ScaledImageSize);
}
}
//============================================================================
void CRenderWidget::scaleToSize(const QSize& TargetSize)
{
if (m_Image.isNull())
{
return;
}
double ScaleFactorH = (double) TargetSize.width() / m_Image.size().width();
double ScaleFactorV = (double) TargetSize.height()
/ m_Image.size().height();
m_ScaleFactor = (ScaleFactorH < ScaleFactorV) ? ScaleFactorH : ScaleFactorV;
this->adjustWidgetSize();
}
//---------------------------------------------------------------------------
// EOF RenderWidget.cpp

111
demo/RenderWidget.h Normal file
View File

@@ -0,0 +1,111 @@
#ifndef RenderWidgetH
#define RenderWidgetH
//============================================================================
/// \file RenderWidget.h
/// \author Uwe Kindler
/// \date 04.11.2022
/// \brief Declaration of CRenderWidget
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include <QWidget>
#include <QPixmap>
//============================================================================
// FORWARD DECLARATIONS
//============================================================================
class QImage;
/**
* @brief Widget for fast display of images (i.e. for video capture devices)
*/
class CRenderWidget : public QWidget
{
Q_OBJECT
private:
QPixmap m_Image;
double m_ScaleFactor;
protected:
/**
* @brief Reimplemented paint event method showing actual image.
*/
void paintEvent(QPaintEvent* PaintEvent);
/**
* @brief Change scale factor
*/
void scaleImage(double ScaleFactor);
/**
* @brief Adjust widget size to size of image.
*/
void adjustWidgetSize();
public:
/**
* Constructor
* @param[in] Parent Parent widget.
*/
CRenderWidget(QWidget* Parent);
/**
* Destructor
*/
virtual ~CRenderWidget();
signals:
/**
* @brief Signalize change of captured image size.
* @param ImageSize New image size.
*/
void imageSizeChanged(const QSize& ImageSize);
public slots:
/**
* @brief Show new image in render widget.
*/
void showImage(const QImage& Image);
/**
* @brief Zoom into the scene.
* This function decreases the scaling factor by setting it to the previous
* value in internal scaling list.
* @brief Steps The number of steps to zoom in. One step is 25%.
*/
void zoomIn();
/**
* @brief Zoom out of the scene.
* This function decreases the scaling factor by setting it to the next
* value in internal scaling list.
* @brief Steps The number of steps to zoom out. One step is 25%.
*/
void zoomOut();
/**
* @brief Change zoom by zoom value.
* @param[in] ZoomValue This is the zoom value to apply. A value of 1
* means no change a value > 1 increases the image (i.e. 1.25 would increase
* the image by 25%) and a value of < 1 decreases the image size (i.e.
* a value of 0.8 would decrease the image size by 25%).
*/
void zoomByValue(double ZoomValue);
/**
* @brief Resets the actual scaling to 1 and display the image with its
* actual pixel size.
*/
void normalSize();
/**
* @brief Scales the wiget and its content image to the given TargetSize
*/
void scaleToSize(const QSize& TargetSize);
}; // class CRenderWidget
//---------------------------------------------------------------------------
#endif // RenderWidgetH

BIN
demo/app.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

1
demo/app.rc Normal file
View File

@@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "app.ico"

View File

@@ -15,19 +15,25 @@ lessThan(QT_MAJOR_VERSION, 6) {
CONFIG += c++14
CONFIG += debug_and_release
DEFINES += QT_DEPRECATED_WARNINGS
RC_FILE += app.rc
adsBuildStatic {
DEFINES += ADS_STATIC
}
SOURCES += \
main.cpp \
MainWindow.cpp \
StatusDialog.cpp
HEADERS += \
MainWindow.h \
StatusDialog.h
StatusDialog.h \
ImageViewer.h \
RenderWidget.h
SOURCES += \
main.cpp \
MainWindow.cpp \
StatusDialog.cpp \
ImageViewer.cpp \
RenderWidget.cpp
FORMS += \
mainwindow.ui \

View File

@@ -17,5 +17,24 @@
<file>images/create_floating_editor.svg</file>
<file>images/create_floating_table.svg</file>
<file>images/docked_editor.svg</file>
<file>images/tab.svg</file>
<file>res/visual_studio_light.css</file>
<file>images/color_lens.svg</file>
<file>images/ads_icon.svg</file>
<file>images/ads_logo.svg</file>
<file>images/find_in_page.svg</file>
<file>images/perm_media.svg</file>
<file>images/zoom_in.svg</file>
<file>images/zoom_out.svg</file>
<file>images/zoom_out_map.svg</file>
<file>images/ads_tile_blue.svg</file>
<file>images/ads_tile_blue_light.svg</file>
<file>images/ads_tile_green.svg</file>
<file>images/ads_tile_orange.svg</file>
<file>images/photo.svg</file>
<file>images/crop_original.svg</file>
<file>images/panorama.svg</file>
<file>images/ads_icon2.svg</file>
<file>images/font_download.svg</file>
</qresource>
</RCC>

11
demo/images/ads_icon.svg Normal file
View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1024" height="1024" version="1.1" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
<text x="1251.1022" y="1305.4956" fill="#000000" font-family="sans-serif" font-size="40px" style="line-height:1.25" xml:space="preserve"><tspan x="1251.1022" y="1305.4956"/></text>
<g transform="translate(581.23 1750.5)">
<path d="m191.64-726.53h-521.75c-138.69 0-251.12-112.43-251.12-251.12v-521.75c0-138.69 112.43-251.12 251.12-251.12h521.75c138.69 0 251.12 112.43 251.12 251.12v521.75c0 138.69-112.43 251.12-251.12 251.12z" fill="#e0e0e0" style="mix-blend-mode:normal"/>
<path d="m-175.9-1515.9v256h469.33v-256z" fill="#009ddd" style="mix-blend-mode:normal"/>
<path d="m80.1-1217.2v256h213.33v-256z" fill="#ff9833" style="mix-blend-mode:normal"/>
<path d="m-175.9-1217.2v256h213.33v-256z" fill="#accb01" style="mix-blend-mode:normal"/>
<path d="m-431.9-1515.9v554.67h213.33v-554.67z" fill="#0083c3" style="mix-blend-mode:normal"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1004 B

11
demo/images/ads_icon2.svg Normal file
View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1024" height="1024" version="1.1" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
<desc>electric_iron icon - Licensed under Iconfu Standard License v1.0 (https://www.iconfu.com/iconfu_standard_license) - Incors GmbH</desc>
<g transform="matrix(1.4118 0 0 1.4118 -210.82 -210.82)" stroke-width=".50173">
<text x="1251.1022" y="1305.4956" fill="#000000" font-family="sans-serif" font-size="40px" style="line-height:1.25" xml:space="preserve"><tspan x="1251.1022" y="1305.4956" stroke-width=".70833"/></text>
<path d="m405.33 234.66v256h469.33v-256z" fill="#009ddd" style="mix-blend-mode:normal"/>
<path d="m661.33 533.33v256h213.33v-256z" fill="#ff9833" style="mix-blend-mode:normal"/>
<path d="m405.33 533.33v256h213.33v-256z" fill="#accb01" style="mix-blend-mode:normal"/>
<path d="m149.33 234.66v554.67h213.33v-554.67z" fill="#0083c3" style="mix-blend-mode:normal"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 956 B

12
demo/images/ads_logo.svg Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="6907.3" height="1024" version="1.1" viewBox="0 0 6907.3 1024" xmlns="http://www.w3.org/2000/svg">
<text x="1251.1022" y="1305.4956" fill="#000000" font-family="sans-serif" font-size="40px" style="line-height:1.25" xml:space="preserve"><tspan x="1251.1022" y="1305.4956"/></text>
<text x="1178.9221" y="718.37329" fill="#8f918f" font-family="sans-serif" font-size="628px" style="line-height:1.25" xml:space="preserve"><tspan x="1178.9221" y="718.37329" fill="#8f918f" font-family="'Segoe UI'" font-size="628px" font-weight="300">Qt Advanced Docking</tspan></text>
<g transform="translate(581.23 1750.5)">
<path d="m191.64-726.53h-521.75c-138.69 0-251.12-112.43-251.12-251.12v-521.75c0-138.69 112.43-251.12 251.12-251.12h521.75c138.69 0 251.12 112.43 251.12 251.12v521.75c0 138.69-112.43 251.12-251.12 251.12z" fill="#e0e0e0" style="mix-blend-mode:normal"/>
<path d="m-175.9-1515.9v256h469.33v-256z" fill="#009ddd" style="mix-blend-mode:normal"/>
<path d="m80.1-1217.2v256h213.33v-256z" fill="#ff9833" style="mix-blend-mode:normal"/>
<path d="m-175.9-1217.2v256h213.33v-256z" fill="#accb01" style="mix-blend-mode:normal"/>
<path d="m-431.9-1515.9v554.67h213.33v-554.67z" fill="#0083c3" style="mix-blend-mode:normal"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1024" height="1024" version="1.1" viewBox="0 0 270.93 270.93" xmlns="http://www.w3.org/2000/svg">
<path d="m-2.5e-6 -2.5e-6v270.93h270.93v-270.93z" fill="#0083c3" stroke-width=".26458" style="mix-blend-mode:normal"/>
<g fill="#fff" fill-opacity=".25">
<g transform="matrix(.12402 0 0 .12402 71.967 73.674)" stroke-width="4.7887">
<path d="m405.33 234.66v256h469.33v-256z" style="mix-blend-mode:normal"/>
<path d="m661.33 533.33v256h213.33v-256z" style="mix-blend-mode:normal"/>
<path d="m405.33 533.33v256h213.33v-256z" style="mix-blend-mode:normal"/>
<path d="m149.33 234.66v554.67h213.33v-554.67z" style="mix-blend-mode:normal"/>
</g>
<g stroke-width=".26458" aria-label="Docking">
<path d="m100.07 182.94q0 2.7805-1.5208 4.1938-1.5054 1.3979-4.2091 1.3979h-3.057v-10.968h3.3796q1.6437 0 2.8573 0.61447 1.2289 0.61446 1.8895 1.8127 0.66055 1.1982 0.66055 2.9494zm-1.4594 0.0461q0-2.1967-1.0907-3.2106-1.0753-1.0292-3.057-1.0292h-1.7973v8.6026h1.4901q4.4549 0 4.4549-4.3627z"/>
<path d="m114.84 184.4q0 2.0431-1.0446 3.1645-1.0292 1.1214-2.7958 1.1214-1.0907 0-1.9509-0.49158-0.84489-0.50693-1.3365-1.4594-0.49158-0.96778-0.49158-2.335 0-2.0431 1.0139-3.1491 1.0292-1.106 2.8112-1.106 1.106 0 1.9663 0.50694 0.86026 0.49157 1.3365 1.444 0.49158 0.93706 0.49158 2.3042zm-6.2215 0q0 1.4594 0.56838 2.3196 0.58374 0.84489 1.8434 0.84489 1.2443 0 1.828-0.84489 0.58374-0.86025 0.58374-2.3196 0-1.4594-0.58374-2.2889-0.58375-0.82953-1.8434-0.82953t-1.828 0.82953-0.56838 2.2889z"/>
<path d="m125.64 188.69q-1.106 0-1.9509-0.44549-0.84489-0.44549-1.3365-1.3826-0.47622-0.93707-0.47622-2.3964 0-1.5208 0.49158-2.4732 0.50693-0.95243 1.3826-1.3979t1.9817-0.44549q0.61447 0 1.1982 0.13826 0.59911 0.12289 0.96779 0.30723l-0.41477 1.1214q-0.36868-0.13826-0.86025-0.26115-0.49158-0.1229-0.9217-0.1229-2.4272 0-2.4272 3.1184 0 1.4901 0.58374 2.2889 0.59911 0.78345 1.7666 0.78345 0.66055 0 1.1828-0.13826 0.5223-0.13825 0.95242-0.33795v1.1982q-0.41476 0.21506-0.9217 0.3226-0.49157 0.12289-1.1982 0.12289z"/>
<path d="m136.4 176.86v6.0986q0 0.24579-0.0307 0.6452-0.0154 0.3994-0.0307 0.69127h0.0614q0.0922-0.12289 0.27651-0.35332 0.18434-0.23042 0.36868-0.46085 0.19971-0.24578 0.33796-0.3994l2.6268-2.7805h1.5823l-3.3335 3.5178 3.5639 4.716h-1.6283l-2.8573-3.8404-0.93707 0.81417v3.0262h-1.3365v-11.675z"/>
<path d="m149.32 177.22q0.30724 0 0.53766 0.21506 0.24579 0.1997 0.24579 0.64519t-0.24579 0.66056q-0.23042 0.1997-0.53766 0.1997-0.33795 0-0.56838-0.1997-0.23042-0.21507-0.23042-0.66056t0.23042-0.64519q0.23043-0.21506 0.56838-0.21506zm0.66056 3.0877v8.2339h-1.3518v-8.2339z"/>
<path d="m161.92 180.15q1.4747 0 2.2274 0.722 0.75272 0.722 0.75272 2.3043v5.3612h-1.3365v-5.2691q0-1.9817-1.8434-1.9817-1.3672 0-1.8895 0.76808-0.5223 0.76809-0.5223 2.2121v4.2706h-1.3518v-8.2339h1.0907l0.1997 1.1214h0.0768q0.39941-0.64519 1.106-0.95242 0.70664-0.3226 1.4901-0.3226z"/>
<path d="m175.73 180.15q0.81417 0 1.4594 0.30724 0.66055 0.30723 1.1214 0.93706h0.0768l0.18434-1.0907h1.0753v8.3721q0 1.7666-0.90634 2.6576-0.89098 0.89098-2.7805 0.89098-1.8127 0-2.9648-0.5223v-1.2443q1.2136 0.6452 3.0416 0.6452 1.06 0 1.6591-0.62983 0.61447-0.61447 0.61447-1.6898v-0.3226q0-0.18434 0.0154-0.52229 0.0154-0.35332 0.0307-0.49158h-0.0615q-0.82953 1.2443-2.55 1.2443-1.5976 0-2.504-1.1214-0.89098-1.1214-0.89098-3.1338 0-1.9663 0.89098-3.1184 0.90634-1.1675 2.4886-1.1675zm0.18434 1.1368q-1.0292 0-1.5976 0.82953-0.56838 0.81417-0.56838 2.335t0.55302 2.335q0.55302 0.79881 1.6437 0.79881 1.2443 0 1.8127-0.66056 0.56838-0.67591 0.56838-2.166v-0.32259q0-1.6744-0.58374-2.4118-0.58375-0.73736-1.828-0.73736z"/>
</g>
<g stroke-width=".26458" aria-label="Qt Advanced ">
<path d="m100.61 89.668q0 2.0124-0.81417 3.441-0.79881 1.4133-2.3811 1.9356l2.6269 2.7344h-1.9817l-2.1199-2.4732q-0.09217 0-0.1997 0-0.09217 0.01536-0.18434 0.01536-1.7051 0-2.8419-0.70664-1.1214-0.70664-1.6744-1.9817-0.55302-1.275-0.55302-2.9802 0-1.6744 0.55302-2.9341 0.55302-1.275 1.6744-1.9817 1.1368-0.70664 2.8573-0.70664 1.6437 0 2.7651 0.70664 1.1214 0.69128 1.6898 1.9663 0.58374 1.2597 0.58374 2.9648zm-8.664 0q0 2.0738 0.87562 3.272 0.87562 1.1829 2.7344 1.1829 1.8588 0 2.719-1.1829 0.87562-1.1982 0.87562-3.272 0-2.0738-0.86026-3.2413-0.86026-1.1829-2.719-1.1829-1.8741 0-2.7497 1.1829-0.87562 1.1675-0.87562 3.2413z"/>
<path d="m105.6 94.215q0.30723 0 0.62983-0.04609 0.32259-0.04609 0.52229-0.12289v1.0292q-0.21506 0.10753-0.61446 0.16898-0.39941 0.07681-0.76809 0.07681-0.64519 0-1.1982-0.21506-0.53766-0.23042-0.87562-0.78345-0.33796-0.55302-0.33796-1.5515v-4.7929h-1.1675v-0.64519l1.1829-0.53766 0.53766-1.7512h0.7988v1.8895h2.3811v1.0446h-2.3811v4.7621q0 0.75272 0.35332 1.1214 0.36868 0.35332 0.93707 0.35332z"/>
<path d="m119.46 95.168-1.3211-3.3949h-4.3474l-1.3058 3.3949h-1.3979l4.2859-11.014h1.2443l4.2706 11.014zm-1.7359-4.6239-1.2289-3.3181q-0.0461-0.12289-0.15362-0.44549-0.10753-0.3226-0.21507-0.66055-0.0922-0.35332-0.15361-0.53766-0.1229 0.47621-0.26115 0.93706-0.12289 0.44549-0.21507 0.70664l-1.2443 3.3181z"/>
<path d="m125.13 95.321q-1.5362 0-2.4579-1.06-0.9217-1.0753-0.9217-3.1952t0.9217-3.1952q0.93706-1.0907 2.4732-1.0907 0.95243 0 1.5515 0.35332 0.61447 0.35332 0.99851 0.86026h0.0922q-0.0307-0.1997-0.0614-0.58374-0.0307-0.3994-0.0307-0.62983v-3.2874h1.3518v11.675h-1.0907l-0.1997-1.106h-0.0614q-0.36868 0.5223-0.98314 0.89098-0.61447 0.36868-1.5823 0.36868zm0.21506-1.1214q1.3058 0 1.828-0.70664 0.53766-0.722 0.53766-2.166v-0.24579q0-1.5362-0.50694-2.3503-0.50694-0.82953-1.8741-0.82953-1.0907 0-1.6437 0.87562-0.53766 0.86026-0.53766 2.3196 0 1.4747 0.53766 2.2889 0.55302 0.81417 1.6591 0.81417z"/>
<path d="m133.47 95.168-3.1184-8.2339h1.444l1.7512 4.8543q0.12289 0.33796 0.26115 0.75272 0.13825 0.41477 0.24579 0.79881 0.10753 0.38404 0.15361 0.62983h0.0615q0.0461-0.24579 0.16898-0.62983 0.12289-0.3994 0.26115-0.79881 0.13825-0.41477 0.26115-0.75272l1.7512-4.8543h1.444l-3.1338 8.2339z"/>
<path d="m142.58 86.796q1.5054 0 2.2274 0.66055 0.722 0.66055 0.722 2.1046v5.607h-0.98315l-0.26115-1.1675h-0.0615q-0.53766 0.67591-1.1368 0.99851-0.59911 0.3226-1.6283 0.3226-1.1214 0-1.8588-0.58374-0.73736-0.59911-0.73736-1.8588 0-1.2289 0.96778-1.8895 0.96779-0.67591 2.9802-0.73736l1.3979-0.04609v-0.49158q0-1.0292-0.44549-1.4286t-1.2597-0.3994q-0.64519 0-1.2289 0.1997-0.58374 0.18434-1.0907 0.43013l-0.41476-1.0139q0.53766-0.29187 1.275-0.49158 0.73736-0.21506 1.5362-0.21506zm1.613 4.3474-1.2136 0.04609q-1.5362 0.06145-2.1353 0.49157-0.58375 0.43013-0.58375 1.2136 0 0.69128 0.41477 1.0139 0.43013 0.3226 1.0907 0.3226 1.0292 0 1.7205-0.56838 0.70664-0.58374 0.70664-1.782z"/>
<path d="m152.04 86.78q1.4747 0 2.2274 0.722 0.75272 0.722 0.75272 2.3043v5.3612h-1.3365v-5.2691q0-1.9817-1.8434-1.9817-1.3672 0-1.8895 0.76808t-0.5223 2.2121v4.2706h-1.3518v-8.2339h1.0907l0.1997 1.1214h0.0768q0.39941-0.64519 1.106-0.95243 0.70663-0.3226 1.4901-0.3226z"/>
<path d="m160.87 95.321q-1.106 0-1.9509-0.44549-0.8449-0.44549-1.3365-1.3826-0.47622-0.93706-0.47622-2.3964 0-1.5208 0.49158-2.4732 0.50694-0.95243 1.3826-1.3979 0.87562-0.44549 1.9817-0.44549 0.61447 0 1.1982 0.13826 0.59911 0.12289 0.96779 0.30723l-0.41476 1.1214q-0.36869-0.13826-0.86026-0.26115-0.49157-0.12289-0.9217-0.12289-2.4272 0-2.4272 3.1184 0 1.4901 0.58374 2.2889 0.59911 0.78345 1.7666 0.78345 0.66055 0 1.1828-0.13826 0.5223-0.13826 0.95243-0.33796v1.1982q-0.41477 0.21506-0.92171 0.3226-0.49157 0.12289-1.1982 0.12289z"/>
<path d="m168.13 86.78q1.0446 0 1.8127 0.46085 0.76809 0.46085 1.1675 1.3057 0.41477 0.82953 0.41477 1.9509v0.81417h-5.6378q0.0307 1.3979 0.70664 2.1353 0.69128 0.722 1.9202 0.722 0.78345 0 1.3826-0.13826 0.61447-0.15362 1.2597-0.43013v1.1829q-0.62983 0.27651-1.2443 0.3994-0.61447 0.13826-1.4594 0.13826-1.1828 0-2.0738-0.47621t-1.3979-1.4133q-0.49157-0.93706-0.49157-2.3196 0-1.3518 0.44549-2.3196 0.46085-0.96779 1.275-1.4901 0.82953-0.5223 1.9202-0.5223zm-0.0154 1.106q-0.96779 0-1.5362 0.62983-0.55302 0.61447-0.66055 1.7205h4.1937q-0.0154-1.0446-0.49157-1.6898-0.47622-0.66055-1.5054-0.66055z"/>
<path d="m176.53 95.321q-1.5362 0-2.4579-1.06-0.92171-1.0753-0.92171-3.1952t0.92171-3.1952q0.93706-1.0907 2.4732-1.0907 0.95243 0 1.5515 0.35332 0.61447 0.35332 0.99851 0.86026h0.0922q-0.0307-0.1997-0.0614-0.58374-0.0307-0.3994-0.0307-0.62983v-3.2874h1.3518v11.675h-1.0907l-0.1997-1.106h-0.0614q-0.36868 0.5223-0.98315 0.89098-0.61446 0.36868-1.5822 0.36868zm0.21506-1.1214q1.3058 0 1.828-0.70664 0.53766-0.722 0.53766-2.166v-0.24579q0-1.5362-0.50693-2.3503-0.50694-0.82953-1.8741-0.82953-1.0907 0-1.6437 0.87562-0.53766 0.86026-0.53766 2.3196 0 1.4747 0.53766 2.2889 0.55302 0.81417 1.6591 0.81417z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="1024"
height="1024"
viewBox="0 0 270.93333 270.93333"
version="1.1"
id="svg506"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="ads_tile_blue_light.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview508"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
showgrid="false"
inkscape:zoom="0.77111176"
inkscape:cx="450.64804"
inkscape:cy="534.2935"
inkscape:window-width="1920"
inkscape:window-height="1009"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs503" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
id="path16513"
style="mix-blend-mode:normal;fill:#009ddd;fill-opacity:1;fill-rule:nonzero;stroke-width:0.264583"
d="M -2.5e-6,-2.5e-6 V 270.93333 H 270.93333 V -2.5e-6 Z" />
<g
id="g1224"
transform="matrix(0.12402399,0,0,0.12402399,71.967002,73.673805)"
style="fill:#ffffff;fill-opacity:0.25;stroke-width:2.13332">
<path
id="path927"
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:0.25;fill-rule:nonzero;stroke-width:4.7887"
d="m 405.32995,234.66 v 256 h 469.3301 v -256 z" />
<path
id="path16513-9"
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:0.25;fill-rule:nonzero;stroke-width:4.7887"
d="M 661.32995,533.3299 V 789.32994 H 874.66003 V 533.3299 Z" />
<path
id="path16513-5"
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:0.25;fill-rule:nonzero;stroke-width:4.7887"
d="m 405.32995,533.33 v 256 h 213.33008 v -256 z" />
<path
id="path24788"
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:0.25;fill-rule:nonzero;stroke-width:4.7887"
d="M 149.32995,234.66 V 789.32994 H 362.66003 V 234.66 Z" />
</g>
<g
aria-label="Docking"
id="text2150"
style="font-size:15.3617px;line-height:1.05;fill:#ffffff;stroke-width:0.264583;fill-opacity:0.25">
<path
d="m 100.07327,182.94499 q 0,2.78047 -1.520805,4.19375 -1.505447,1.39791 -4.209106,1.39791 H 91.286381 V 177.5684 h 3.379574 q 1.643702,0 2.857276,0.61447 1.228936,0.61446 1.889489,1.81268 0.66055,1.19821 0.66055,2.94944 z m -1.459358,0.0461 q 0,-2.19673 -1.090681,-3.2106 -1.075319,-1.02923 -3.056978,-1.02923 h -1.797319 v 8.60255 h 1.490085 q 4.454893,0 4.454893,-4.36272 z"
style="text-align:center;letter-spacing:5.36125px;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2539" />
<path
d="m 114.83588,184.40435 q 0,2.04311 -1.0446,3.16451 -1.02923,1.12141 -2.79583,1.12141 -1.09068,0 -1.95094,-0.49158 -0.84489,-0.50693 -1.33646,-1.45936 -0.49158,-0.96778 -0.49158,-2.33498 0,-2.0431 1.01387,-3.14914 1.02924,-1.10605 2.8112,-1.10605 1.10604,0 1.96629,0.50694 0.86026,0.49157 1.33647,1.444 0.49158,0.93706 0.49158,2.30425 z m -6.22149,0 q 0,1.45937 0.56838,2.31962 0.58374,0.84489 1.8434,0.84489 1.2443,0 1.82805,-0.84489 0.58374,-0.86025 0.58374,-2.31962 0,-1.45936 -0.58374,-2.28889 -0.58375,-0.82953 -1.84341,-0.82953 -1.25966,0 -1.82804,0.82953 -0.56838,0.82953 -0.56838,2.28889 z"
style="text-align:center;letter-spacing:5.36125px;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2541" />
<path
d="m 125.63516,188.69027 q -1.10604,0 -1.95094,-0.44549 -0.84489,-0.44549 -1.33646,-1.38255 -0.47622,-0.93707 -0.47622,-2.39643 0,-1.52081 0.49158,-2.47323 0.50693,-0.95243 1.38255,-1.39792 0.87562,-0.44549 1.98166,-0.44549 0.61447,0 1.19821,0.13826 0.59911,0.12289 0.96779,0.30723 l -0.41477,1.12141 q -0.36868,-0.13826 -0.86025,-0.26115 -0.49158,-0.1229 -0.9217,-0.1229 -2.42715,0 -2.42715,3.11843 0,1.49008 0.58374,2.28889 0.59911,0.78345 1.7666,0.78345 0.66055,0 1.18285,-0.13826 0.5223,-0.13825 0.95242,-0.33795 v 1.19821 q -0.41476,0.21506 -0.9217,0.3226 -0.49157,0.12289 -1.19821,0.12289 z"
style="text-align:center;letter-spacing:5.36125px;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2543" />
<path
d="m 136.40372,176.86176 v 6.09859 q 0,0.24579 -0.0307,0.6452 -0.0154,0.3994 -0.0307,0.69127 h 0.0614 q 0.0922,-0.12289 0.27651,-0.35332 0.18434,-0.23042 0.36868,-0.46085 0.19971,-0.24578 0.33796,-0.3994 l 2.62685,-2.78047 h 1.58226 l -3.33349,3.51783 3.56391,4.71604 h -1.62834 l -2.85727,-3.84042 -0.93707,0.81417 v 3.02625 h -1.33647 v -11.67489 z"
style="text-align:center;letter-spacing:5.36125px;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2545" />
<path
d="m 149.32293,177.21508 q 0.30724,0 0.53766,0.21506 0.24579,0.1997 0.24579,0.64519 0,0.44549 -0.24579,0.66056 -0.23042,0.1997 -0.53766,0.1997 -0.33795,0 -0.56838,-0.1997 -0.23042,-0.21507 -0.23042,-0.66056 0,-0.44549 0.23042,-0.64519 0.23043,-0.21506 0.56838,-0.21506 z m 0.66056,3.0877 v 8.23387 h -1.35183 v -8.23387 z"
style="text-align:center;letter-spacing:5.36125px;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2547" />
<path
d="m 161.91954,180.14916 q 1.47472,0 2.22745,0.722 0.75272,0.722 0.75272,2.30426 v 5.36123 h -1.33647 v -5.26906 q 0,-1.98166 -1.8434,-1.98166 -1.36719,0 -1.88949,0.76808 -0.5223,0.76809 -0.5223,2.21209 v 4.27055 h -1.35183 v -8.23387 h 1.09068 l 0.1997,1.1214 h 0.0768 q 0.39941,-0.64519 1.10604,-0.95242 0.70664,-0.3226 1.49009,-0.3226 z"
style="text-align:center;letter-spacing:5.36125px;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2549" />
<path
d="m 175.72973,180.14916 q 0.81417,0 1.45936,0.30724 0.66055,0.30723 1.1214,0.93706 h 0.0768 l 0.18434,-1.09068 h 1.07532 v 8.37213 q 0,1.76659 -0.90634,2.65757 -0.89098,0.89098 -2.78047,0.89098 -1.81268,0 -2.96481,-0.5223 v -1.2443 q 1.21358,0.6452 3.04162,0.6452 1.05996,0 1.65906,-0.62983 0.61447,-0.61447 0.61447,-1.68979 v -0.3226 q 0,-0.18434 0.0154,-0.52229 0.0154,-0.35332 0.0307,-0.49158 h -0.0615 q -0.82953,1.2443 -2.55004,1.2443 -1.59762,0 -2.50396,-1.12141 -0.89098,-1.1214 -0.89098,-3.13378 0,-1.9663 0.89098,-3.11843 0.90634,-1.16749 2.4886,-1.16749 z m 0.18434,1.13677 q -1.02924,0 -1.59762,0.82953 -0.56838,0.81417 -0.56838,2.33498 0,1.52081 0.55302,2.33498 0.55302,0.79881 1.6437,0.79881 1.2443,0 1.81268,-0.66056 0.56838,-0.67591 0.56838,-2.166 v -0.32259 q 0,-1.67443 -0.58374,-2.41179 -0.58375,-0.73736 -1.82804,-0.73736 z"
style="text-align:center;letter-spacing:5.36125px;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2551" />
</g>
<g
aria-label="Qt Advanced
"
id="text2150-1"
style="font-size:15.3617px;line-height:1.05;fill:#ffffff;stroke-width:0.264583;fill-opacity:0.25">
<path
d="m 100.61097,89.66819 q 0,2.012383 -0.814169,3.441021 -0.798808,1.413276 -2.381063,1.935574 l 2.626852,2.734383 h -1.981661 l -2.119914,-2.473234 q -0.09217,0 -0.199702,0 -0.09217,0.01536 -0.184341,0.01536 -1.705148,0 -2.841914,-0.706638 -1.121404,-0.706639 -1.674426,-1.98166 -0.553021,-1.275021 -0.553021,-2.980169 0,-1.674426 0.553021,-2.934085 0.553022,-1.275021 1.674426,-1.98166 1.136766,-0.706638 2.857276,-0.706638 1.643702,0 2.765106,0.706638 1.121404,0.691277 1.68979,1.966298 0.58374,1.25966 0.58374,2.964808 z m -8.663997,0 q 0,2.07383 0.875617,3.272042 0.875617,1.182851 2.734382,1.182851 1.858766,0 2.719021,-1.182851 0.875617,-1.198212 0.875617,-3.272042 0,-2.073829 -0.860255,-3.241318 -0.860255,-1.182851 -2.719021,-1.182851 -1.874127,0 -2.749744,1.182851 -0.875617,1.167489 -0.875617,3.241318 z"
style="text-align:center;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2518" />
<path
d="m 105.60353,94.215253 q 0.30723,0 0.62983,-0.04609 0.32259,-0.04609 0.52229,-0.122893 v 1.029234 q -0.21506,0.107532 -0.61446,0.168978 -0.39941,0.07681 -0.76809,0.07681 -0.64519,0 -1.19821,-0.215064 -0.53766,-0.230425 -0.87562,-0.783447 -0.33796,-0.553021 -0.33796,-1.551531 v -4.792851 h -1.16749 v -0.645191 l 1.18286,-0.53766 0.53766,-1.751234 h 0.7988 v 1.88949 h 2.38107 v 1.044595 h -2.38107 v 4.762127 q 0,0.752724 0.35332,1.121404 0.36868,0.353319 0.93707,0.353319 z"
style="text-align:center;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2520" />
<path
d="m 119.45978,95.167679 -1.3211,-3.394936 h -4.34736 l -1.30575,3.394936 h -1.39791 l 4.28591,-11.014339 h 1.2443 l 4.27055,11.014339 z m -1.73587,-4.623872 -1.22893,-3.318127 q -0.0461,-0.122894 -0.15362,-0.445489 -0.10753,-0.322596 -0.21507,-0.660554 -0.0922,-0.353319 -0.15361,-0.537659 -0.1229,0.476213 -0.26115,0.937064 -0.12289,0.445489 -0.21507,0.706638 l -1.24429,3.318127 z"
style="text-align:center;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2522" />
<path
d="m 125.12825,95.321296 q -1.53617,0 -2.45787,-1.059957 -0.9217,-1.075319 -0.9217,-3.195234 0,-2.119915 0.9217,-3.195234 0.93706,-1.09068 2.47323,-1.09068 0.95243,0 1.55153,0.353319 0.61447,0.353319 0.99851,0.860255 h 0.0922 q -0.0307,-0.199702 -0.0614,-0.583745 -0.0307,-0.399404 -0.0307,-0.629829 v -3.287404 h 1.35183 v 11.674892 h -1.09068 l -0.1997,-1.106043 h -0.0614 q -0.36868,0.522298 -0.98314,0.890979 -0.61447,0.368681 -1.58226,0.368681 z m 0.21506,-1.121404 q 1.30575,0 1.82805,-0.706638 0.53766,-0.722 0.53766,-2.166 v -0.245787 q 0,-1.53617 -0.50694,-2.35034 -0.50694,-0.829532 -1.87413,-0.829532 -1.09068,0 -1.6437,0.875617 -0.53766,0.860255 -0.53766,2.319616 0,1.474724 0.53766,2.288894 0.55302,0.81417 1.65906,0.81417 z"
style="text-align:center;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2524" />
<path
d="m 133.46965,95.167679 -3.11842,-8.233871 h 1.444 l 1.75123,4.854297 q 0.12289,0.337957 0.26115,0.752723 0.13825,0.414766 0.24579,0.798809 0.10753,0.384042 0.15361,0.629829 h 0.0615 q 0.0461,-0.245787 0.16898,-0.629829 0.12289,-0.399405 0.26115,-0.798809 0.13825,-0.414766 0.26115,-0.752723 l 1.75123,-4.854297 h 1.444 l -3.13379,8.233871 z"
style="text-align:center;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2526" />
<path
d="m 142.57913,86.795552 q 1.50545,0 2.22745,0.660553 0.722,0.660554 0.722,2.104553 v 5.607021 h -0.98315 l -0.26115,-1.167489 h -0.0615 q -0.53766,0.675914 -1.13676,0.99851 -0.59911,0.322596 -1.62834,0.322596 -1.12141,0 -1.85877,-0.583745 -0.73736,-0.599106 -0.73736,-1.858765 0,-1.228936 0.96778,-1.88949 0.96779,-0.675914 2.98017,-0.737361 l 1.39792,-0.04609 V 89.71427 q 0,-1.029234 -0.44549,-1.428638 -0.44549,-0.399404 -1.25966,-0.399404 -0.64519,0 -1.22894,0.199702 -0.58374,0.184341 -1.09068,0.430128 l -0.41476,-1.013872 q 0.53766,-0.291873 1.27502,-0.491575 0.73736,-0.215064 1.53617,-0.215064 z m 1.61298,4.347361 -1.21358,0.04609 q -1.53617,0.06145 -2.13527,0.491574 -0.58375,0.430128 -0.58375,1.213574 0,0.691277 0.41477,1.013872 0.43013,0.322596 1.09068,0.322596 1.02923,0 1.72051,-0.568383 0.70664,-0.583744 0.70664,-1.781957 z"
style="text-align:center;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2528" />
<path
d="m 152.04195,86.780191 q 1.47472,0 2.22745,0.722 0.75272,0.721999 0.75272,2.304255 v 5.361233 h -1.33647 v -5.269063 q 0,-1.98166 -1.8434,-1.98166 -1.36719,0 -1.88949,0.768085 -0.5223,0.768085 -0.5223,2.212085 v 4.270553 h -1.35183 v -8.233871 h 1.09068 l 0.1997,1.121404 h 0.0768 q 0.39941,-0.645192 1.10605,-0.952426 0.70663,-0.322595 1.49008,-0.322595 z"
style="text-align:center;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2530" />
<path
d="m 160.87493,95.321296 q -1.10604,0 -1.95093,-0.445489 -0.8449,-0.44549 -1.33647,-1.382553 -0.47622,-0.937064 -0.47622,-2.396426 0,-1.520808 0.49158,-2.473233 0.50694,-0.952426 1.38255,-1.397915 0.87562,-0.445489 1.98166,-0.445489 0.61447,0 1.19821,0.138255 0.59911,0.122894 0.96779,0.307234 l -0.41476,1.121404 q -0.36869,-0.138255 -0.86026,-0.261149 -0.49157,-0.122893 -0.9217,-0.122893 -2.42715,0 -2.42715,3.118425 0,1.490085 0.58374,2.288893 0.59911,0.783447 1.7666,0.783447 0.66055,0 1.18285,-0.138256 0.5223,-0.138255 0.95243,-0.337957 v 1.198213 q -0.41477,0.215063 -0.92171,0.322595 -0.49157,0.122894 -1.19821,0.122894 z"
style="text-align:center;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2532" />
<path
d="m 168.12564,86.780191 q 1.0446,0 1.81268,0.460851 0.76809,0.460851 1.16749,1.305744 0.41477,0.829532 0.41477,1.950936 v 0.81417 h -5.63775 q 0.0307,1.397915 0.70664,2.135276 0.69128,0.722 1.92021,0.722 0.78345,0 1.38256,-0.138255 0.61447,-0.153617 1.25966,-0.430128 v 1.182851 q -0.62983,0.276511 -1.2443,0.399405 -0.61447,0.138255 -1.45936,0.138255 -1.18285,0 -2.07383,-0.476213 -0.89098,-0.476213 -1.39792,-1.413276 -0.49157,-0.937064 -0.49157,-2.319617 0,-1.35183 0.44549,-2.319617 0.46085,-0.967787 1.27502,-1.490085 0.82953,-0.522297 1.92021,-0.522297 z m -0.0154,1.106042 q -0.96779,0 -1.53617,0.62983 -0.55302,0.614468 -0.66055,1.72051 h 4.19374 q -0.0154,-1.044595 -0.49157,-1.689787 -0.47622,-0.660553 -1.50545,-0.660553 z"
style="text-align:center;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2534" />
<path
d="m 176.52848,95.321296 q -1.53617,0 -2.45787,-1.059957 -0.92171,-1.075319 -0.92171,-3.195234 0,-2.119915 0.92171,-3.195234 0.93706,-1.09068 2.47323,-1.09068 0.95243,0 1.55153,0.353319 0.61447,0.353319 0.99851,0.860255 h 0.0922 q -0.0307,-0.199702 -0.0614,-0.583745 -0.0307,-0.399404 -0.0307,-0.629829 v -3.287404 h 1.35183 v 11.674892 h -1.09068 l -0.1997,-1.106043 h -0.0614 q -0.36868,0.522298 -0.98315,0.890979 -0.61446,0.368681 -1.58225,0.368681 z m 0.21506,-1.121404 q 1.30575,0 1.82804,-0.706638 0.53766,-0.722 0.53766,-2.166 v -0.245787 q 0,-1.53617 -0.50693,-2.35034 -0.50694,-0.829532 -1.87413,-0.829532 -1.09068,0 -1.6437,0.875617 -0.53766,0.860255 -0.53766,2.319616 0,1.474724 0.53766,2.288894 0.55302,0.81417 1.65906,0.81417 z"
style="text-align:center;text-anchor:middle;fill:#ffffff;fill-opacity:0.25"
id="path2536" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1024" height="1024" version="1.1" viewBox="0 0 270.93 270.93" xmlns="http://www.w3.org/2000/svg">
<path d="m-2.5e-6 -2.5e-6v270.93h270.93v-270.93z" fill="#accb01" stroke-width=".26458" style="mix-blend-mode:normal"/>
<g fill="#fff" fill-opacity=".25">
<g transform="matrix(.12402 0 0 .12402 71.967 73.674)" stroke-width="4.7887">
<path d="m405.33 234.66v256h469.33v-256z" style="mix-blend-mode:normal"/>
<path d="m661.33 533.33v256h213.33v-256z" style="mix-blend-mode:normal"/>
<path d="m405.33 533.33v256h213.33v-256z" style="mix-blend-mode:normal"/>
<path d="m149.33 234.66v554.67h213.33v-554.67z" style="mix-blend-mode:normal"/>
</g>
<g stroke-width=".26458" aria-label="Docking">
<path d="m100.07 182.94q0 2.7805-1.5208 4.1938-1.5054 1.3979-4.2091 1.3979h-3.057v-10.968h3.3796q1.6437 0 2.8573 0.61447 1.2289 0.61446 1.8895 1.8127 0.66055 1.1982 0.66055 2.9494zm-1.4594 0.0461q0-2.1967-1.0907-3.2106-1.0753-1.0292-3.057-1.0292h-1.7973v8.6026h1.4901q4.4549 0 4.4549-4.3627z"/>
<path d="m114.84 184.4q0 2.0431-1.0446 3.1645-1.0292 1.1214-2.7958 1.1214-1.0907 0-1.9509-0.49158-0.84489-0.50693-1.3365-1.4594-0.49158-0.96778-0.49158-2.335 0-2.0431 1.0139-3.1491 1.0292-1.106 2.8112-1.106 1.106 0 1.9663 0.50694 0.86026 0.49157 1.3365 1.444 0.49158 0.93706 0.49158 2.3042zm-6.2215 0q0 1.4594 0.56838 2.3196 0.58374 0.84489 1.8434 0.84489 1.2443 0 1.828-0.84489 0.58374-0.86025 0.58374-2.3196 0-1.4594-0.58374-2.2889-0.58375-0.82953-1.8434-0.82953t-1.828 0.82953-0.56838 2.2889z"/>
<path d="m125.64 188.69q-1.106 0-1.9509-0.44549-0.84489-0.44549-1.3365-1.3826-0.47622-0.93707-0.47622-2.3964 0-1.5208 0.49158-2.4732 0.50693-0.95243 1.3826-1.3979t1.9817-0.44549q0.61447 0 1.1982 0.13826 0.59911 0.12289 0.96779 0.30723l-0.41477 1.1214q-0.36868-0.13826-0.86025-0.26115-0.49158-0.1229-0.9217-0.1229-2.4272 0-2.4272 3.1184 0 1.4901 0.58374 2.2889 0.59911 0.78345 1.7666 0.78345 0.66055 0 1.1828-0.13826 0.5223-0.13825 0.95242-0.33795v1.1982q-0.41476 0.21506-0.9217 0.3226-0.49157 0.12289-1.1982 0.12289z"/>
<path d="m136.4 176.86v6.0986q0 0.24579-0.0307 0.6452-0.0154 0.3994-0.0307 0.69127h0.0614q0.0922-0.12289 0.27651-0.35332 0.18434-0.23042 0.36868-0.46085 0.19971-0.24578 0.33796-0.3994l2.6268-2.7805h1.5823l-3.3335 3.5178 3.5639 4.716h-1.6283l-2.8573-3.8404-0.93707 0.81417v3.0262h-1.3365v-11.675z"/>
<path d="m149.32 177.22q0.30724 0 0.53766 0.21506 0.24579 0.1997 0.24579 0.64519t-0.24579 0.66056q-0.23042 0.1997-0.53766 0.1997-0.33795 0-0.56838-0.1997-0.23042-0.21507-0.23042-0.66056t0.23042-0.64519q0.23043-0.21506 0.56838-0.21506zm0.66056 3.0877v8.2339h-1.3518v-8.2339z"/>
<path d="m161.92 180.15q1.4747 0 2.2274 0.722 0.75272 0.722 0.75272 2.3043v5.3612h-1.3365v-5.2691q0-1.9817-1.8434-1.9817-1.3672 0-1.8895 0.76808-0.5223 0.76809-0.5223 2.2121v4.2706h-1.3518v-8.2339h1.0907l0.1997 1.1214h0.0768q0.39941-0.64519 1.106-0.95242 0.70664-0.3226 1.4901-0.3226z"/>
<path d="m175.73 180.15q0.81417 0 1.4594 0.30724 0.66055 0.30723 1.1214 0.93706h0.0768l0.18434-1.0907h1.0753v8.3721q0 1.7666-0.90634 2.6576-0.89098 0.89098-2.7805 0.89098-1.8127 0-2.9648-0.5223v-1.2443q1.2136 0.6452 3.0416 0.6452 1.06 0 1.6591-0.62983 0.61447-0.61447 0.61447-1.6898v-0.3226q0-0.18434 0.0154-0.52229 0.0154-0.35332 0.0307-0.49158h-0.0615q-0.82953 1.2443-2.55 1.2443-1.5976 0-2.504-1.1214-0.89098-1.1214-0.89098-3.1338 0-1.9663 0.89098-3.1184 0.90634-1.1675 2.4886-1.1675zm0.18434 1.1368q-1.0292 0-1.5976 0.82953-0.56838 0.81417-0.56838 2.335t0.55302 2.335q0.55302 0.79881 1.6437 0.79881 1.2443 0 1.8127-0.66056 0.56838-0.67591 0.56838-2.166v-0.32259q0-1.6744-0.58374-2.4118-0.58375-0.73736-1.828-0.73736z"/>
</g>
<g stroke-width=".26458" aria-label="Qt Advanced ">
<path d="m100.61 89.668q0 2.0124-0.81417 3.441-0.79881 1.4133-2.3811 1.9356l2.6269 2.7344h-1.9817l-2.1199-2.4732q-0.09217 0-0.1997 0-0.09217 0.01536-0.18434 0.01536-1.7051 0-2.8419-0.70664-1.1214-0.70664-1.6744-1.9817-0.55302-1.275-0.55302-2.9802 0-1.6744 0.55302-2.9341 0.55302-1.275 1.6744-1.9817 1.1368-0.70664 2.8573-0.70664 1.6437 0 2.7651 0.70664 1.1214 0.69128 1.6898 1.9663 0.58374 1.2597 0.58374 2.9648zm-8.664 0q0 2.0738 0.87562 3.272 0.87562 1.1829 2.7344 1.1829 1.8588 0 2.719-1.1829 0.87562-1.1982 0.87562-3.272 0-2.0738-0.86026-3.2413-0.86026-1.1829-2.719-1.1829-1.8741 0-2.7497 1.1829-0.87562 1.1675-0.87562 3.2413z"/>
<path d="m105.6 94.215q0.30723 0 0.62983-0.04609 0.32259-0.04609 0.52229-0.12289v1.0292q-0.21506 0.10753-0.61446 0.16898-0.39941 0.07681-0.76809 0.07681-0.64519 0-1.1982-0.21506-0.53766-0.23042-0.87562-0.78345-0.33796-0.55302-0.33796-1.5515v-4.7929h-1.1675v-0.64519l1.1829-0.53766 0.53766-1.7512h0.7988v1.8895h2.3811v1.0446h-2.3811v4.7621q0 0.75272 0.35332 1.1214 0.36868 0.35332 0.93707 0.35332z"/>
<path d="m119.46 95.168-1.3211-3.3949h-4.3474l-1.3058 3.3949h-1.3979l4.2859-11.014h1.2443l4.2706 11.014zm-1.7359-4.6239-1.2289-3.3181q-0.0461-0.12289-0.15362-0.44549-0.10753-0.3226-0.21507-0.66055-0.0922-0.35332-0.15361-0.53766-0.1229 0.47621-0.26115 0.93706-0.12289 0.44549-0.21507 0.70664l-1.2443 3.3181z"/>
<path d="m125.13 95.321q-1.5362 0-2.4579-1.06-0.9217-1.0753-0.9217-3.1952t0.9217-3.1952q0.93706-1.0907 2.4732-1.0907 0.95243 0 1.5515 0.35332 0.61447 0.35332 0.99851 0.86026h0.0922q-0.0307-0.1997-0.0614-0.58374-0.0307-0.3994-0.0307-0.62983v-3.2874h1.3518v11.675h-1.0907l-0.1997-1.106h-0.0614q-0.36868 0.5223-0.98314 0.89098-0.61447 0.36868-1.5823 0.36868zm0.21506-1.1214q1.3058 0 1.828-0.70664 0.53766-0.722 0.53766-2.166v-0.24579q0-1.5362-0.50694-2.3503-0.50694-0.82953-1.8741-0.82953-1.0907 0-1.6437 0.87562-0.53766 0.86026-0.53766 2.3196 0 1.4747 0.53766 2.2889 0.55302 0.81417 1.6591 0.81417z"/>
<path d="m133.47 95.168-3.1184-8.2339h1.444l1.7512 4.8543q0.12289 0.33796 0.26115 0.75272 0.13825 0.41477 0.24579 0.79881 0.10753 0.38404 0.15361 0.62983h0.0615q0.0461-0.24579 0.16898-0.62983 0.12289-0.3994 0.26115-0.79881 0.13825-0.41477 0.26115-0.75272l1.7512-4.8543h1.444l-3.1338 8.2339z"/>
<path d="m142.58 86.796q1.5054 0 2.2274 0.66055 0.722 0.66055 0.722 2.1046v5.607h-0.98315l-0.26115-1.1675h-0.0615q-0.53766 0.67591-1.1368 0.99851-0.59911 0.3226-1.6283 0.3226-1.1214 0-1.8588-0.58374-0.73736-0.59911-0.73736-1.8588 0-1.2289 0.96778-1.8895 0.96779-0.67591 2.9802-0.73736l1.3979-0.04609v-0.49158q0-1.0292-0.44549-1.4286t-1.2597-0.3994q-0.64519 0-1.2289 0.1997-0.58374 0.18434-1.0907 0.43013l-0.41476-1.0139q0.53766-0.29187 1.275-0.49158 0.73736-0.21506 1.5362-0.21506zm1.613 4.3474-1.2136 0.04609q-1.5362 0.06145-2.1353 0.49157-0.58375 0.43013-0.58375 1.2136 0 0.69128 0.41477 1.0139 0.43013 0.3226 1.0907 0.3226 1.0292 0 1.7205-0.56838 0.70664-0.58374 0.70664-1.782z"/>
<path d="m152.04 86.78q1.4747 0 2.2274 0.722 0.75272 0.722 0.75272 2.3043v5.3612h-1.3365v-5.2691q0-1.9817-1.8434-1.9817-1.3672 0-1.8895 0.76808t-0.5223 2.2121v4.2706h-1.3518v-8.2339h1.0907l0.1997 1.1214h0.0768q0.39941-0.64519 1.106-0.95243 0.70663-0.3226 1.4901-0.3226z"/>
<path d="m160.87 95.321q-1.106 0-1.9509-0.44549-0.8449-0.44549-1.3365-1.3826-0.47622-0.93706-0.47622-2.3964 0-1.5208 0.49158-2.4732 0.50694-0.95243 1.3826-1.3979 0.87562-0.44549 1.9817-0.44549 0.61447 0 1.1982 0.13826 0.59911 0.12289 0.96779 0.30723l-0.41476 1.1214q-0.36869-0.13826-0.86026-0.26115-0.49157-0.12289-0.9217-0.12289-2.4272 0-2.4272 3.1184 0 1.4901 0.58374 2.2889 0.59911 0.78345 1.7666 0.78345 0.66055 0 1.1828-0.13826 0.5223-0.13826 0.95243-0.33796v1.1982q-0.41477 0.21506-0.92171 0.3226-0.49157 0.12289-1.1982 0.12289z"/>
<path d="m168.13 86.78q1.0446 0 1.8127 0.46085 0.76809 0.46085 1.1675 1.3057 0.41477 0.82953 0.41477 1.9509v0.81417h-5.6378q0.0307 1.3979 0.70664 2.1353 0.69128 0.722 1.9202 0.722 0.78345 0 1.3826-0.13826 0.61447-0.15362 1.2597-0.43013v1.1829q-0.62983 0.27651-1.2443 0.3994-0.61447 0.13826-1.4594 0.13826-1.1828 0-2.0738-0.47621t-1.3979-1.4133q-0.49157-0.93706-0.49157-2.3196 0-1.3518 0.44549-2.3196 0.46085-0.96779 1.275-1.4901 0.82953-0.5223 1.9202-0.5223zm-0.0154 1.106q-0.96779 0-1.5362 0.62983-0.55302 0.61447-0.66055 1.7205h4.1937q-0.0154-1.0446-0.49157-1.6898-0.47622-0.66055-1.5054-0.66055z"/>
<path d="m176.53 95.321q-1.5362 0-2.4579-1.06-0.92171-1.0753-0.92171-3.1952t0.92171-3.1952q0.93706-1.0907 2.4732-1.0907 0.95243 0 1.5515 0.35332 0.61447 0.35332 0.99851 0.86026h0.0922q-0.0307-0.1997-0.0614-0.58374-0.0307-0.3994-0.0307-0.62983v-3.2874h1.3518v11.675h-1.0907l-0.1997-1.106h-0.0614q-0.36868 0.5223-0.98315 0.89098-0.61446 0.36868-1.5822 0.36868zm0.21506-1.1214q1.3058 0 1.828-0.70664 0.53766-0.722 0.53766-2.166v-0.24579q0-1.5362-0.50693-2.3503-0.50694-0.82953-1.8741-0.82953-1.0907 0-1.6437 0.87562-0.53766 0.86026-0.53766 2.3196 0 1.4747 0.53766 2.2889 0.55302 0.81417 1.6591 0.81417z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1024" height="1024" version="1.1" viewBox="0 0 270.93 270.93" xmlns="http://www.w3.org/2000/svg">
<path d="m-2.5e-6 -2.5e-6v270.93h270.93v-270.93z" fill="#ff9833" stroke-width=".26458" style="mix-blend-mode:normal"/>
<g fill="#fff" fill-opacity=".25">
<g transform="matrix(.12402 0 0 .12402 71.967 73.674)" stroke-width="4.7887">
<path d="m405.33 234.66v256h469.33v-256z" style="mix-blend-mode:normal"/>
<path d="m661.33 533.33v256h213.33v-256z" style="mix-blend-mode:normal"/>
<path d="m405.33 533.33v256h213.33v-256z" style="mix-blend-mode:normal"/>
<path d="m149.33 234.66v554.67h213.33v-554.67z" style="mix-blend-mode:normal"/>
</g>
<g stroke-width=".26458" aria-label="Docking">
<path d="m100.07 182.94q0 2.7805-1.5208 4.1938-1.5054 1.3979-4.2091 1.3979h-3.057v-10.968h3.3796q1.6437 0 2.8573 0.61447 1.2289 0.61446 1.8895 1.8127 0.66055 1.1982 0.66055 2.9494zm-1.4594 0.0461q0-2.1967-1.0907-3.2106-1.0753-1.0292-3.057-1.0292h-1.7973v8.6026h1.4901q4.4549 0 4.4549-4.3627z"/>
<path d="m114.84 184.4q0 2.0431-1.0446 3.1645-1.0292 1.1214-2.7958 1.1214-1.0907 0-1.9509-0.49158-0.84489-0.50693-1.3365-1.4594-0.49158-0.96778-0.49158-2.335 0-2.0431 1.0139-3.1491 1.0292-1.106 2.8112-1.106 1.106 0 1.9663 0.50694 0.86026 0.49157 1.3365 1.444 0.49158 0.93706 0.49158 2.3042zm-6.2215 0q0 1.4594 0.56838 2.3196 0.58374 0.84489 1.8434 0.84489 1.2443 0 1.828-0.84489 0.58374-0.86025 0.58374-2.3196 0-1.4594-0.58374-2.2889-0.58375-0.82953-1.8434-0.82953t-1.828 0.82953-0.56838 2.2889z"/>
<path d="m125.64 188.69q-1.106 0-1.9509-0.44549-0.84489-0.44549-1.3365-1.3826-0.47622-0.93707-0.47622-2.3964 0-1.5208 0.49158-2.4732 0.50693-0.95243 1.3826-1.3979t1.9817-0.44549q0.61447 0 1.1982 0.13826 0.59911 0.12289 0.96779 0.30723l-0.41477 1.1214q-0.36868-0.13826-0.86025-0.26115-0.49158-0.1229-0.9217-0.1229-2.4272 0-2.4272 3.1184 0 1.4901 0.58374 2.2889 0.59911 0.78345 1.7666 0.78345 0.66055 0 1.1828-0.13826 0.5223-0.13825 0.95242-0.33795v1.1982q-0.41476 0.21506-0.9217 0.3226-0.49157 0.12289-1.1982 0.12289z"/>
<path d="m136.4 176.86v6.0986q0 0.24579-0.0307 0.6452-0.0154 0.3994-0.0307 0.69127h0.0614q0.0922-0.12289 0.27651-0.35332 0.18434-0.23042 0.36868-0.46085 0.19971-0.24578 0.33796-0.3994l2.6268-2.7805h1.5823l-3.3335 3.5178 3.5639 4.716h-1.6283l-2.8573-3.8404-0.93707 0.81417v3.0262h-1.3365v-11.675z"/>
<path d="m149.32 177.22q0.30724 0 0.53766 0.21506 0.24579 0.1997 0.24579 0.64519t-0.24579 0.66056q-0.23042 0.1997-0.53766 0.1997-0.33795 0-0.56838-0.1997-0.23042-0.21507-0.23042-0.66056t0.23042-0.64519q0.23043-0.21506 0.56838-0.21506zm0.66056 3.0877v8.2339h-1.3518v-8.2339z"/>
<path d="m161.92 180.15q1.4747 0 2.2274 0.722 0.75272 0.722 0.75272 2.3043v5.3612h-1.3365v-5.2691q0-1.9817-1.8434-1.9817-1.3672 0-1.8895 0.76808-0.5223 0.76809-0.5223 2.2121v4.2706h-1.3518v-8.2339h1.0907l0.1997 1.1214h0.0768q0.39941-0.64519 1.106-0.95242 0.70664-0.3226 1.4901-0.3226z"/>
<path d="m175.73 180.15q0.81417 0 1.4594 0.30724 0.66055 0.30723 1.1214 0.93706h0.0768l0.18434-1.0907h1.0753v8.3721q0 1.7666-0.90634 2.6576-0.89098 0.89098-2.7805 0.89098-1.8127 0-2.9648-0.5223v-1.2443q1.2136 0.6452 3.0416 0.6452 1.06 0 1.6591-0.62983 0.61447-0.61447 0.61447-1.6898v-0.3226q0-0.18434 0.0154-0.52229 0.0154-0.35332 0.0307-0.49158h-0.0615q-0.82953 1.2443-2.55 1.2443-1.5976 0-2.504-1.1214-0.89098-1.1214-0.89098-3.1338 0-1.9663 0.89098-3.1184 0.90634-1.1675 2.4886-1.1675zm0.18434 1.1368q-1.0292 0-1.5976 0.82953-0.56838 0.81417-0.56838 2.335t0.55302 2.335q0.55302 0.79881 1.6437 0.79881 1.2443 0 1.8127-0.66056 0.56838-0.67591 0.56838-2.166v-0.32259q0-1.6744-0.58374-2.4118-0.58375-0.73736-1.828-0.73736z"/>
</g>
<g stroke-width=".26458" aria-label="Qt Advanced ">
<path d="m100.61 89.668q0 2.0124-0.81417 3.441-0.79881 1.4133-2.3811 1.9356l2.6269 2.7344h-1.9817l-2.1199-2.4732q-0.09217 0-0.1997 0-0.09217 0.01536-0.18434 0.01536-1.7051 0-2.8419-0.70664-1.1214-0.70664-1.6744-1.9817-0.55302-1.275-0.55302-2.9802 0-1.6744 0.55302-2.9341 0.55302-1.275 1.6744-1.9817 1.1368-0.70664 2.8573-0.70664 1.6437 0 2.7651 0.70664 1.1214 0.69128 1.6898 1.9663 0.58374 1.2597 0.58374 2.9648zm-8.664 0q0 2.0738 0.87562 3.272 0.87562 1.1829 2.7344 1.1829 1.8588 0 2.719-1.1829 0.87562-1.1982 0.87562-3.272 0-2.0738-0.86026-3.2413-0.86026-1.1829-2.719-1.1829-1.8741 0-2.7497 1.1829-0.87562 1.1675-0.87562 3.2413z"/>
<path d="m105.6 94.215q0.30723 0 0.62983-0.04609 0.32259-0.04609 0.52229-0.12289v1.0292q-0.21506 0.10753-0.61446 0.16898-0.39941 0.07681-0.76809 0.07681-0.64519 0-1.1982-0.21506-0.53766-0.23042-0.87562-0.78345-0.33796-0.55302-0.33796-1.5515v-4.7929h-1.1675v-0.64519l1.1829-0.53766 0.53766-1.7512h0.7988v1.8895h2.3811v1.0446h-2.3811v4.7621q0 0.75272 0.35332 1.1214 0.36868 0.35332 0.93707 0.35332z"/>
<path d="m119.46 95.168-1.3211-3.3949h-4.3474l-1.3058 3.3949h-1.3979l4.2859-11.014h1.2443l4.2706 11.014zm-1.7359-4.6239-1.2289-3.3181q-0.0461-0.12289-0.15362-0.44549-0.10753-0.3226-0.21507-0.66055-0.0922-0.35332-0.15361-0.53766-0.1229 0.47621-0.26115 0.93706-0.12289 0.44549-0.21507 0.70664l-1.2443 3.3181z"/>
<path d="m125.13 95.321q-1.5362 0-2.4579-1.06-0.9217-1.0753-0.9217-3.1952t0.9217-3.1952q0.93706-1.0907 2.4732-1.0907 0.95243 0 1.5515 0.35332 0.61447 0.35332 0.99851 0.86026h0.0922q-0.0307-0.1997-0.0614-0.58374-0.0307-0.3994-0.0307-0.62983v-3.2874h1.3518v11.675h-1.0907l-0.1997-1.106h-0.0614q-0.36868 0.5223-0.98314 0.89098-0.61447 0.36868-1.5823 0.36868zm0.21506-1.1214q1.3058 0 1.828-0.70664 0.53766-0.722 0.53766-2.166v-0.24579q0-1.5362-0.50694-2.3503-0.50694-0.82953-1.8741-0.82953-1.0907 0-1.6437 0.87562-0.53766 0.86026-0.53766 2.3196 0 1.4747 0.53766 2.2889 0.55302 0.81417 1.6591 0.81417z"/>
<path d="m133.47 95.168-3.1184-8.2339h1.444l1.7512 4.8543q0.12289 0.33796 0.26115 0.75272 0.13825 0.41477 0.24579 0.79881 0.10753 0.38404 0.15361 0.62983h0.0615q0.0461-0.24579 0.16898-0.62983 0.12289-0.3994 0.26115-0.79881 0.13825-0.41477 0.26115-0.75272l1.7512-4.8543h1.444l-3.1338 8.2339z"/>
<path d="m142.58 86.796q1.5054 0 2.2274 0.66055 0.722 0.66055 0.722 2.1046v5.607h-0.98315l-0.26115-1.1675h-0.0615q-0.53766 0.67591-1.1368 0.99851-0.59911 0.3226-1.6283 0.3226-1.1214 0-1.8588-0.58374-0.73736-0.59911-0.73736-1.8588 0-1.2289 0.96778-1.8895 0.96779-0.67591 2.9802-0.73736l1.3979-0.04609v-0.49158q0-1.0292-0.44549-1.4286t-1.2597-0.3994q-0.64519 0-1.2289 0.1997-0.58374 0.18434-1.0907 0.43013l-0.41476-1.0139q0.53766-0.29187 1.275-0.49158 0.73736-0.21506 1.5362-0.21506zm1.613 4.3474-1.2136 0.04609q-1.5362 0.06145-2.1353 0.49157-0.58375 0.43013-0.58375 1.2136 0 0.69128 0.41477 1.0139 0.43013 0.3226 1.0907 0.3226 1.0292 0 1.7205-0.56838 0.70664-0.58374 0.70664-1.782z"/>
<path d="m152.04 86.78q1.4747 0 2.2274 0.722 0.75272 0.722 0.75272 2.3043v5.3612h-1.3365v-5.2691q0-1.9817-1.8434-1.9817-1.3672 0-1.8895 0.76808t-0.5223 2.2121v4.2706h-1.3518v-8.2339h1.0907l0.1997 1.1214h0.0768q0.39941-0.64519 1.106-0.95243 0.70663-0.3226 1.4901-0.3226z"/>
<path d="m160.87 95.321q-1.106 0-1.9509-0.44549-0.8449-0.44549-1.3365-1.3826-0.47622-0.93706-0.47622-2.3964 0-1.5208 0.49158-2.4732 0.50694-0.95243 1.3826-1.3979 0.87562-0.44549 1.9817-0.44549 0.61447 0 1.1982 0.13826 0.59911 0.12289 0.96779 0.30723l-0.41476 1.1214q-0.36869-0.13826-0.86026-0.26115-0.49157-0.12289-0.9217-0.12289-2.4272 0-2.4272 3.1184 0 1.4901 0.58374 2.2889 0.59911 0.78345 1.7666 0.78345 0.66055 0 1.1828-0.13826 0.5223-0.13826 0.95243-0.33796v1.1982q-0.41477 0.21506-0.92171 0.3226-0.49157 0.12289-1.1982 0.12289z"/>
<path d="m168.13 86.78q1.0446 0 1.8127 0.46085 0.76809 0.46085 1.1675 1.3057 0.41477 0.82953 0.41477 1.9509v0.81417h-5.6378q0.0307 1.3979 0.70664 2.1353 0.69128 0.722 1.9202 0.722 0.78345 0 1.3826-0.13826 0.61447-0.15362 1.2597-0.43013v1.1829q-0.62983 0.27651-1.2443 0.3994-0.61447 0.13826-1.4594 0.13826-1.1828 0-2.0738-0.47621t-1.3979-1.4133q-0.49157-0.93706-0.49157-2.3196 0-1.3518 0.44549-2.3196 0.46085-0.96779 1.275-1.4901 0.82953-0.5223 1.9202-0.5223zm-0.0154 1.106q-0.96779 0-1.5362 0.62983-0.55302 0.61447-0.66055 1.7205h4.1937q-0.0154-1.0446-0.49157-1.6898-0.47622-0.66055-1.5054-0.66055z"/>
<path d="m176.53 95.321q-1.5362 0-2.4579-1.06-0.92171-1.0753-0.92171-3.1952t0.92171-3.1952q0.93706-1.0907 2.4732-1.0907 0.95243 0 1.5515 0.35332 0.61447 0.35332 0.99851 0.86026h0.0922q-0.0307-0.1997-0.0614-0.58374-0.0307-0.3994-0.0307-0.62983v-3.2874h1.3518v11.675h-1.0907l-0.1997-1.106h-0.0614q-0.36868 0.5223-0.98315 0.89098-0.61446 0.36868-1.5822 0.36868zm0.21506-1.1214q1.3058 0 1.828-0.70664 0.53766-0.722 0.53766-2.166v-0.24579q0-1.5362-0.50693-2.3503-0.50694-0.82953-1.8741-0.82953-1.0907 0-1.6437 0.87562-0.53766 0.86026-0.53766 2.3196 0 1.4747 0.53766 2.2889 0.55302 0.81417 1.6591 0.81417z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -0,0 +1,6 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024">
<desc>color_lens icon - Licensed under Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - Created with Iconfu.com - Derivative work of Material icons (Copyright Google Inc.)</desc>
<g fill="#03b8e5" fill-rule="nonzero" style="mix-blend-mode: normal">
<path d="M896,469.33c0,117.76 -95.57,213.34 -213.33,213.34h-75.52c-35.41,0 -64,28.59 -64,64c0,16.21 6.4,31.15 16.21,42.24c10.24,11.52 16.64,26.45 16.64,43.09c0,35.41 -28.59,64 -64,64c-212.05,0 -384,-171.95 -384,-384c0,-212.05 171.95,-384 384,-384c212.05,0 384,152.74 384,341.33zM341.33,448c0,-35.41 -28.59,-64 -64,-64c-35.41,0 -64,28.59 -64,64c0,35.41 28.59,64 64,64c35.41,0 64,-28.59 64,-64zM469.33,277.33c0,-35.41 -28.59,-64 -64,-64c-35.41,0 -64,28.59 -64,64c0,35.41 28.59,64 64,64c35.41,0 64,-28.59 64,-64zM682.67,277.33c0,-35.41 -28.59,-64 -64,-64c-35.41,0 -64,28.59 -64,64c0,35.41 28.59,64 64,64c35.41,0 64,-28.59 64,-64zM810.67,448c0,-35.41 -28.59,-64 -64,-64c-35.41,0 -64,28.59 -64,64c0,35.41 28.59,64 64,64c35.41,0 64,-28.59 64,-64z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,6 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024">
<desc>crop_original icon - Licensed under Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - Created with Iconfu.com - Derivative work of Material icons (Copyright Google Inc.)</desc>
<g fill="#03b8e5" fill-rule="nonzero" style="mix-blend-mode: normal">
<path d="M896,213.33v597.34c0,46.93 -38.4,85.33 -85.33,85.33h-597.34c-46.93,0 -85.33,-38.4 -85.33,-85.33v-597.34c0,-46.93 38.4,-85.33 85.33,-85.33h597.34c46.93,0 85.33,38.4 85.33,85.33zM810.67,213.33h-597.34v597.34h597.34zM746.67,725.33h-469.34l117.34,-150.61l83.62,100.69l117.34,-151.04z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 700 B

View File

@@ -0,0 +1,6 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024">
<desc>find_in_page icon - Licensed under Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - Created with Iconfu.com - Derivative work of Material icons (Copyright Google Inc.)</desc>
<g fill="#03b8e5" fill-rule="nonzero" style="mix-blend-mode: normal">
<path d="M689.92,672c22.19,-33.71 35.41,-73.81 35.41,-117.33c0,-117.76 -95.57,-213.34 -213.33,-213.34c-117.76,0 -213.33,95.58 -213.33,213.34c0,117.76 95.57,213.33 213.33,213.33c43.52,0 83.63,-13.22 117.76,-35.41l189.01,189.01c-14.51,10.67 -31.57,17.07 -50.77,17.07h-512.43c-46.93,0 -84.9,-38.41 -84.9,-85.34l0.42,-682.66c0,-46.93 37.98,-85.34 84.91,-85.34h341.33l256,256v494.51zM512,426.67c70.83,0 128,57.17 128,128c0,70.83 -57.17,128 -128,128c-70.83,0 -128,-57.17 -128,-128c0,-70.83 57.17,-128 128,-128z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 915 B

View File

@@ -0,0 +1,6 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024">
<desc>font_download icon - Licensed under Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - Created with Iconfu.com - Derivative work of Material icons (Copyright Google Inc.)</desc>
<g fill="#03b8e5" fill-rule="nonzero" style="mix-blend-mode: normal">
<path d="M938.67,170.67v682.66c0,46.93 -38.41,85.34 -85.34,85.34h-682.66c-46.93,0 -85.34,-38.41 -85.34,-85.34v-682.66c0,-46.93 38.41,-85.34 85.34,-85.34h682.66c46.93,0 85.34,38.41 85.34,85.34zM769.71,789.33l-218.03,-554.66h-79.36l-218.03,554.66h89.18l47.78,-128h240.64l48.64,128zM512,340.48l88.32,235.52h-176.64z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 724 B

6
demo/images/panorama.svg Normal file
View File

@@ -0,0 +1,6 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024">
<desc>panorama icon - Licensed under Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - Created with Iconfu.com - Derivative work of Material icons (Copyright Google Inc.)</desc>
<g fill="#03b8e5" fill-rule="nonzero" style="mix-blend-mode: normal">
<path d="M896,853.33h-768c-46.93,0 -85.33,-38.4 -85.33,-85.33v-512c0,-46.93 38.4,-85.33 85.33,-85.33h768c46.93,0 85.33,38.4 85.33,85.33v512c0,46.93 -38.4,85.33 -85.33,85.33zM213.33,725.33h597.34l-192,-256l-149.34,192.43l-106.66,-128.43z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 643 B

View File

@@ -0,0 +1,6 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024">
<desc>perm_media icon - Licensed under Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - Created with Iconfu.com - Derivative work of Material icons (Copyright Google Inc.)</desc>
<g fill="#03b8e5" fill-rule="nonzero" style="mix-blend-mode: normal">
<path d="M1024,256v426.67c0,46.93 -38.4,85.33 -85.33,85.33h-682.67c-46.93,0 -85.33,-38.4 -85.33,-85.33l0.42,-512c0,-46.93 37.98,-85.34 84.91,-85.34h256l85.33,85.34h341.34c46.93,0 85.33,38.4 85.33,85.33zM85.33,853.33h768v85.34h-768c-46.93,0 -85.33,-38.41 -85.33,-85.34l0.43,-384h-0.43v-213.33h85.33zM896,640l-149.33,-192l-106.67,128.43l-149.33,-192.43l-192,256z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 769 B

6
demo/images/photo.svg Normal file
View File

@@ -0,0 +1,6 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024">
<desc>photo icon - Licensed under Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - Created with Iconfu.com - Derivative work of Material icons (Copyright Google Inc.)</desc>
<g fill="#03b8e5" fill-rule="nonzero" style="mix-blend-mode: normal">
<path d="M810.67,896h-597.34c-46.93,0 -85.33,-38.4 -85.33,-85.33v-597.34c0,-46.93 38.4,-85.33 85.33,-85.33h597.34c46.93,0 85.33,38.4 85.33,85.33v597.34c0,46.93 -38.4,85.33 -85.33,85.33zM213.33,768h597.34l-192,-256l-149.34,192.43l-106.66,-128.43z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 649 B

6
demo/images/tab.svg Normal file
View File

@@ -0,0 +1,6 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024">
<desc>tab icon - Licensed under Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - Created with Iconfu.com - Derivative work of Material icons (Copyright Google Inc.)</desc>
<g fill="#03b8e5" fill-rule="nonzero" style="mix-blend-mode: normal">
<path d="M981.33,213.33v597.34c0,46.93 -38.4,85.33 -85.33,85.33h-768c-46.93,0 -85.33,-38.4 -85.33,-85.33v-597.34c0,-46.93 38.4,-85.33 85.33,-85.33h768c46.93,0 85.33,38.4 85.33,85.33zM896,384h-341.33v-170.67h-426.67v597.34h768z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 628 B

6
demo/images/zoom_in.svg Normal file
View File

@@ -0,0 +1,6 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024">
<desc>zoom_in icon - Licensed under Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - Created with Iconfu.com - Derivative work of Material icons (Copyright Google Inc.)</desc>
<g fill="#03b8e5" fill-rule="nonzero" style="mix-blend-mode: normal">
<path d="M874.24,810.67l-63.57,63.57l-213.34,-212.91v-33.7l-11.52,-11.95c-48.64,41.81 -111.79,66.99 -180.48,66.99c-153.17,0 -277.33,-124.17 -277.33,-277.34c0,-153.17 124.16,-277.33 277.33,-277.33c153.17,0 277.34,124.16 277.34,277.33c0,68.69 -25.18,131.84 -66.99,180.48l11.95,11.52h33.7zM597.33,405.33c0,-106.24 -85.76,-192 -192,-192c-106.24,0 -192,85.76 -192,192c0,106.24 85.76,192 192,192c106.24,0 192,-85.76 192,-192zM512,426.67h-85.33v85.33h-42.67v-85.33h-85.33v-42.67h85.33v-85.33h42.67v85.33h85.33z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 909 B

6
demo/images/zoom_out.svg Normal file
View File

@@ -0,0 +1,6 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024">
<desc>zoom_out icon - Licensed under Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - Created with Iconfu.com - Derivative work of Material icons (Copyright Google Inc.)</desc>
<g fill="#03b8e5" fill-rule="nonzero" style="mix-blend-mode: normal">
<path d="M874.24,810.67l-63.57,63.57l-213.34,-212.91v-33.7l-11.52,-11.95c-48.64,41.81 -111.79,66.99 -180.48,66.99c-153.17,0 -277.33,-124.17 -277.33,-277.34c0,-153.17 124.16,-277.33 277.33,-277.33c153.17,0 277.34,124.16 277.34,277.33c0,68.69 -25.18,131.84 -66.99,180.48l11.95,11.52h33.7zM597.33,405.33c0,-106.24 -85.76,-192 -192,-192c-106.24,0 -192,85.76 -192,192c0,106.24 85.76,192 192,192c106.24,0 192,-85.76 192,-192zM298.67,384h213.33v42.67h-213.33z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 859 B

View File

@@ -0,0 +1,6 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024">
<desc>zoom_out_map icon - Licensed under Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - Created with Iconfu.com - Derivative work of Material icons (Copyright Google Inc.)</desc>
<g fill="#03b8e5" fill-rule="nonzero" style="mix-blend-mode: normal">
<path d="M896,896h-256l98.13,-98.13l-123.3,-122.46l60.58,-60.58l122.46,123.3l98.13,-98.13zM896,128v256l-98.13,-98.13l-122.46,123.3l-60.58,-60.58l123.3,-122.46l-98.13,-98.13zM128,896v-256l98.13,98.13l122.46,-123.3l60.58,60.58l-123.3,122.46l98.13,98.13zM128,128h256l-98.13,98.13l123.3,122.46l-60.58,60.58l-122.46,-123.3l-98.13,98.13z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 742 B

View File

@@ -45,17 +45,18 @@ int main(int argc, char *argv[])
QApplication a(argc, argv);
a.setApplicationName("Advanced Docking System Demo");
a.setQuitOnLastWindowClosed(true);
QFile StyleSheetFile(":/adsdemo/app.css");
StyleSheetFile.open(QIODevice::ReadOnly);
QTextStream StyleSheetStream(&StyleSheetFile);
a.setStyleSheet(StyleSheetStream.readAll());
StyleSheetFile.close();
a.setWindowIcon(QIcon(":/adsdemo/images/ads_icon2.svg"));
qInstallMessageHandler(myMessageOutput);
qDebug() << "Message handler test";
CMainWindow mw;
mw.show();
QFile StyleSheetFile(":/adsdemo/app.css");
StyleSheetFile.open(QIODevice::ReadOnly);
QTextStream StyleSheetStream(&StyleSheetFile);
a.setStyleSheet(StyleSheetStream.readAll());
StyleSheetFile.close();
return a.exec();
}

View File

@@ -0,0 +1,379 @@
/*
* Visual Studio like light theme
*/
/*****************************************************************************
* CDockManager
*****************************************************************************/
ads--CDockManager
{
background: palette(window);
}
/*****************************************************************************
* CDockContainerWidget
*****************************************************************************/
ads--CDockContainerWidget {
background: palette(window);
padding: 2px;
}
/*****************************************************************************
* CDockAreaWidget
*****************************************************************************/
ads--CDockAreaWidget {
background: palette(window);
/*border: 1px solid palette(dark);*/
}
ads--CDockAreaTitleBar {
background: transparent;
border-bottom: 2px solid rgb(204, 204, 204);
padding-bottom: 0px;
}
ads--CTitleBarButton {
padding: 0px 0px;
background: transparent;
border: none;
}
ads--CTitleBarButton:hover {
background: rgba(0, 0, 0, 24);
}
ads--CTitleBarButton:pressed {
background: rgba(0, 0, 0, 48);
}
QScrollArea#dockWidgetScrollArea {
padding: 0px;
border: none;
}
#tabsMenuButton::menu-indicator {
image: none;
}
#dockAreaCloseButton {
qproperty-icon: url(:/ads/images/close-button.svg),
url(:/ads/images/close-button-disabled.svg) disabled;
qproperty-iconSize: 16px;
}
#detachGroupButton {
qproperty-icon: url(:/ads/images/detach-button.svg),
url(:/ads/images/detach-button-disabled.svg) disabled;
qproperty-iconSize: 16px;
}
ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar {
border-bottom: 2px solid palette(highlight);
}
/*****************************************************************************
* CDockWidgetTab
*****************************************************************************/
ads--CDockWidgetTab {
background: palette(window);
border: none;
padding: 0 0px;
qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/
}
ads--CDockWidgetTab[activeTab="true"] {
background: rgb(204, 204, 204);
}
ads--CDockWidgetTab QLabel {
color: palette(foreground);
}
ads--CDockWidgetTab[activeTab="true"] QLabel {
color: palette(foreground);
}
#tabCloseButton {
margin-top: 2px;
background: none;
border: none;
padding: 0px -2px;
qproperty-icon: url(:/ads/images/close-button.svg),
url(:/ads/images/close-button-disabled.svg) disabled;
qproperty-iconSize: 16px;
}
#tabCloseButton:hover {
/*border: 1px solid rgba(0, 0, 0, 32);*/
background: rgba(0, 0, 0, 24);
}
#tabCloseButton:pressed {
background: rgba(0, 0, 0, 48);
}
/* Focus related styling */
ads--CDockWidgetTab[focused="true"] {
background: palette(highlight);
border-color: palette(highlight);
}
ads--CDockWidgetTab[focused="true"] > #tabCloseButton {
qproperty-icon: url(:/ads/images/close-button-focused.svg)
}
ads--CDockWidgetTab[focused="true"]>#tabCloseButton:hover {
background: rgba(255, 255, 255, 48);
}
ads--CDockWidgetTab[focused="true"]>#tabCloseButton:pressed {
background: rgba(255, 255, 255, 92);
}
ads--CDockWidgetTab[focused="true"] QLabel {
color: palette(light);
}
/*****************************************************************************
* CDockWidget
*****************************************************************************/
ads--CDockWidget {
background: palette(light);
border: 1px solid rgb(204, 204, 204);
border-top: none;
}
/*****************************************************************************
*
* Styling of auto hide functionality
*
*****************************************************************************/
/*****************************************************************************
* CAutoHideTab
*****************************************************************************/
ads--CAutoHideTab {
qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/
background: none;
border: none;
padding-left: 2px;
padding-right: 0px;
text-align: center;
min-height: 20px;
padding-bottom: 2px;
}
ads--CAutoHideTab:hover
{
color: palette(highlight);
}
ads--CAutoHideTab[iconOnly="false"][sideBarLocation="0"],
ads--CAutoHideTab[iconOnly="false"][sideBarLocation="2"] {
border-top: 6px solid rgba(0, 0, 0, 48);
}
ads--CAutoHideTab[iconOnly="false"][sideBarLocation="1"],
ads--CAutoHideTab[iconOnly="false"][sideBarLocation="3"] {
border-bottom: 6px solid rgba(0, 0, 0, 48);
}
ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="0"],
ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="2"],
ads--CAutoHideTab[iconOnly="false"][sideBarLocation="0"][activeTab="true"],
ads--CAutoHideTab[iconOnly="false"][sideBarLocation="2"][activeTab="true"] {
border-top: 6px solid palette(highlight);
}
ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="1"],
ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="3"],
ads--CAutoHideTab[iconOnly="false"][sideBarLocation="1"][activeTab="true"],
ads--CAutoHideTab[iconOnly="false"][sideBarLocation="3"][activeTab="true"] {
border-bottom: 6px solid palette(highlight);
}
/**
* Auto hide tabs with icon only
*/
ads--CAutoHideTab[iconOnly="true"][sideBarLocation="0"] {
border-top: 6px solid rgba(0, 0, 0, 48);
}
ads--CAutoHideTab[iconOnly="true"][sideBarLocation="1"] {
border-left: 6px solid rgba(0, 0, 0, 48);
}
ads--CAutoHideTab[iconOnly="true"][sideBarLocation="2"] {
border-right: 6px solid rgba(0, 0, 0, 48);
}
ads--CAutoHideTab[iconOnly="true"][sideBarLocation="3"] {
border-bottom: 6px solid rgba(0, 0, 0, 48);
}
/**
* Auto hide tabs with icon only hover
*/
ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="0"],
ads--CAutoHideTab[iconOnly="true"][sideBarLocation="0"][activeTab="true"] {
border-top: 6px solid palette(highlight);
}
ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="1"],
ads--CAutoHideTab[iconOnly="true"][sideBarLocation="1"][activeTab="true"] {
border-left: 6px solid palette(highlight);
}
ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="2"],
ads--CAutoHideTab[iconOnly="true"][sideBarLocation="2"][activeTab="true"] {
border-right: 6px solid palette(highlight);
}
ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="3"],
ads--CAutoHideTab[iconOnly="true"][sideBarLocation="3"][activeTab="true"] {
border-bottom: 6px solid palette(highlight);
}
/*****************************************************************************
* CAutoHideSideBar
*****************************************************************************/
ads--CAutoHideSideBar{
background: palette(window);
border: none;
qproperty-spacing: 12;
}
#sideTabsContainerWidget {
background: transparent;
}
ads--CAutoHideSideBar[sideBarLocation="0"] {
border-bottom: 1px solid palette(dark);
}
ads--CAutoHideSideBar[sideBarLocation="1"] {
border-right: 1px solid palette(dark);
}
ads--CAutoHideSideBar[sideBarLocation="2"] {
border-left: 1px solid palette(dark);
}
ads--CAutoHideSideBar[sideBarLocation="3"] {
border-top: 1px solid palette(dark);
}
/*****************************************************************************
* CAutoHideDockContainer
*****************************************************************************/
ads--CAutoHideDockContainer {
background: palette(window);
}
ads--CAutoHideDockContainer ads--CDockAreaTitleBar {
background: palette(highlight);
padding: 0px;
border: none;
}
/*
* This is required because the ads--CDockAreaWidget[focused="true"] will
* overwrite the ads--CAutoHideDockContainer ads--CDockAreaTitleBar rule
*/
ads--CAutoHideDockContainer ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar {
background: palette(highlight);
padding: 0px;
border: none;
}
#autoHideTitleLabel {
padding-left: 4px;
color: palette(light);
}
/*****************************************************************************
* CAutoHideDockContainer titlebar buttons
*****************************************************************************/
#dockAreaAutoHideButton {
qproperty-icon: url(:/ads/images/vs-pin-button.svg);
qproperty-iconSize: 16px;
}
ads--CAutoHideDockContainer #dockAreaAutoHideButton {
qproperty-icon: url(:/ads/images/vs-pin-button-pinned-focused.svg);
qproperty-iconSize: 16px;
}
ads--CAutoHideDockContainer #dockAreaCloseButton{
qproperty-icon: url(:/ads/images/close-button-focused.svg)
}
ads--CAutoHideDockContainer ads--CTitleBarButton:hover {
background: rgba(255, 255, 255, 48);
}
ads--CAutoHideDockContainer ads--CTitleBarButton:pressed {
background: rgba(255, 255, 255, 96);
}
/*****************************************************************************
* CAutoHideDockContainer Titlebar and Buttons
*****************************************************************************/
/*****************************************************************************
* CResizeHandle
*****************************************************************************/
ads--CResizeHandle {
background: palette(window);
}
ads--CAutoHideDockContainer[sideBarLocation="0"] ads--CResizeHandle {
border-top: 1px solid palette(dark);
}
ads--CAutoHideDockContainer[sideBarLocation="1"] ads--CResizeHandle {
border-left: 1px solid palette(dark);
}
ads--CAutoHideDockContainer[sideBarLocation="2"] ads--CResizeHandle {
border-right: 1px solid palette(dark);
}
ads--CAutoHideDockContainer[sideBarLocation="3"] ads--CResizeHandle {
border-top: 1px solid palette(dark);
}

BIN
doc/AutoHide_Movie.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

BIN
doc/AutoHide_PinTo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1,123 +1,77 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
viewBox="0,0,1024,1024"
id="svg1145"
viewBox="0 0 1023.99 1023.99"
id="svg26"
sodipodi:docname="ads_icon.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
inkscape:export-filename="C:\CodingXP\cetoni_projects\QtAdvancedDockingSystem\doc\ads_icon_256.png"
inkscape:export-xdpi="24"
inkscape:export-ydpi="24">
<metadata
id="metadata1151">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
width="1023.99"
height="1023.99"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1149" />
id="defs30" />
<sodipodi:namedview
id="namedview28"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:zoom="0.12999302"
inkscape:cx="3277.099"
inkscape:cy="-257.70614"
inkscape:window-width="1920"
inkscape:window-height="1017"
id="namedview1147"
showgrid="false"
inkscape:zoom="0.32593202"
inkscape:cx="256.13402"
inkscape:cy="235.82602"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg1145" />
inkscape:current-layer="svg26"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<desc
id="desc1129">window_size icon - Licensed under Iconfu Standard License v1.0 (https://www.iconfu.com/iconfu_standard_license) - Incors GmbH</desc>
<path
id="path1797-1"
visibility="hidden"
d="M 71.53142,291.89723 H 950.1828 l 0.6743,0.6742 v 586.08 l -0.6743,0.6743 H 71.53142 l -0.6743,-0.6743 v -586.08 z"
inkscape:connector-curvature="0"
style="visibility:hidden;mix-blend-mode:normal;fill:#ffffff;fill-rule:nonzero;stroke-width:0.99999988;fill-opacity:1" />
<rect
transform="rotate(-90)"
y="412.13489"
x="-911.34436"
height="560.90375"
width="327.70862"
id="rect1739-8"
style="opacity:1;fill:#ffd292;fill-opacity:1;stroke:none;stroke-width:37.79526901;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke" />
<path
id="path1799"
d="M 988.40121,578.11175 V 651.2546 H 409.96541 V 578.11175 Z"
inkscape:connector-curvature="0"
style="mix-blend-mode:normal;fill:#546e7a;fill-rule:nonzero;stroke-width:0.99999988" />
<rect
style="opacity:1;fill:#b3c3cb;fill-opacity:1;stroke:none;stroke-width:37.79526901;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
id="rect1739-6-1"
width="655.41724"
height="338.99207"
x="-914.85529"
y="38.243896"
transform="rotate(-90)" />
<path
id="path1801-7"
d="m 73.1429,73.14287 h 877.7142 c 40.2857,0 73.1429,32.86857 73.1429,73.14285 V 914.2857 c 0,20.12571 -16.4458,36.57142 -36.5715,36.57142 H 36.5714 C 16.4343,950.85712 0,934.42284 0,914.2857 V 146.28572 C 0,106.00001 32.8571,73.14287 73.1429,73.14287 Z m 0,219.42856 V 877.71427 H 950.8571 V 292.57143 Z"
inkscape:connector-curvature="0"
style="mix-blend-mode:normal;fill:#546e7a;fill-rule:nonzero;stroke-width:0.99999988" />
<path
id="path1799-6"
d="M 359.8801,276.79402 H 433.023 V 886.78767 H 359.8801 Z"
inkscape:connector-curvature="0"
style="mix-blend-mode:normal;fill:#546e7a;fill-rule:nonzero;stroke-width:0.99999988" />
<circle
r="36.81749"
cy="169.78555"
cx="920.66248"
id="path1917-42"
style="opacity:1;fill:#ffa726;fill-opacity:1;stroke:none;stroke-width:63.79999924;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" />
<circle
r="36.81749"
cy="169.78555"
cx="817.22302"
id="path1917-4-6"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:63.79999924;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" />
<path
id="path1799-8"
d="m 615.67076,292.13464 v 73.14285 H 433.023 v -73.14285 z"
inkscape:connector-curvature="0"
style="mix-blend-mode:normal;fill:#95abb6;fill-rule:nonzero;stroke-width:0.99999994;fill-opacity:1" />
<path
id="path1799-8-1"
d="m 798.31852,292.13464 v 73.14285 H 615.67076 v -73.14285 z"
inkscape:connector-curvature="0"
style="mix-blend-mode:normal;fill:#c7d4d9;fill-rule:nonzero;stroke-width:0.99999994;fill-opacity:1" />
<path
id="path1799-8-7"
d="m 255.79066,292.57143 v 73.14285 H 73.1429 v -73.14285 z"
inkscape:connector-curvature="0"
style="mix-blend-mode:normal;fill:#dfe5e9;fill-opacity:1;fill-rule:nonzero;stroke-width:0.99999994" />
<path
id="path1799-8-7-6"
d="m 616.34083,651.15739 v 73.14285 H 433.69307 v -73.14285 z"
inkscape:connector-curvature="0"
style="mix-blend-mode:normal;fill:#ffba56;fill-opacity:1;fill-rule:nonzero;stroke-width:0.99999994" />
id="desc2">electric_iron icon - Licensed under Iconfu Standard License v1.0 (https://www.iconfu.com/iconfu_standard_license) - Incors GmbH</desc>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none"
x="1251.1022"
y="1305.4956"
id="text9788"><tspan
sodipodi:role="line"
id="tspan9786"
x="1251.1022"
y="1305.4956" /></text>
<g
id="g94691"
transform="translate(581.23034,1750.5233)">
<path
d="m 191.63966,-726.53328 h -521.75 c -138.69,0 -251.12,-112.43001 -251.12,-251.12 v -521.75002 c 0,-138.69 112.43,-251.12 251.12,-251.12 h 521.75 c 138.69,0 251.12,112.43 251.12,251.12 v 521.75002 c 0,138.68999 -112.43,251.12 -251.12,251.12 z"
fill="#707070"
id="path4-5"
style="mix-blend-mode:normal;fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero" />
<path
id="path927"
style="mix-blend-mode:normal;fill:#009ddd;fill-opacity:1;fill-rule:nonzero"
d="m -175.90039,-1515.8633 v 256 h 469.3301 v -256 z" />
<path
id="path16513"
style="mix-blend-mode:normal;fill:#ff9833;fill-opacity:1;fill-rule:nonzero"
d="m 80.099609,-1217.1934 v 256.00004 H 293.42969 v -256.00004 z" />
<path
id="path16513-5"
style="mix-blend-mode:normal;fill:#accb01;fill-opacity:1;fill-rule:nonzero"
d="m -175.90039,-1217.1933 v 256 H 37.42969 v -256 z" />
<path
id="path24788"
style="mix-blend-mode:normal;fill:#0083c3;fill-opacity:1;fill-rule:nonzero"
d="m -431.90039,-1515.8633 v 554.66994 h 213.33008 v -554.66994 z" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

33
doc/ads_logo.svg Normal file
View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1032" height="151.81" version="1.1" viewBox="0 0 1032 151.81" xmlns="http://www.w3.org/2000/svg">
<desc>electric_iron icon - Licensed under Iconfu Standard License v1.0 (https://www.iconfu.com/iconfu_standard_license) - Incors GmbH</desc>
<text x="1251.1022" y="1305.4956" fill="#000000" font-family="sans-serif" font-size="40px" style="line-height:1.25" xml:space="preserve"><tspan x="1251.1022" y="1305.4956"/></text>
<g transform="scale(.14825)" stroke-width="6.7454">
<g fill="#8f918f" aria-label="Qt Advanced Docking">
<path d="m1416.3 726.04q-93.219 0-148.72-61.942-55.196-61.942-55.196-160.99 0-105.18 56.729-168.35 57.035-63.475 155.47-63.475 88.926 0 143.82 61.022 55.196 60.715 55.196 159.45 0 109.16-56.422 171.72-17.479 19.625-38.944 32.811l106.71 81.26h-51.209l-83.1-66.848q-37.41 15.332-84.327 15.332zm3.0664-427.15q-76.66 0-126.34 55.502-49.369 55.502-49.369 145.35 0 90.766 46.916 144.74 46.916 53.662 125.11 53.662 81.567 0 129.1-53.049 47.53-53.356 47.53-148.41 0-93.219-46.61-145.35-46.303-52.436-126.34-52.436z"/>
<path d="m1826.9 714.08q-22.078 10.426-41.397 10.426-69.608 0-69.608-83.407v-210.97h-56.422v-25.758h56.422v-81.567q6.7461-2.4531 14.106-4.9063 7.3594-2.1465 14.106-4.5996v91.073h82.793v25.758h-82.793v207.29q0 32.504 10.119 47.223 10.426 14.412 34.957 14.412 17.479 0 37.717-11.346z"/>
<path d="m2353.7 718.37-50.289-136.76h-190.73l-50.289 136.76h-33.424l165.89-439.72h28.824l164.05 439.72zm-134.92-367.97q-3.373-9.1993-5.5195-18.092-2.1465-7.6661-4.5997-15.332h-1.2265q-5.2129 20.238-10.119 32.811l-73.901 203.92h169.57z"/>
<path d="m2679 718.37v-57.035h-1.2266q-15.332 29.744-45.383 47.223-30.051 17.479-67.768 17.479-57.955 0-94.752-42.317-36.49-42.317-36.49-116.83 0-76.047 39.864-122.96 40.17-47.223 103.95-47.223 70.528 0 100.58 57.955h1.2266v-201.16h28.211v464.87zm0-191.04q0-43.85-27.904-74.207-27.598-30.664-74.514-30.664-49.369 0-81.567 38.024-32.198 37.717-32.198 103.95 0 65.008 28.824 100.58 29.131 35.264 74.821 35.264 53.662 0 83.1-33.117 29.438-33.424 29.438-81.26z"/>
<path d="m2910.8 718.37h-25.758l-121.43-314h31.584l93.526 249.91q6.7462 18.092 9.5059 32.811h1.2266q3.9864-19.318 8.8926-31.584l96.592-251.14h30.664z"/>
<path d="m3280 718.37v-62.862h-1.2265q-15.026 32.197-43.85 51.516-28.518 19.012-63.475 19.012-44.77 0-70.834-25.145t-26.065-63.475q0-82.18 108.86-99.352l96.592-14.412q0-101.19-76.047-101.19-51.822 0-100.89 41.703v-34.037q17.479-13.799 47.223-23.611 30.051-9.8126 56.422-9.8126 48.449 0 74.821 30.051 26.678 30.051 26.678 87.393v204.22zm-86.473-156.39q-49.369 7.0528-69.301 22.998-19.932 15.639-19.932 51.209 0 27.904 18.398 45.996 18.705 18.092 51.822 18.092 45.383 0 75.434-33.424 30.051-33.731 30.051-86.78v-30.664z"/>
<path d="m3616.1 718.37v-182.76q0-113.15-81.567-113.15-45.383 0-74.514 33.424-29.131 33.117-29.131 82.18v180.31h-28.211v-314h28.211v57.035h1.2266q34.344-64.701 107.32-64.701 50.903 0 77.887 34.037 26.984 33.731 26.984 96.592v191.04z"/>
<path d="m3942.1 704.57q-34.957 21.465-83.407 21.465-64.088 0-103.34-43.85-39.25-44.156-39.25-115.3 0-74.821 44.156-122.35 44.156-47.836 113.46-47.836 35.877 0 69.608 14.719v31.891q-33.731-20.852-73.901-20.852-55.196 0-89.54 39.863-34.344 39.557-34.344 102.73 0 61.022 31.278 98.125 31.584 37.104 83.1 37.104 47.223 0 82.18-25.145z"/>
<path d="m4024.3 562.6q0 64.701 29.744 101.19 30.051 36.49 82.18 36.49 52.742 0 103.03-38.944v30.051q-48.756 34.651-108.86 34.651-60.715 0-98.126-43.543-37.41-43.543-37.41-122.96 0-68.688 38.944-115.6 39.25-47.223 101.81-47.223 58.569 0 89.846 41.09t31.278 112.23v12.572zm203-25.758q-1.8399-54.276-26.065-84.327-24.225-30.051-66.848-30.051-44.156 0-73.287 29.744-28.824 29.438-35.57 84.633z"/>
<path d="m4557.5 718.37v-57.035h-1.2266q-15.332 29.744-45.383 47.223-30.051 17.479-67.768 17.479-57.955 0-94.752-42.317-36.49-42.317-36.49-116.83 0-76.047 39.863-122.96 40.17-47.223 103.95-47.223 70.528 0 100.58 57.955h1.2266v-201.16h28.211v464.87zm0-191.04q0-43.85-27.904-74.207-27.598-30.664-74.514-30.664-49.369 0-81.567 38.024-32.197 37.717-32.197 103.95 0 65.008 28.824 100.58 29.131 35.264 74.821 35.264 53.662 0 83.1-33.117 29.438-33.424 29.438-81.26z"/>
<path d="m4864.5 718.37v-439.72h110.08q109.47 0 166.51 54.582 57.035 54.582 57.035 159.15 0 100.58-61.328 163.44-61.022 62.555-168.65 62.555zm30.358-411.82v384.22h68.994q97.819 0 150.25-50.596 52.436-50.903 52.436-146.57 0-187.05-196.56-187.05z"/>
<path d="m5407.5 726.04q-68.688 0-108.86-45.076-39.863-45.383-39.863-117.75 0-78.194 41.703-122.35 42.01-44.156 110.39-44.156 67.155 0 106.1 43.85 38.944 43.85 38.944 121.43 0 73.287-39.863 118.67-39.557 45.383-108.55 45.383zm2.1465-303.58q-55.502 0-88.62 37.41-32.811 37.41-32.811 103.95 0 61.635 32.197 99.045 32.197 37.41 88.006 37.41 56.729 0 87.393-36.797t30.664-102.11q0-67.155-30.664-103.03-30.358-35.877-86.166-35.877z"/>
<path d="m5837.1 704.57q-34.957 21.465-83.407 21.465-64.088 0-103.34-43.85-39.25-44.156-39.25-115.3 0-74.821 44.156-122.35 44.156-47.836 113.46-47.836 35.877 0 69.608 14.719v31.891q-33.731-20.852-73.901-20.852-55.196 0-89.54 39.863-34.344 39.557-34.344 102.73 0 61.022 31.278 98.125 31.584 37.104 83.1 37.104 47.223 0 82.18-25.145z"/>
<path d="m6092.2 718.37-150.25-155.16h-1.2266v155.16h-28.211v-464.87h28.211v299.59h1.2266l142.59-148.72h36.49l-149.03 152.09 160.99 161.91z"/>
<path d="m6205.1 325.26q-9.1992 0-16.252-6.7461-7.0528-6.7461-7.0528-17.172 0-10.119 7.0528-16.252 7.3594-6.4395 16.252-6.4395 9.506 0 16.559 6.1328 7.3594 6.1328 7.3594 16.559 0 9.8126-7.0527 16.865-7.0528 7.0528-16.865 7.0528zm-13.799 393.12v-314h28.211v314z"/>
<path d="m6533.5 718.37v-182.76q0-113.15-81.567-113.15-45.383 0-74.514 33.424-29.131 33.117-29.131 82.18v180.31h-28.211v-314h28.211v57.035h1.2265q34.344-64.701 107.32-64.701 50.902 0 77.887 34.037 26.984 33.731 26.984 96.592v191.04z"/>
<path d="m6907.3 695.07q0 88.62-38.637 129.71-38.637 41.09-120.2 41.09-45.383 0-93.526-23.918v-29.438q49.676 27.598 94.139 27.598 130.02 0 130.02-137.38v-40.783h-1.2266q-37.104 64.088-113.15 64.088-57.955 0-94.752-42.01-36.49-42.01-36.49-117.14t39.557-122.66q39.557-47.53 104.26-47.53 69.301 0 100.58 57.342h1.2266v-49.676h28.211zm-28.211-170.19q0-41.703-28.211-72.061-27.904-30.358-72.981-30.358-51.822 0-83.407 38.944-31.584 38.944-31.584 103.03 0 64.395 28.824 100.27 29.131 35.57 76.66 35.57 50.596 0 80.647-32.811 30.051-32.811 30.051-80.34z"/>
</g>
<g transform="translate(581.23 1750.5)">
<path d="m191.64-726.53h-521.75c-138.69 0-251.12-112.43-251.12-251.12v-521.75c0-138.69 112.43-251.12 251.12-251.12h521.75c138.69 0 251.12 112.43 251.12 251.12v521.75c0 138.69-112.43 251.12-251.12 251.12z" fill="#e0e0e0" style="mix-blend-mode:normal"/>
<path d="m-175.9-1515.9v256h469.33v-256z" fill="#009ddd" style="mix-blend-mode:normal"/>
<path d="m80.1-1217.2v256h213.33v-256z" fill="#ff9833" style="mix-blend-mode:normal"/>
<path d="m-175.9-1217.2v256h213.33v-256z" fill="#accb01" style="mix-blend-mode:normal"/>
<path d="m-431.9-1515.9v554.67h213.33v-554.67z" fill="#0083c3" style="mix-blend-mode:normal"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
doc/ads_logo_ukraine.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

View File

@@ -12,20 +12,6 @@ styles as much as possible.
## Features
### Overview
- [Features](#features)
- [Overview](#overview)
- [Docking everywhere - no central widget](#docking-everywhere---no-central-widget)
- [Docking inside floating windows](#docking-inside-floating-windows)
- [Grouped dragging](#grouped-dragging)
- [Perspectives for fast switching of the complete main window layout](#perspectives-for-fast-switching-of-the-complete-main-window-layout)
- [Opaque and non-opaque splitter resizing](#opaque-and-non-opaque-splitter-resizing)
- [Opaque and non-opaque undocking](#opaque-and-non-opaque-undocking)
- [Tab-menu for easy handling of many tabbed dock widgets](#tab-menu-for-easy-handling-of-many-tabbed-dock-widgets)
- [Many different ways to detach dock widgets](#many-different-ways-to-detach-dock-widgets)
- [Supports deletion of dynamically created dock widgets](#supports-deletion-of-dynamically-created-dock-widgets)
### Docking everywhere - no central widget
There is no central widget like in the Qt docking system. You can dock on every
@@ -106,3 +92,10 @@ You can detach dock widgets and also dock areas in the following ways:
### Supports deletion of dynamically created dock widgets
Normally clicking the close button of a dock widget will just hide the widget and the user can show it again using the toggleView() action of the dock widget. This is meant for user interfaces with a static amount of widgets. But the advanced docking system also supports dynamic dock widgets that will get deleted on close. If you set the dock widget flag `DockWidgetDeleteOnClose` for a certain dock widget, then it will be deleted as soon as you close this dock widget. This enables the implementation of user interfaces with dynamically created editors, like in word processing applications or source code development tools.
### Python PyQt5 Bindings
![Python Logo](https://raw.githubusercontent.com/githubuser0xFFFF/Qt-Advanced-Docking-System/master/doc/python_logo.png)
The Advanced Docking System comes with a complete Python integration based on
PyQt5 bindings. The package is available via [conda-forge](https://github.com/conda-forge/pyqtads-feedstock).

View File

@@ -4,21 +4,21 @@
"extensionType": [
"library"
],
"version": "3.0.0",
"version": "3.8.2",
"vendor": {
"name": "githubuser0xFFFF",
"url": "https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System"
},
"contact": "https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues",
"icon": "https://raw.githubusercontent.com/githubuser0xFFFF/Qt-Advanced-Docking-System/master/doc/ads_icon_512.png",
"icon": "https://raw.githubusercontent.com/githubuser0xFFFF/Qt-Advanced-Docking-System/master/doc/ads_icon.svg",
"licenses": [
{ "licenseType": "LGPLv2.1",
{ "licenseType": "LGPL-2.1-only",
"licenseUrl": "https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html" }
],
"created": "2017-03-30",
"lastUpdate": "2020-01-16",
"lastUpdate": "2022-03-02",
"platforms": [
"Windows 7-10", "Kubuntu 18.04", "Kubuntu 19.10", "Ubuntu 19.10"
"Windows 7-11", "Kubuntu 18.04", "Kubuntu 19.10", "Ubuntu 19.10", "Ubuntu 20.04"
],
"qtVersions": [
"5.5.1 or newer"

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

BIN
doc/showcase_d-tect-x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 KiB

BIN
doc/showcase_metgem.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 KiB

After

Width:  |  Height:  |  Size: 529 KiB

BIN
doc/taiwan_ukraine.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

BIN
doc/ukraine.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

View File

@@ -27,6 +27,29 @@
- [`EqualSplitOnInsertion`](#equalsplitoninsertion)
- [`FloatingContainerForceNativeTitleBar` (Linux only)](#floatingcontainerforcenativetitlebar-linux-only)
- [`FloatingContainerForceQWidgetTitleBar` (Linux only)](#floatingcontainerforceqwidgettitlebar-linux-only)
- [`MiddleMouseButtonClosesTab`](#middlemousebuttonclosestab)
- [Auto-Hide Configuration Flags](#auto-hide-configuration-flags)
- [Auto Hide Dock Widgets](#auto-hide-dock-widgets)
- [Pinning Auto-Hide Widgets to a certain border](#pinning-auto-hide-widgets-to-a-certain-border)
- [Show / Hide Auto-Hide Widgets via Mouse Over](#show--hide-auto-hide-widgets-via-mouse-over)
- [Adding Auto Hide Widgets](#adding-auto-hide-widgets)
- [Setting Auto-Hide Flags](#setting-auto-hide-flags)
- [`AutoHideFeatureEnabled`](#autohidefeatureenabled)
- [`DockAreaHasAutoHideButton`](#dockareahasautohidebutton)
- [`AutoHideButtonTogglesArea`](#autohidebuttontogglesarea)
- [`AutoHideButtonCheckable`](#autohidebuttoncheckable)
- [`AutoHideSideBarsIconOnly`](#autohidesidebarsicononly)
- [`AutoHideShowOnMouseOver`](#autohideshowonmouseover)
- [DockWidget Feature Flags](#dockwidget-feature-flags)
- [`DockWidgetClosable`](#dockwidgetclosable)
- [`DockWidgetMovable`](#dockwidgetmovable)
- [`DockWidgetFloatable`](#dockwidgetfloatable)
- [`DockWidgetDeleteOnClose`](#dockwidgetdeleteonclose)
- [`CustomCloseHandling`](#customclosehandling)
- [`DockWidgetFocusable`](#dockwidgetfocusable)
- [`DockWidgetForceCloseWithArea`](#dockwidgetforceclosewitharea)
- [`NoTab`](#notab)
- [`DeleteContentOnClose`](#deletecontentonclose)
- [Central Widget](#central-widget)
- [Empty Dock Area](#empty-dock-area)
- [Custom Close Handling](#custom-close-handling)
@@ -36,14 +59,15 @@
## Configuration Flags
The Advanced Docking System has a number of global configuration options to
configure the design and the functionality of the docking system. Eachs
configure the design and the functionality of the docking system. Each
configuration will be explained in detail in the following sections.
### Setting Configuration Flags
You should set the configuration flags before you create the dock manager
instance. That means, setting the configurations flags is the first thing
you do, if you use the library.
You must set the configuration flags before creating the dock manager
instance otherwise the manager will not be created correctly and will
crash upon being created. That means, setting the configurations flags
is the first thing you must do, if you use the library.
```c++
CDockManager::setConfigFlags(CDockManager::DefaultOpaqueConfig);
@@ -55,9 +79,9 @@ d->DockManager = new CDockManager(this);
If you set the configurations flags, you can set individual flags using the
function `CDockManager::setConfigFlag` or you can set all flags using
the function `CDockManager::setConfigFlags`. Instead of settings all
flags individualy, it is better to pick a predefined set of configuration
flags individually, it is better to pick a predefined set of configuration
flags and then modify individual flags. The following predefined
configurations are avilable
configurations are available
- `DefaultNonOpaqueConfig` - uses non opaque splitter resizing and non opaque docking
- `DefaultOpaqueConfig` - uses opaque splitter resizing and opaque docking
@@ -148,11 +172,11 @@ constant, that means, if enabled, the tabs need more space.
### `OpaqueUndocking`
If this flag is set, opaque undocking is active. That means, as soon as you drag a dock widget or a dock area with a number of dock widgets it will be undocked and moved into a floating widget and then the floating widget will be dragged around. That means undocking will take place immediatelly. You can compare this with opaque splitter resizing.
If this flag is set, opaque undocking is active. That means, as soon as you drag a dock widget or a dock area with a number of dock widgets it will be undocked and moved into a floating widget and then the floating widget will be dragged around. That means undocking will take place immediately. You can compare this with opaque splitter resizing.
![OpaqueUndocking true](opaque_undocking.gif)
If you would like to test opaque undocking, you should set the pedefined config
If you would like to test opaque undocking, you should set the predefined config
flags `CDockManager::DefaultOpaqueConfig`.
```c++
@@ -275,7 +299,8 @@ current dock widget.
![FloatingContainerHasWidgetTitle true](cfg_flag_FloatingContainerHasWidgetTitle_true.png)
otherwise it displays application name as window title.
otherwise it displays the title set with `CDockManager::setFloatingContainersTitle` or
application name as window title.
![FloatingContainerHasWidgetTitle false](cfg_flag_FloatingContainerHasWidgetTitle_false.png)
@@ -311,7 +336,7 @@ still has a titlebar to drag it out of the main window.
If this is enabled, the docking system is able to highlight the tab and the
components of a dock area with a different style (i.e. a different color).
This option is disabled by default and needs to be enabled explicitely
This option is disabled by default and needs to be enabled explicitly
because it adds some overhead. The dock manager needs to react on focus
changes and dock widget dragging to highlight the right dock widget. You should
enable it only, if you really need it for your application.
@@ -331,7 +356,7 @@ be set to true and you can use this property to style the focused dock
widget differently. The picture above uses the following styling:
```css
/* Color the tab with the nhighlight color */
/* Color the tab with the highlight color */
ads--CDockWidgetTab[focused="true"]
{
background: palette(highlight);
@@ -464,6 +489,192 @@ If you would like to overwrite autodetection, then you can activate this flag
to force QWidget based title bars. You can overwrite autodetection and this
flag, if you set the environment variable `ADS_UseNativeTitle` to 0 or 1.
### `MiddleMouseButtonClosesTab`
If the flag is set, the user can use the mouse middle button to close the tab
under the mouse. So you do not need to exactly hit the tab close button to
close tab. Just click with the middle mouse button on a tab like this is
possible in various web browsers.
![MiddleMouseButtonClosesTab true](cfg_flag_MiddleMouseButtonClosesTab.gif)
## Auto-Hide Configuration Flags
### Auto Hide Dock Widgets
The Advanced Docking System supports "Auto-Hide" functionality for **all**
dock containers. The "Auto Hide" feature allows to display more information
using less screen space by hiding or showing windows pinned to one of the
four dock container borders.
Enabling this feature adds a button with a pin icon to each dock area.
![DockAreaHasAutoHideButton true](cfg_flag_DockAreaHasAutoHideButton.png)
By clicking this button, the current dock widget (or the complete area - depending on the
configuration flags) will be pinned to a certain border. The border is choosen
depending on the location of the dock area. If you click the pin button while
holding down the **Ctrl** key, the whole dock area will be pinned to a certain
border.
### Pinning Auto-Hide Widgets to a certain border
If you would like to pin a dock widget or a dock area to a certain border,
then you can right-click into the dock widget tab or into the dock area title bar
to show the context menu. Then you can select the location via the **Pin to** menu:
![Pin to](AutoHide_PinTo.png)
### Show / Hide Auto-Hide Widgets via Mouse Over
Normally Auto-Hide widgets are shown by clicking the Auto-Hide tab and hidden by
clicking the Auto-Hide tab again or by clicking into any other dock widget in
the same container. If the Auto-Hide config flag `AutoHideShowOnMouseOver` is set,
the Auto-Hide widget is shown, if the user hovers over the Auto-Hide tab and is
collapsed if the mouse cursor leaves the Auto-Hide widget. Showing and hiding
by mouse click still works if this feature is enabled.
### Adding Auto Hide Widgets
Adding an auto hide widget is similar to adding a dock widget, simply call
`dockManager->addAutoHideDockWidget()`.
```c++
CDockManager::setAutoHideConfigFlags(CDockManager::DefaultAutoHideConfig);
d->DockManager = new CDockManager(this);
CDockWidget* TableDockWidget = new CDockWidget("Table 1");
DockManager->addAutoHideDockWidget(SideBarLeft, TableDockWidget);
```
See `autohide` example or the demo application to learn how it works.
### Setting Auto-Hide Flags
The Advanced Docking System has a number of global configuration flags to
configure the Auto-Hide functionality. You should set the Auto-Hide flags before
creating the dock manager instance. That means, you should set the Auto-Hide
flags after setting the configuration flags.
```c++
CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true);
CDockManager::setAutoHideConfigFlags(CDockManager::DefaultAutoHideConfig);
CDockManager::setAutoHideConfigFlag(CDockManager::AutoHideShowOnMouseOver, true);
...
d->DockManager = new CDockManager(this);
```
If you set the Auto-Hide flags, you can set individual flags using the
function `CDockManager::setAutoHideConfigFlag` or you can set all flags using
the function `CDockManager::setAutoHideConfigFlags`. Instead of settings all
flags individually, it is better to pick a predefined set of configuration
flags and then modify individual flags. The following predefined
configurations are available
- `DefaultAutoHideConfig` - default auto hide config
Pick one of those predefined configurations and then modify the following
configurations flags to adjust the docking system to your needs.
### `AutoHideFeatureEnabled`
Enables / disables the Auto-Hide functionality. Only if this flag is enabled,
the other Auto-Hide flags will be evaluated.
### `DockAreaHasAutoHideButton`
If this flag is set (default), then each dock area has a pin button in the title
bar to toggle Auto-Hide state.
![DockAreaHasAutoHideButton true](cfg_flag_DockAreaHasAutoHideButton.png)
### `AutoHideButtonTogglesArea`
If set, the the pin button in the dock area title bar toggles the complete area.
If not set (default), then the pin button toggles the current active tab / dock
widget and pressing the **Ctrl** key while clicking the pin button toggles the
complete ara.
### `AutoHideButtonCheckable`
Normally the pin button in the dock area title bar is not checkable. If this
flag is set, then the button is checkable. That means, if button is checked,
the dock widget is pinned.
### `AutoHideSideBarsIconOnly`
Normally the Auto-Hide tabs show the icon and title of the dock widget:
![AutoHideSideBarsIconOnly false](cfg_flag_AutoHideSideBarsIconOnly_false.png)
You can set this flag, if you would like to have only icons in the Auto-Hide
tabs instead of icon and dock widget title. If this is set, the Auto-Hide tab
needs less space. The tooltip of each tab still shows the dock widget title.
![AutoHideSideBarsIconOnly true](cfg_flag_AutoHideSideBarsIconOnly_true.png)
### `AutoHideShowOnMouseOver`
Normally Auto-Hide widgets are shown by clicking the Auto-Hide tab and
hidden by clicking the Auto-Hide tab again or by clicking into any other
dock widget in the same container. If this flag is set, the Auto-Hide widget
is shown, if the user hovers over the Auto-Hide tab or if the users moves the
mouse outside of the Auto-Hide widget. Showing and hiding my mouse click still
works if this feature is enabled.
## DockWidget Feature Flags
### `DockWidgetClosable`
If set, the dock widget will have a close button.
### `DockWidgetMovable`
If a dock widget is movable, then it and can be moved to a new position in the
current dock container. Disable this flag to prevent moving of a dock widget
via mouse. If the `OpaqueUndocking` configuration flag is set, then dock widgets
are immediately undocked into floating widgets. That means, moving is only
possible in this case, if the dock widget is also floatable (feature flag
`DockWidgetFloatable` is set).
### `DockWidgetFloatable`
If set, a dock widget can be dragged into a floating window.
### `DockWidgetDeleteOnClose`
Deletes the dock widget and its content when it is closed.
### `CustomCloseHandling`
Clicking the close button will not close the dock widget but emits the
`closeRequested()` signal instead. This allows the application to implement
a custom close handling.
### `DockWidgetFocusable`
If this is enabled, a dock widget can get focus highlighting.
### `DockWidgetForceCloseWithArea`
A dock widget will be closed when the dock area hosting it is closed. If the
`DockWidgetDeleteOnClose` feature is enabled for a dock widget, then it will
be deleted, if the user clicks the close button of this dock widget. If the
user clicks the close button of the dock area that contains this widget,
then only the visibility of the dock widget is toggled. If this feature flag
is set, the closing the dock area also closes the dock widget. That means, if
the dock widget feature `DockWidgetDeleteOnClose` is set for the dock widgets
in a dock area, then all dock widgets will be deleted if the dock area is closed.
### `NoTab`
A dock widget tab will never be shown if this flag is set.
### `DeleteContentOnClose`
Deletes only the contained widget on close, keeping the dock widget intact and
in place. Attempts to rebuild the contents widget on show if there is a widget
factory set. See [issue #365](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/pull/365) for more details.
## Central Widget
The Advanced Docking System has been developed to overcome the limitations of
@@ -550,3 +761,4 @@ just call the function for settings the stylesheet with an empty string.
```c++
DockManager->setStyleSheet("");
```

View File

@@ -1,8 +1,10 @@
cmake_minimum_required(VERSION 3.5)
project(QtADSExamples LANGUAGES CXX VERSION ${VERSION_SHORT})
add_subdirectory(simple)
add_subdirectory(hideshow)
add_subdirectory(sidebar)
add_subdirectory(deleteonclose)
add_subdirectory(centralwidget)
add_subdirectory(autohide)
add_subdirectory(emptydockarea)
add_subdirectory(dockindock)

View File

@@ -0,0 +1,28 @@
cmake_minimum_required(VERSION 3.5)
project(ads_example_autohide VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(AutoHideExample WIN32
main.cpp
mainwindow.cpp
mainwindow.ui
)
target_include_directories(AutoHideExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(AutoHideExample PRIVATE qtadvanceddocking)
target_link_libraries(AutoHideExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
set_target_properties(AutoHideExample PROPERTIES
AUTOMOC ON
AUTORCC ON
AUTOUIC ON
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
VERSION ${VERSION_SHORT}
EXPORT_NAME "Qt Advanced Docking System Auto Hide Example"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/bin"
)

View File

@@ -0,0 +1,34 @@
ADS_OUT_ROOT = $${OUT_PWD}/../..
QT += core gui widgets
TARGET = AutoHideExample
DESTDIR = $${ADS_OUT_ROOT}/lib
TEMPLATE = app
CONFIG += c++14
CONFIG += debug_and_release
adsBuildStatic {
DEFINES += ADS_STATIC
}
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
LIBS += -L$${ADS_OUT_ROOT}/lib
include(../../ads.pri)
INCLUDEPATH += ../../src
DEPENDPATH += ../../src

View File

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

106
examples/autohide/main.py Normal file
View File

@@ -0,0 +1,106 @@
import os
import sys
from PyQt5 import uic
from PyQt5.QtCore import Qt, QTimer, QDir, QSignalBlocker
from PyQt5.QtGui import QCloseEvent, QIcon
from PyQt5.QtWidgets import (QApplication, QLabel, QCalendarWidget, QFrame, QTreeView,
QTableWidget, QFileSystemModel, QPlainTextEdit, QToolBar,
QWidgetAction, QComboBox, QAction, QSizePolicy, QInputDialog)
from PyQtAds import QtAds
UI_FILE = os.path.join(os.path.dirname(__file__), 'mainwindow.ui')
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)
class MainWindow(MainWindowUI, MainWindowBase):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.OpaqueSplitterResize, True)
QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.XmlCompressionEnabled, False)
QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.FocusHighlighting, True)
self.dock_manager = QtAds.CDockManager(self)
# Set central widget
text_edit = QPlainTextEdit()
text_edit.setPlaceholderText("This is the central editor. Enter your text here.")
central_dock_widget = QtAds.CDockWidget("CentralWidget")
central_dock_widget.setWidget(text_edit)
central_dock_area = self.dock_manager.setCentralWidget(central_dock_widget)
central_dock_area.setAllowedAreas(QtAds.DockWidgetArea.OuterDockAreas)
# create other dock widgets
table = QTableWidget()
table.setColumnCount(3)
table.setRowCount(10)
table_dock_widget = QtAds.CDockWidget("Table 1")
table_dock_widget.setWidget(table)
table_dock_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget)
table_dock_widget.resize(250, 150)
table_dock_widget.setMinimumSize(200, 150)
table_area = self.dock_manager.addDockWidget(QtAds.DockWidgetArea.LeftDockWidgetArea, table_dock_widget)
self.menuView.addAction(table_dock_widget.toggleViewAction())
table = QTableWidget()
table.setColumnCount(5)
table.setRowCount(1020)
table_dock_widget = QtAds.CDockWidget("Table 2")
table_dock_widget.setWidget(table)
table_dock_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget)
table_dock_widget.resize(250, 150)
table_dock_widget.setMinimumSize(200, 150)
table_area = self.dock_manager.addDockWidget(QtAds.DockWidgetArea.BottomDockWidgetArea, table_dock_widget, table_area)
self.menuView.addAction(table_dock_widget.toggleViewAction())
properties_table = QTableWidget()
properties_table.setColumnCount(3)
properties_table.setRowCount(10)
properties_dock_widget = QtAds.CDockWidget("Properties")
properties_dock_widget.setWidget(properties_table)
properties_dock_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget)
properties_dock_widget.resize(250, 150)
properties_dock_widget.setMinimumSize(200, 150)
self.dock_manager.addDockWidget(QtAds.DockWidgetArea.RightDockWidgetArea, properties_dock_widget, central_dock_area)
self.menuView.addAction(properties_dock_widget.toggleViewAction())
self.create_perspective_ui()
def create_perspective_ui(self):
save_perspective_action = QAction("Create Perspective", self)
save_perspective_action.triggered.connect(self.save_perspective)
perspective_list_action = QWidgetAction(self)
self.perspective_combobox = QComboBox(self)
self.perspective_combobox.setSizeAdjustPolicy(QComboBox.AdjustToContents)
self.perspective_combobox.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
self.perspective_combobox.activated[str].connect(self.dock_manager.openPerspective)
perspective_list_action.setDefaultWidget(self.perspective_combobox)
self.toolBar.addSeparator()
self.toolBar.addAction(perspective_list_action)
self.toolBar.addAction(save_perspective_action)
def save_perspective(self):
perspective_name, ok = QInputDialog.getText(self, "Save Perspective", "Enter Unique name:")
if not ok or not perspective_name:
return
self.dock_manager.addPerspective(perspective_name)
blocker = QSignalBlocker(self.perspective_combobox)
self.perspective_combobox.clear()
self.perspective_combobox.addItems(self.dock_manager.perspectiveNames())
self.perspective_combobox.setCurrentText(perspective_name)
def closeEvent(self, event: QCloseEvent):
self.dock_manager.deleteLater()
super().closeEvent(event)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()

View File

@@ -0,0 +1,126 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QWidgetAction>
#include <QFileSystemModel>
#include <QTableWidget>
#include <QHBoxLayout>
#include <QInputDialog>
#include <QFileDialog>
#include <QSettings>
#include <QPlainTextEdit>
#include <QToolBar>
#include "AutoHideDockContainer.h"
#include "DockAreaWidget.h"
#include "DockAreaTitleBar.h"
using namespace ads;
CMainWindow::CMainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::CMainWindow)
{
ui->setupUi(this);
CDockManager::setConfigFlag(CDockManager::OpaqueSplitterResize, true);
CDockManager::setConfigFlag(CDockManager::XmlCompressionEnabled, false);
CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true);
CDockManager::setAutoHideConfigFlags(CDockManager::DefaultAutoHideConfig);
DockManager = new CDockManager(this);
// Set central widget
QPlainTextEdit* w = new QPlainTextEdit();
w->setPlaceholderText("This is the central editor. Enter your text here.");
CDockWidget* CentralDockWidget = new CDockWidget("CentralWidget");
CentralDockWidget->setWidget(w);
auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget);
CentralDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas);
// create other dock widgets
QTableWidget* table = new QTableWidget();
table->setColumnCount(3);
table->setRowCount(10);
CDockWidget* TableDockWidget = new CDockWidget("Table 1");
TableDockWidget->setWidget(table);
TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
TableDockWidget->setMinimumSize(200,150);
const auto autoHideContainer = DockManager->addAutoHideDockWidget(SideBarLocation::SideBarLeft, TableDockWidget);
autoHideContainer->setSize(480);
ui->menuView->addAction(TableDockWidget->toggleViewAction());
table = new QTableWidget();
table->setColumnCount(5);
table->setRowCount(1020);
TableDockWidget = new CDockWidget("Table 2");
TableDockWidget->setWidget(table);
TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
TableDockWidget->resize(250, 150);
TableDockWidget->setMinimumSize(200,150);
DockManager->addAutoHideDockWidget(SideBarLocation::SideBarLeft, TableDockWidget);
ui->menuView->addAction(TableDockWidget->toggleViewAction());
QTableWidget* propertiesTable = new QTableWidget();
propertiesTable->setColumnCount(3);
propertiesTable->setRowCount(10);
CDockWidget* PropertiesDockWidget = new CDockWidget("Properties");
PropertiesDockWidget->setWidget(propertiesTable);
PropertiesDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
PropertiesDockWidget->resize(250, 150);
PropertiesDockWidget->setMinimumSize(200,150);
DockManager->addDockWidget(DockWidgetArea::RightDockWidgetArea, PropertiesDockWidget, CentralDockArea);
ui->menuView->addAction(PropertiesDockWidget->toggleViewAction());
createPerspectiveUi();
}
CMainWindow::~CMainWindow()
{
delete ui;
}
void CMainWindow::createPerspectiveUi()
{
SavePerspectiveAction = new QAction("Create Perspective", this);
connect(SavePerspectiveAction, SIGNAL(triggered()), SLOT(savePerspective()));
PerspectiveListAction = new QWidgetAction(this);
PerspectiveComboBox = new QComboBox(this);
PerspectiveComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
PerspectiveComboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
connect(PerspectiveComboBox, SIGNAL(currentTextChanged(const QString&)),
DockManager, SLOT(openPerspective(const QString&)));
PerspectiveListAction->setDefaultWidget(PerspectiveComboBox);
ui->toolBar->addSeparator();
ui->toolBar->addAction(PerspectiveListAction);
ui->toolBar->addAction(SavePerspectiveAction);
}
void CMainWindow::savePerspective()
{
QString PerspectiveName = QInputDialog::getText(this, "Save Perspective", "Enter unique name:");
if (PerspectiveName.isEmpty())
{
return;
}
DockManager->addPerspective(PerspectiveName);
QSignalBlocker Blocker(PerspectiveComboBox);
PerspectiveComboBox->clear();
PerspectiveComboBox->addItems(DockManager->perspectiveNames());
PerspectiveComboBox->setCurrentText(PerspectiveName);
}
//============================================================================
void CMainWindow::closeEvent(QCloseEvent* event)
{
// Delete dock manager here to delete all floating widgets. This ensures
// that all top level windows of the dock manager are properly closed
DockManager->deleteLater();
QMainWindow::closeEvent(event);
}

View File

@@ -0,0 +1,43 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QComboBox>
#include <QWidgetAction>
#include "DockManager.h"
#include "DockAreaWidget.h"
#include "DockWidget.h"
QT_BEGIN_NAMESPACE
namespace Ui { class CMainWindow; }
QT_END_NAMESPACE
class CMainWindow : public QMainWindow
{
Q_OBJECT
public:
CMainWindow(QWidget *parent = nullptr);
~CMainWindow();
protected:
virtual void closeEvent(QCloseEvent* event) override;
private:
QAction* SavePerspectiveAction = nullptr;
QWidgetAction* PerspectiveListAction = nullptr;
QComboBox* PerspectiveComboBox = nullptr;
Ui::CMainWindow *ui;
ads::CDockManager* DockManager;
ads::CDockAreaWidget* StatusDockArea;
ads::CDockWidget* TimelineDockWidget;
void createPerspectiveUi();
private slots:
void savePerspective();
};
#endif // MAINWINDOW_H

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CMainWindow</class>
<widget class="QMainWindow" name="CMainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1284</width>
<height>757</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1284</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
</property>
</widget>
<addaction name="menuView"/>
</widget>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -96,7 +96,7 @@ void CMainWindow::createPerspectiveUi()
PerspectiveComboBox = new QComboBox(this);
PerspectiveComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
PerspectiveComboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
connect(PerspectiveComboBox, SIGNAL(activated(const QString&)),
connect(PerspectiveComboBox, SIGNAL(currentTextChanged(const QString&)),
DockManager, SLOT(openPerspective(const QString&)));
PerspectiveListAction->setDefaultWidget(PerspectiveComboBox);
ui->toolBar->addSeparator();

View File

@@ -206,11 +206,15 @@ void DockInDockWidget::fillPerspectivesMenu( QMenu* menu )
if ( !perspectiveNames.isEmpty() )
{
QMenu* load = menu->addMenu( "Load perspective" );
for ( auto name : perspectiveNames )
load->addAction( new LoadPerspectiveAction( load, name, *this ) );
for (const auto& name : perspectiveNames)
{
load->addAction(new LoadPerspectiveAction( load, name, *this));
}
QMenu* remove = menu->addMenu( "Remove perspective" );
for ( auto name : perspectiveNames )
remove->addAction( new RemovePerspectiveAction( remove, name, *this ) );
for (const auto& name : perspectiveNames)
{
remove->addAction( new RemovePerspectiveAction( remove, name, *this ));
}
}
}

View File

@@ -219,8 +219,10 @@ void PerspectivesManager::loadPerspectives()
// load group info:
mainSettings->beginGroup(GROUP_PREFIX);
for ( auto key : mainSettings->allKeys() )
for (const auto& key : mainSettings->allKeys())
{
m_perspectives[perspective].groups[key] = mainSettings->value( key ).toStringList();
}
mainSettings->endGroup();
}
else

View File

@@ -1,8 +1,10 @@
TEMPLATE = subdirs
SUBDIRS = \
autohide \
centralwidget \
simple \
hideshow \
sidebar \
deleteonclose \
emptydockarea \

View File

@@ -0,0 +1,28 @@
cmake_minimum_required(VERSION 3.5)
project(ads_example_hideshow VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(HideShowExample WIN32
main.cpp
MainWindow.cpp
MainWindow.ui
)
target_include_directories(HideShowExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(HideShowExample PRIVATE qtadvanceddocking)
target_link_libraries(HideShowExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
set_target_properties(HideShowExample PROPERTIES
AUTOMOC ON
AUTORCC ON
AUTOUIC ON
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
VERSION ${VERSION_SHORT}
EXPORT_NAME "Qt Advanced Docking System Hide,Show Example"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/bin"
)

View File

@@ -0,0 +1,80 @@
#include "../../examples/hideshow/MainWindow.h"
#include "ui_MainWindow.h"
#include <QLabel>
#include <QPushButton>
using namespace ads;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->centralWidget->setLayout( m_layout = new QStackedLayout() );
m_welcomeWidget = new QWidget(this);
auto welcomeLayout = new QVBoxLayout(m_welcomeWidget);
welcomeLayout->addStretch();
QPushButton* openButton = new QPushButton("Open project");
welcomeLayout->addWidget( openButton );
welcomeLayout->addStretch();
connect( openButton, SIGNAL(clicked()), this, SLOT(openProject()) );
m_DockManager = new ads::CDockManager(ui->centralWidget);
// Create example content label - this can be any application specific
// widget
QLabel* l = new QLabel();
l->setWordWrap(true);
l->setAlignment(Qt::AlignTop | Qt::AlignLeft);
l->setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ");
// Create a dock widget with the title Label 1 and set the created label
// as the dock widget content
ads::CDockWidget* DockWidget = new ads::CDockWidget("Label 1");
DockWidget->setWidget(l);
// Add the toggleViewAction of the dock widget to the menu to give
// the user the possibility to show the dock widget if it has been closed
ui->menuView->addAction(DockWidget->toggleViewAction());
connect( ui->actionOpen, SIGNAL(triggered()), this, SLOT(openProject()) );
connect( ui->actionClose, SIGNAL(triggered()), this, SLOT(closeProject()) );
// Add the dock widget to the top dock widget area
m_DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);
ui->centralWidget->layout()->addWidget( m_welcomeWidget );
ui->centralWidget->layout()->addWidget( m_DockManager );
closeProject();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::openProject()
{
ui->actionOpen->setEnabled(false);
ui->actionClose->setEnabled(true);
ui->menuView->setEnabled(true);
m_layout->setCurrentWidget( m_DockManager );
}
void MainWindow::closeProject()
{
ui->actionOpen->setEnabled(true);
ui->actionClose->setEnabled(false);
ui->menuView->setEnabled(false);
m_DockManager->hideManagerAndFloatingWidgets();
m_layout->setCurrentWidget( m_welcomeWidget );
}

View File

@@ -0,0 +1,33 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStackedLayout>
#include "DockManager.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void openProject();
void closeProject();
private:
Ui::MainWindow *ui;
QWidget* m_welcomeWidget;
ads::CDockManager* m_DockManager;
QStackedLayout* m_layout;
};
#endif // MAINWINDOW_H

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget"/>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>26</height>
</rect>
</property>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
</property>
</widget>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionOpen"/>
<addaction name="actionClose"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuView"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionOpen">
<property name="text">
<string>Open project</string>
</property>
</action>
<action name="actionClose">
<property name="text">
<string>Close project</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,31 @@
ADS_OUT_ROOT = $${OUT_PWD}/../..
QT += core gui widgets
TARGET = HideShowExample
DESTDIR = $${ADS_OUT_ROOT}/lib
TEMPLATE = app
CONFIG += c++14
CONFIG += debug_and_release
adsBuildStatic {
DEFINES += ADS_STATIC
}
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
MainWindow.cpp
HEADERS += \
MainWindow.h
FORMS += \
MainWindow.ui
LIBS += -L$${ADS_OUT_ROOT}/lib
include(../../ads.pri)
INCLUDEPATH += ../../src
DEPENDPATH += ../../src

View File

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

View File

@@ -43,6 +43,7 @@ MainWindow::MainWindow(QWidget *parent) :
QPlainTextEdit* te = new QPlainTextEdit();
te->setPlaceholderText("Please enter your text here into this QPlainTextEdit...");
DockWidget = new ads::CDockWidget("Editor 1");
DockWidget->setWidget(te);
ui->menuView->addAction(DockWidget->toggleViewAction());
m_DockManager->addDockWidget(ads::BottomDockWidgetArea, DockWidget);
}

2
persist/perspectives.ini Normal file
View File

@@ -0,0 +1,2 @@
[Perspectives]
size=0

27
project.py Normal file
View File

@@ -0,0 +1,27 @@
import os
from pyqtbuild import PyQtBindings, PyQtProject
from sipbuild import Option
class PyQtAds(PyQtProject):
def __init__(self):
""" Initialise the project. """
super().__init__()
self.bindings_factories = [ads]
class ads(PyQtBindings):
def __init__(self, project):
""" Initialise the bindings. """
super().__init__(project, 'ads')
def apply_user_defaults(self, tool):
""" Set default values for user options that haven't been set yet. """
resource_file = os.path.join(self.project.root_dir,'src','ads.qrc')
print("Adding resource file to qmake project: ", resource_file)
self.builder_settings.append('RESOURCES += '+resource_file)
super().apply_user_defaults(tool)

65
pyproject.toml Normal file
View File

@@ -0,0 +1,65 @@
# Specify the build system.
[build-system]
requires = ["sip >=6.0.2, <6.6", "PyQt-builder >=1.6, <2", "PyQt5>=5.15.4", "PyQt5-sip<13,>=12.8"]
build-backend = "sipbuild.api"
# Specify the PEP 566 metadata for the project.
[tool.sip.metadata]
name = "PyQtAds"
version = "3.8.2"
summary = "Python bindings for Qt Advanced Docking System"
home-page = "https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/"
license = "LGPL v2.1"
description-file = "README.md"
requires-dist = "PyQt5 (>=5.15.4)"
description-content-type = "text/markdown"
[tool.sip.project]
tag-prefix = "QtAds"
[tool.sip.bindings.ads]
define-macros = ["ADS_SHARED_EXPORT"]
sip-file = "ads.sip"
include-dirs = ["src"]
qmake-QT = ["widgets"]
headers = [
"src/DockAreaTabBar.h",
"src/DockAreaTitleBar.h",
"src/DockAreaTitleBar_p.h",
"src/DockAreaWidget.h",
"src/DockComponentsFactory.h",
"src/DockContainerWidget.h",
"src/DockFocusController.h",
"src/DockManager.h",
"src/DockOverlay.h",
"src/DockSplitter.h",
"src/DockWidget.h",
"src/DockWidgetTab.h",
"src/DockingStateReader.h",
"src/ElidingLabel.h",
"src/FloatingDockContainer.h",
"src/FloatingDragPreview.h",
"src/IconProvider.h",
"src/ads_globals.h",
# "src/linux/FloatingWidgetTitleBar.h",
]
sources = [
"src/DockAreaTabBar.cpp",
"src/DockAreaTitleBar.cpp",
"src/DockAreaWidget.cpp",
"src/DockComponentsFactory.cpp",
"src/DockContainerWidget.cpp",
"src/DockFocusController.cpp",
"src/DockManager.cpp",
"src/DockOverlay.cpp",
"src/DockSplitter.cpp",
"src/DockWidget.cpp",
"src/DockWidgetTab.cpp",
"src/DockingStateReader.cpp",
"src/ElidingLabel.cpp",
"src/FloatingDockContainer.cpp",
"src/FloatingDragPreview.cpp",
"src/IconProvider.cpp",
"src/ads_globals.cpp",
# "src/linux/FloatingWidgetTitleBar.cpp",
]

View File

@@ -172,6 +172,7 @@ public:
EqualSplitOnInsertion,
FloatingContainerForceNativeTitleBar,
FloatingContainerForceQWidgetTitleBar,
MiddleMouseButtonClosesTab,
DefaultDockAreaButtons,
DefaultBaseConfig,
DefaultOpaqueConfig,

View File

@@ -34,6 +34,7 @@ public:
DockWidgetFocusable,
DockWidgetForceCloseWithArea,
NoTab,
DeleteContentOnClose,
DefaultDockWidgetFeatures,
AllDockWidgetFeatures,
DockWidgetAlwaysCloseAndDelete,

View File

@@ -1,4 +1,4 @@
%Module(name=PyQtAds.QtAds.ads, call_super_init=True, keyword_arguments="Optional", use_limited_api=True)
%Module(name=PyQtAds, call_super_init=True, keyword_arguments="Optional", use_limited_api=True)
%Import QtCore/QtCoremod.sip
%DefaultSupertype sip.simplewrapper

View File

@@ -0,0 +1,647 @@
/*******************************************************************************
** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
//============================================================================
/// \file AutoHideDockContainer.cpp
/// \author Syarif Fakhri
/// \date 05.09.2022
/// \brief Implementation of CAutoHideDockContainer class
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include "AutoHideDockContainer.h"
#include <QXmlStreamWriter>
#include <QBoxLayout>
#include <QPainter>
#include <QSplitter>
#include <QPointer>
#include <QApplication>
#include <QCursor>
#include "DockManager.h"
#include "DockAreaWidget.h"
#include "ResizeHandle.h"
#include "DockComponentsFactory.h"
#include "AutoHideSideBar.h"
#include "AutoHideTab.h"
#include <iostream>
namespace ads
{
static const int ResizeMargin = 30;
//============================================================================
bool static isHorizontalArea(SideBarLocation Area)
{
switch (Area)
{
case SideBarLocation::SideBarTop:
case SideBarLocation::SideBarBottom: return true;
case SideBarLocation::SideBarLeft:
case SideBarLocation::SideBarRight: return false;
default:
return true;
}
return true;
}
//============================================================================
Qt::Edge static edgeFromSideTabBarArea(SideBarLocation Area)
{
switch (Area)
{
case SideBarLocation::SideBarTop: return Qt::BottomEdge;
case SideBarLocation::SideBarBottom: return Qt::TopEdge;
case SideBarLocation::SideBarLeft: return Qt::RightEdge;
case SideBarLocation::SideBarRight: return Qt::LeftEdge;
default:
return Qt::LeftEdge;
}
return Qt::LeftEdge;
}
//============================================================================
int resizeHandleLayoutPosition(SideBarLocation Area)
{
switch (Area)
{
case SideBarLocation::SideBarBottom:
case SideBarLocation::SideBarRight: return 0;
case SideBarLocation::SideBarTop:
case SideBarLocation::SideBarLeft: return 1;
default:
return 0;
}
return 0;
}
/**
* Private data of CAutoHideDockContainer - pimpl
*/
struct AutoHideDockContainerPrivate
{
CAutoHideDockContainer* _this;
CDockAreaWidget* DockArea{nullptr};
CDockWidget* DockWidget{nullptr};
SideBarLocation SideTabBarArea = SideBarNone;
QBoxLayout* Layout = nullptr;
CResizeHandle* ResizeHandle = nullptr;
QSize Size; // creates invalid size
QPointer<CAutoHideTab> SideTab;
/**
* Private data constructor
*/
AutoHideDockContainerPrivate(CAutoHideDockContainer *_public);
/**
* Convenience function to get a dock widget area
*/
DockWidgetArea getDockWidgetArea(SideBarLocation area)
{
switch (area)
{
case SideBarLocation::SideBarLeft: return LeftDockWidgetArea;
case SideBarLocation::SideBarRight: return RightDockWidgetArea;
case SideBarLocation::SideBarBottom: return BottomDockWidgetArea;
case SideBarLocation::SideBarTop: return TopDockWidgetArea;
default:
return LeftDockWidgetArea;
}
return LeftDockWidgetArea;
}
/**
* Update the resize limit of the resize handle
*/
void updateResizeHandleSizeLimitMax()
{
auto Rect = _this->dockContainer()->contentRect();
const auto maxResizeHandleSize = ResizeHandle->orientation() == Qt::Horizontal
? Rect.width() : Rect.height();
ResizeHandle->setMaxResizeSize(maxResizeHandleSize - ResizeMargin);
}
/**
* Convenience function to check, if this is an horizontal area
*/
bool isHorizontal() const
{
return isHorizontalArea(SideTabBarArea);
}
/**
* Forward this event to the dock container
*/
void forwardEventToDockContainer(QEvent* event)
{
auto DockContainer = _this->dockContainer();
if (DockContainer)
{
DockContainer->handleAutoHideWidgetEvent(event, _this);
}
}
}; // struct AutoHideDockContainerPrivate
//============================================================================
AutoHideDockContainerPrivate::AutoHideDockContainerPrivate(
CAutoHideDockContainer *_public) :
_this(_public)
{
}
//============================================================================
CDockContainerWidget* CAutoHideDockContainer::dockContainer() const
{
if (d->DockArea)
{
return d->DockArea->dockContainer();
}
else
{
return internal::findParent<CDockContainerWidget*>(this);
}
}
//============================================================================
CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarLocation area, CDockContainerWidget* parent) :
Super(parent),
d(new AutoHideDockContainerPrivate(this))
{
hide(); // auto hide dock container is initially always hidden
d->SideTabBarArea = area;
d->SideTab = componentsFactory()->createDockWidgetSideTab(nullptr);
connect(d->SideTab, &CAutoHideTab::pressed, this, &CAutoHideDockContainer::toggleCollapseState);
d->DockArea = new CDockAreaWidget(DockWidget->dockManager(), parent);
d->DockArea->setObjectName("autoHideDockArea");
d->DockArea->setAutoHideDockContainer(this);
setObjectName("autoHideDockContainer");
d->Layout = new QBoxLayout(isHorizontalArea(area) ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight);
d->Layout->setContentsMargins(0, 0, 0, 0);
d->Layout->setSpacing(0);
setLayout(d->Layout);
d->ResizeHandle = new CResizeHandle(edgeFromSideTabBarArea(area), this);
d->ResizeHandle->setMinResizeSize(64);
bool OpaqueResize = CDockManager::testConfigFlag(CDockManager::OpaqueSplitterResize);
d->ResizeHandle->setOpaqueResize(OpaqueResize);
d->Size = d->DockArea->size();
addDockWidget(DockWidget);
parent->registerAutoHideWidget(this);
// The dock area should not be added to the layout before it contains the
// dock widget. If you add it to the layout before it contains the dock widget
// then you will likely see this warning for OpenGL widgets or QAxWidgets:
// setGeometry: Unable to set geometry XxY+Width+Height on QWidgetWindow/'WidgetClassWindow
d->Layout->addWidget(d->DockArea);
d->Layout->insertWidget(resizeHandleLayoutPosition(area), d->ResizeHandle);
}
//============================================================================
void CAutoHideDockContainer::updateSize()
{
auto dockContainerParent = dockContainer();
if (!dockContainerParent)
{
return;
}
auto rect = dockContainerParent->contentRect();
switch (sideBarLocation())
{
case SideBarLocation::SideBarTop:
resize(rect.width(), qMin(rect.height() - ResizeMargin, d->Size.height()));
move(rect.topLeft());
break;
case SideBarLocation::SideBarLeft:
resize(qMin(d->Size.width(), rect.width() - ResizeMargin), rect.height());
move(rect.topLeft());
break;
case SideBarLocation::SideBarRight:
{
resize(qMin(d->Size.width(), rect.width() - ResizeMargin), rect.height());
QPoint p = rect.topRight();
p.rx() -= (width() - 1);
move(p);
}
break;
case SideBarLocation::SideBarBottom:
{
resize(rect.width(), qMin(rect.height() - ResizeMargin, d->Size.height()));
QPoint p = rect.bottomLeft();
p.ry() -= (height() - 1);
move(p);
}
break;
default:
break;
}
}
//============================================================================
CAutoHideDockContainer::~CAutoHideDockContainer()
{
ADS_PRINT("~CAutoHideDockContainer");
// Remove event filter in case there are any queued messages
qApp->removeEventFilter(this);
if (dockContainer())
{
dockContainer()->removeAutoHideWidget(this);
}
if (d->SideTab)
{
delete d->SideTab;
}
delete d;
}
//============================================================================
CAutoHideSideBar* CAutoHideDockContainer::sideBar() const
{
auto DockContainer = dockContainer();
return DockContainer ? DockContainer->sideTabBar(d->SideTabBarArea) : nullptr;
}
//============================================================================
CAutoHideTab* CAutoHideDockContainer::autoHideTab() const
{
return d->SideTab;
}
//============================================================================
CDockWidget* CAutoHideDockContainer::dockWidget() const
{
return d->DockWidget;
}
//============================================================================
void CAutoHideDockContainer::addDockWidget(CDockWidget* DockWidget)
{
if (d->DockWidget)
{
// Remove the old dock widget at this area
d->DockArea->removeDockWidget(d->DockWidget);
}
d->DockWidget = DockWidget;
d->SideTab->setDockWidget(DockWidget);
CDockAreaWidget* OldDockArea = DockWidget->dockAreaWidget();
auto IsRestoringState = DockWidget->dockManager()->isRestoringState();
if (OldDockArea && !IsRestoringState)
{
// The initial size should be a little bit bigger than the original dock
// area size to prevent that the resize handle of this auto hid dock area
// is near of the splitter of the old dock area.
d->Size = OldDockArea->size() + QSize(16, 16);
OldDockArea->removeDockWidget(DockWidget);
}
d->DockArea->addDockWidget(DockWidget);
updateSize();
}
//============================================================================
SideBarLocation CAutoHideDockContainer::sideBarLocation() const
{
return d->SideTabBarArea;
}
//============================================================================
void CAutoHideDockContainer::setSideBarLocation(SideBarLocation SideBarLocation)
{
if (d->SideTabBarArea == SideBarLocation)
{
return;
}
d->SideTabBarArea = SideBarLocation;
d->Layout->removeWidget(d->ResizeHandle);
d->Layout->setDirection(isHorizontalArea(SideBarLocation) ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight);
d->Layout->insertWidget(resizeHandleLayoutPosition(SideBarLocation), d->ResizeHandle);
d->ResizeHandle->setHandlePosition(edgeFromSideTabBarArea(SideBarLocation));
internal::repolishStyle(this, internal::RepolishDirectChildren);
}
//============================================================================
CDockAreaWidget* CAutoHideDockContainer::dockAreaWidget() const
{
return d->DockArea;
}
//============================================================================
void CAutoHideDockContainer::moveContentsToParent()
{
cleanupAndDelete();
// If we unpin the auto hide dock widget, then we insert it into the same
// location like it had as a auto hide widget. This brings the least surprise
// to the user and he does not have to search where the widget was inserted.
d->DockWidget->setDockArea(nullptr);
auto DockContainer = dockContainer();
DockContainer->addDockWidget(d->getDockWidgetArea(d->SideTabBarArea), d->DockWidget);
}
//============================================================================
void CAutoHideDockContainer::cleanupAndDelete()
{
const auto dockWidget = d->DockWidget;
if (dockWidget)
{
auto SideTab = d->SideTab;
SideTab->removeFromSideBar();
SideTab->setParent(nullptr);
SideTab->hide();
}
hide();
deleteLater();
}
//============================================================================
void CAutoHideDockContainer::saveState(QXmlStreamWriter& s)
{
s.writeStartElement("Widget");
s.writeAttribute("Name", d->DockWidget->objectName());
s.writeAttribute("Closed", QString::number(d->DockWidget->isClosed() ? 1 : 0));
s.writeAttribute("Size", QString::number(d->isHorizontal() ? d->Size.height() : d->Size.width()));
s.writeEndElement();
}
//============================================================================
void CAutoHideDockContainer::toggleView(bool Enable)
{
if (Enable)
{
if (d->SideTab)
{
d->SideTab->show();
}
}
else
{
if (d->SideTab)
{
d->SideTab->hide();
}
hide();
qApp->removeEventFilter(this);
}
}
//============================================================================
void CAutoHideDockContainer::collapseView(bool Enable)
{
if (Enable)
{
hide();
qApp->removeEventFilter(this);
}
else
{
updateSize();
d->updateResizeHandleSizeLimitMax();
raise();
show();
d->DockWidget->dockManager()->setDockWidgetFocused(d->DockWidget);
qApp->installEventFilter(this);
}
ADS_PRINT("CAutoHideDockContainer::collapseView " << Enable);
d->SideTab->updateStyle();
}
//============================================================================
void CAutoHideDockContainer::toggleCollapseState()
{
collapseView(isVisible());
}
//============================================================================
void CAutoHideDockContainer::setSize(int Size)
{
if (d->isHorizontal())
{
d->Size.setHeight(Size);
}
else
{
d->Size.setWidth(Size);
}
updateSize();
}
//============================================================================
/**
* Returns true if the object given in ancestor is an ancestor of the object
* given in descendant
*/
static bool objectIsAncestorOf(const QObject* descendant, const QObject* ancestor)
{
if (!ancestor)
{
return false;
}
while (descendant)
{
if (descendant == ancestor)
{
return true;
}
descendant = descendant->parent();
}
return false;
}
//============================================================================
/**
* Returns true if the object given in ancestor is the object given in descendant
* or if it is an ancestor of the object given in descendant
*/
static bool isObjectOrAncestor(const QObject *descendant, const QObject *ancestor)
{
if (ancestor && (descendant == ancestor))
{
return true;
}
else
{
return objectIsAncestorOf(descendant, ancestor);
}
}
//============================================================================
bool CAutoHideDockContainer::eventFilter(QObject* watched, QEvent* event)
{
// A switch case statement would be nicer here, but we cannot use
// internal::FloatingWidgetDragStartEvent in a switch case
if (event->type() == QEvent::Resize)
{
if (!d->ResizeHandle->isResizing())
{
updateSize();
}
}
else if (event->type() == QEvent::MouseButtonPress)
{
auto widget = qobject_cast<QWidget*>(watched);
// Ignore non widget events
if (!widget)
{
return Super::eventFilter(watched, event);
}
// Now check, if the user clicked into the side tab and ignore this event,
// because the side tab click handler will call collapseView(). If we
// do not ignore this here, then we will collapse the container and the side tab
// click handler will uncollapse it
if (widget == d->SideTab.data())
{
return Super::eventFilter(watched, event);
}
// Now we check, if the user clicked inside of this auto hide container.
// If the click is inside of this auto hide container, then we can
// ignore the event, because the auto hide overlay should not get collapsed if
// user works in it
if (isObjectOrAncestor(widget, this))
{
return Super::eventFilter(watched, event);
}
// Ignore the mouse click if it is not inside of this container
if (!isObjectOrAncestor(widget, dockContainer()))
{
return Super::eventFilter(watched, event);
}
// user clicked into container - collapse the auto hide widget
collapseView(true);
}
else if (event->type() == internal::FloatingWidgetDragStartEvent)
{
// If we are dragging our own floating widget, the we do not need to
// collapse the view
auto FloatingWidget = dockContainer()->floatingWidget();
if (FloatingWidget != watched)
{
collapseView(true);
}
}
else if (event->type() == internal::DockedWidgetDragStartEvent)
{
collapseView(true);
}
return Super::eventFilter(watched, event);
}
//============================================================================
void CAutoHideDockContainer::resizeEvent(QResizeEvent* event)
{
Super::resizeEvent(event);
if (d->ResizeHandle->isResizing())
{
d->Size = this->size();
d->updateResizeHandleSizeLimitMax();
}
}
//============================================================================
void CAutoHideDockContainer::leaveEvent(QEvent *event)
{
// Resizing of the dock container via the resize handle in non opaque mode
// mays cause a leave event that is not really a leave event. Therefore
// we check here, if we are really outside of our rect.
auto pos = mapFromGlobal(QCursor::pos());
if (!rect().contains(pos))
{
d->forwardEventToDockContainer(event);
}
Super::leaveEvent(event);
}
//============================================================================
bool CAutoHideDockContainer::event(QEvent* event)
{
switch (event->type())
{
case QEvent::Enter:
case QEvent::Hide:
d->forwardEventToDockContainer(event);
break;
case QEvent::MouseButtonPress:
return true;
break;
default:
break;
}
return Super::event(event);
}
}

173
src/AutoHideDockContainer.h Normal file
View File

@@ -0,0 +1,173 @@
#ifndef AutoHideDockContainerH
#define AutoHideDockContainerH
/*******************************************************************************
** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
//============================================================================
/// \file AutoHideDockContainer.h
/// \author Syarif Fakhri
/// \date 05.09.2022
/// \brief Declaration of CAutoHideDockContainer class
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include "ads_globals.h"
#include <QSplitter>
#include "AutoHideTab.h"
class QXmlStreamWriter;
namespace ads
{
struct AutoHideDockContainerPrivate;
class CDockManager;
class CDockWidget;
class CDockContainerWidget;
class CAutoHideSideBar;
class CDockAreaWidget;
class CDockingStateReader;
struct SideTabBarPrivate;
/**
* Auto hide container for hosting an auto hide dock widget
*/
class ADS_EXPORT CAutoHideDockContainer : public QFrame
{
Q_OBJECT
Q_PROPERTY(int sideBarLocation READ sideBarLocation)
private:
AutoHideDockContainerPrivate* d; ///< private data (pimpl)
friend struct AutoHideDockContainerPrivate;
friend CAutoHideSideBar;
friend SideTabBarPrivate;
protected:
virtual bool eventFilter(QObject* watched, QEvent* event) override;
virtual void resizeEvent(QResizeEvent* event) override;
virtual void leaveEvent(QEvent *event) override;
virtual bool event(QEvent* event) override;
/**
* Updates the size considering the size limits and the resize margins
*/
void updateSize();
/*
* Saves the state and size
*/
void saveState(QXmlStreamWriter& Stream);
public:
using Super = QFrame;
/**
* Create Auto Hide widget with the given dock widget
*/
CAutoHideDockContainer(CDockWidget* DockWidget, SideBarLocation area,
CDockContainerWidget* parent);
/**
* Virtual Destructor
*/
virtual ~CAutoHideDockContainer();
/**
* Get's the side tab bar
*/
CAutoHideSideBar* sideBar() const;
/**
* Returns the side tab
*/
CAutoHideTab* autoHideTab() const;
/**
* Get's the dock widget in this dock container
*/
CDockWidget* dockWidget() const;
/**
* Adds a dock widget and removes the previous dock widget
*/
void addDockWidget(CDockWidget* DockWidget);
/**
* Returns the side tab bar area of this Auto Hide dock container
*/
SideBarLocation sideBarLocation() const;
/**
* Sets a new SideBarLocation.
* If a new side bar location is set, the auto hide dock container needs
* to update its resize handle position
*/
void setSideBarLocation(SideBarLocation SideBarLocation);
/**
* Returns the dock area widget of this Auto Hide dock container
*/
CDockAreaWidget* dockAreaWidget() const;
/**
* Returns the parent container that hosts this auto hide container
*/
CDockContainerWidget* dockContainer() const;
/**
* Moves the contents to the parent container widget
* Used before removing this Auto Hide dock container
*/
void moveContentsToParent();
/**
* Cleanups up the side tab widget and then deletes itself
*/
void cleanupAndDelete();
/*
* Toggles the auto Hide dock container widget
* This will also hide the side tab widget
*/
void toggleView(bool Enable);
/*
* Collapses the auto hide dock container widget
* Does not hide the side tab widget
*/
void collapseView(bool Enable);
/**
* Toggles the current collapse state
*/
void toggleCollapseState();
/**
* Use this instead of resize.
* Depending on the sidebar location this will set the width or heigth
* of this auto hide container.
*/
void setSize(int Size);
};
} // namespace ads
//-----------------------------------------------------------------------------
#endif

388
src/AutoHideSideBar.cpp Normal file
View File

@@ -0,0 +1,388 @@
/*******************************************************************************
** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
//============================================================================
/// \file AutoHideSideBar.cpp
/// \author Syarif Fakhri
/// \date 05.09.2022
/// \brief Implementation of CAutoHideSideBar class
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include "AutoHideSideBar.h"
#include <QBoxLayout>
#include <QStyleOption>
#include <QPainter>
#include <QXmlStreamWriter>
#include "DockContainerWidget.h"
#include "DockWidgetTab.h"
#include "DockFocusController.h"
#include "AutoHideDockContainer.h"
#include "DockAreaWidget.h"
#include "DockingStateReader.h"
#include "AutoHideTab.h"
namespace ads
{
class CTabsWidget;
/**
* Private data class of CSideTabBar class (pimpl)
*/
struct AutoHideSideBarPrivate
{
/**
* Private data constructor
*/
AutoHideSideBarPrivate(CAutoHideSideBar* _public);
CAutoHideSideBar* _this;
CDockContainerWidget* ContainerWidget;
CTabsWidget* TabsContainerWidget;
QBoxLayout* TabsLayout;
Qt::Orientation Orientation;
SideBarLocation SideTabArea = SideBarLocation::SideBarLeft;
/**
* Convenience function to check if this is a horizontal side bar
*/
bool isHorizontal() const
{
return Qt::Horizontal == Orientation;
}
/**
* Called from viewport to forward event handling to this
*/
void handleViewportEvent(QEvent* e);
}; // struct AutoHideSideBarPrivate
/**
* This widget stores the tab buttons
*/
class CTabsWidget : public QWidget
{
public:
using QWidget::QWidget;
using Super = QWidget;
AutoHideSideBarPrivate* EventHandler;
/**
* Returns the size hint as minimum size hint
*/
virtual QSize minimumSizeHint() const override
{
return Super::sizeHint();
}
/**
* Forward event handling to EventHandler
*/
virtual bool event(QEvent* e) override
{
EventHandler->handleViewportEvent(e);
return Super::event(e);
}
};
//============================================================================
AutoHideSideBarPrivate::AutoHideSideBarPrivate(CAutoHideSideBar* _public) :
_this(_public)
{
}
//============================================================================
void AutoHideSideBarPrivate::handleViewportEvent(QEvent* e)
{
switch (e->type())
{
case QEvent::ChildRemoved:
if (TabsLayout->isEmpty())
{
_this->hide();
}
break;
case QEvent::Resize:
if (_this->tabCount())
{
auto ev = static_cast<QResizeEvent*>(e);
auto Tab = _this->tabAt(0);
int Size = isHorizontal() ? ev->size().height() : ev->size().width();
int TabSize = isHorizontal() ? Tab->size().height() : Tab->size().width();
// If the size of the side bar is less than the size of the first tab
// then there are no visible tabs in this side bar. This check will
// fail if someone will force a very big border via CSS!!
if (Size < TabSize)
{
_this->hide();
}
}
else
{
_this->hide();
}
break;
default:
break;
}
}
//============================================================================
CAutoHideSideBar::CAutoHideSideBar(CDockContainerWidget* parent, SideBarLocation area) :
Super(parent),
d(new AutoHideSideBarPrivate(this))
{
d->SideTabArea = area;
d->ContainerWidget = parent;
d->Orientation = (area == SideBarLocation::SideBarBottom || area == SideBarLocation::SideBarTop)
? Qt::Horizontal : Qt::Vertical;
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
setFrameStyle(QFrame::NoFrame);
setWidgetResizable(true);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
d->TabsContainerWidget = new CTabsWidget();
d->TabsContainerWidget->EventHandler = d;
d->TabsContainerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
d->TabsContainerWidget->setObjectName("sideTabsContainerWidget");
d->TabsLayout = new QBoxLayout(d->Orientation == Qt::Vertical ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight);
d->TabsLayout->setContentsMargins(0, 0, 0, 0);
d->TabsLayout->setSpacing(12);
d->TabsLayout->addStretch(1);
d->TabsContainerWidget->setLayout(d->TabsLayout);
setWidget(d->TabsContainerWidget);
setFocusPolicy(Qt::NoFocus);
if (d->isHorizontal())
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
}
else
{
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
}
hide();
}
//============================================================================
CAutoHideSideBar::~CAutoHideSideBar()
{
ADS_PRINT("~CSideTabBar()");
// The SideTabeBar is not the owner of the tabs and to prevent deletion
// we set the parent here to nullptr to remove it from the children
auto Tabs = findChildren<CAutoHideTab*>(QString(), Qt::FindDirectChildrenOnly);
for (auto Tab : Tabs)
{
Tab->setParent(nullptr);
}
delete d;
}
//============================================================================
void CAutoHideSideBar::insertTab(int Index, CAutoHideTab* SideTab)
{
SideTab->setSideBar(this);
SideTab->installEventFilter(this);
if (Index < 0)
{
d->TabsLayout->insertWidget(d->TabsLayout->count() - 1, SideTab);
}
else
{
d->TabsLayout->insertWidget(Index, SideTab);
}
show();
}
//============================================================================
CAutoHideDockContainer* CAutoHideSideBar::insertDockWidget(int Index, CDockWidget* DockWidget)
{
auto AutoHideContainer = new CAutoHideDockContainer(DockWidget, d->SideTabArea, d->ContainerWidget);
DockWidget->dockManager()->dockFocusController()->clearDockWidgetFocus(DockWidget);
auto Tab = AutoHideContainer->autoHideTab();
DockWidget->setSideTabWidget(Tab);
insertTab(Index, Tab);
return AutoHideContainer;
}
//============================================================================
void CAutoHideSideBar::removeAutoHideWidget(CAutoHideDockContainer* AutoHideWidget)
{
AutoHideWidget->autoHideTab()->removeFromSideBar();
auto DockContainer = AutoHideWidget->dockContainer();
if (DockContainer)
{
DockContainer->removeAutoHideWidget(AutoHideWidget);
}
AutoHideWidget->setParent(nullptr);
}
//============================================================================
void CAutoHideSideBar::addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget)
{
auto SideBar = AutoHideWidget->autoHideTab()->sideBar();
if (SideBar == this)
{
return;
}
if (SideBar)
{
SideBar->removeAutoHideWidget(AutoHideWidget);
}
AutoHideWidget->setParent(d->ContainerWidget);
AutoHideWidget->setSideBarLocation(d->SideTabArea);
d->ContainerWidget->registerAutoHideWidget(AutoHideWidget);
insertTab(-1, AutoHideWidget->autoHideTab());
}
//============================================================================
void CAutoHideSideBar::removeTab(CAutoHideTab* SideTab)
{
SideTab->removeEventFilter(this);
d->TabsLayout->removeWidget(SideTab);
if (d->TabsLayout->isEmpty())
{
hide();
}
}
//============================================================================
bool CAutoHideSideBar::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() != QEvent::ShowToParent)
{
return false;
}
// As soon as on tab is shown, we need to show the side tab bar
auto Tab = qobject_cast<CAutoHideTab*>(watched);
if (Tab)
{
show();
}
return false;
}
//============================================================================
Qt::Orientation CAutoHideSideBar::orientation() const
{
return d->Orientation;
}
//============================================================================
CAutoHideTab* CAutoHideSideBar::tabAt(int index) const
{
return qobject_cast<CAutoHideTab*>(d->TabsLayout->itemAt(index)->widget());
}
//============================================================================
int CAutoHideSideBar::tabCount() const
{
return d->TabsLayout->count() - 1;
}
//============================================================================
SideBarLocation CAutoHideSideBar::sideBarLocation() const
{
return d->SideTabArea;
}
//============================================================================
void CAutoHideSideBar::saveState(QXmlStreamWriter& s) const
{
if (!tabCount())
{
return;
}
s.writeStartElement("SideBar");
s.writeAttribute("Area", QString::number(sideBarLocation()));
s.writeAttribute("Tabs", QString::number(tabCount()));
for (auto i = 0; i < tabCount(); ++i)
{
auto Tab = tabAt(i);
if (!Tab)
{
continue;
}
Tab->dockWidget()->autoHideDockContainer()->saveState(s);
}
s.writeEndElement();
}
//===========================================================================
QSize CAutoHideSideBar::minimumSizeHint() const
{
QSize Size = sizeHint();
Size.setWidth(10);
return Size;
}
//===========================================================================
QSize CAutoHideSideBar::sizeHint() const
{
return d->TabsContainerWidget->sizeHint();
}
//===========================================================================
int CAutoHideSideBar::spacing() const
{
return d->TabsLayout->spacing();
}
//===========================================================================
void CAutoHideSideBar::setSpacing(int Spacing)
{
d->TabsLayout->setSpacing(Spacing);
}
} // namespace ads

169
src/AutoHideSideBar.h Normal file
View File

@@ -0,0 +1,169 @@
#ifndef AutoHideSideBarH
#define AutoHideSideBarH
/*******************************************************************************
** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
//============================================================================
/// \file AutoHideSideBar.h
/// \author Syarif Fakhri
/// \date 05.09.2022
/// \brief Declaration of CAutoHideSideBar class
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include <QScrollArea>
#include "ads_globals.h"
#include "AutoHideTab.h"
class QXmlStreamWriter;
namespace ads
{
struct AutoHideSideBarPrivate;
class DockContainerWidgetPrivate;
class CDockContainerWidget;
class CAutoHideTab;
class CAutoHideDockContainer;
class CDockingStateReader;
/**
* Side tab bar widget that is shown at the edges of a dock container.
* The tab bar is only visible, if it contains visible content, that means if
* it contains visible tabs. If it is empty or all tabs are hidden, then the
* side bar is also hidden. As soon as one single tab becomes visible, this
* tab bar will be shown.
* The CAutoHideSideBar uses a QScrollArea here, to enable proper resizing.
* If the side bar contains many tabs, then the tabs are simply clipped - this
* is the same like in visual studio
*/
class ADS_EXPORT CAutoHideSideBar : public QScrollArea
{
Q_OBJECT
Q_PROPERTY(int sideBarLocation READ sideBarLocation)
Q_PROPERTY(Qt::Orientation orientation READ orientation)
Q_PROPERTY(int spacing READ spacing WRITE setSpacing)
private:
AutoHideSideBarPrivate* d; ///< private data (pimpl)
friend struct AutoHideSideBarPrivate;
friend class DockWidgetSideTab;
friend DockContainerWidgetPrivate;
friend CDockContainerWidget;
protected:
virtual bool eventFilter(QObject *watched, QEvent *event) override;
/**
* Saves the state into the given stream
*/
void saveState(QXmlStreamWriter& Stream) const;
/**
* Inserts the given dock widget tab at the given position.
* An Index value of -1 appends the side tab at the end.
*/
void insertTab(int Index, CAutoHideTab* SideTab);
public:
using Super = QScrollArea;
/**
* Default Constructor
*/
CAutoHideSideBar(CDockContainerWidget* parent, SideBarLocation area);
/**
* Virtual Destructor
*/
virtual ~CAutoHideSideBar();
/**
* Removes the given DockWidgetSideTab from the tabbar
*/
void removeTab(CAutoHideTab* SideTab);
/**
* Insert dock widget into the side bar.
* The function creates the auto hide dock container, inserts the
* auto hide tab
*/
CAutoHideDockContainer* insertDockWidget(int Index, CDockWidget* DockWidget);
/**
* Removes the auto hide widget from this side bar
*/
void removeAutoHideWidget(CAutoHideDockContainer* AutoHideWidget);
/**
* Adds the given AutoHideWidget to this sidebar.
* If the AutoHideWidget is in another sidebar, then it will be removed
* from this sidebar.
*/
void addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget);
/**
* Returns orientation of side tab.
*/
Qt::Orientation orientation() const;
/*
* get the side tab widget at position, returns nullptr if it's out of bounds
*/
CAutoHideTab* tabAt(int index) const;
/*
* Gets the count of the tab widgets
*/
int tabCount() const;
/**
* Getter for side tab bar area property
*/
SideBarLocation sideBarLocation() const;
/**
* Overrides the minimumSizeHint() function of QScrollArea
* The minimumSizeHint() is bigger than the sizeHint () for the scroll
* area because even if the scrollbars are invisible, the required speace
* is reserved in the minimumSizeHint(). This override simply returns
* sizeHint();
*/
virtual QSize minimumSizeHint() const override;
/**
* The function provides a sizeHint that matches the height of the
* internal viewport.
*/
virtual QSize sizeHint() const override;
/**
* Getter for spacing property - returns the spacing of the tabs
*/
int spacing() const;
/**
* Setter for spacing property - sets the spacing
*/
void setSpacing(int Spacing);
};
} // namespace ads
//-----------------------------------------------------------------------------
#endif

281
src/AutoHideTab.cpp Normal file
View File

@@ -0,0 +1,281 @@
/*******************************************************************************
** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
//============================================================================
/// \file AutoHideTab.cpp
/// \author Syarif Fakhri
/// \date 05.09.2022
/// \brief Implementation of CAutoHideTab class
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include "AutoHideTab.h"
#include <QBoxLayout>
#include <QApplication>
#include <QElapsedTimer>
#include "AutoHideDockContainer.h"
#include "AutoHideSideBar.h"
#include "DockAreaWidget.h"
#include "DockManager.h"
#include "DockWidget.h"
namespace ads
{
/**
* Private data class of CDockWidgetTab class (pimpl)
*/
struct AutoHideTabPrivate
{
CAutoHideTab* _this;
CDockWidget* DockWidget = nullptr;
CAutoHideSideBar* SideBar = nullptr;
Qt::Orientation Orientation{Qt::Vertical};
QElapsedTimer TimeSinceHoverMousePress;
/**
* Private data constructor
*/
AutoHideTabPrivate(CAutoHideTab* _public);
/**
* Update the orientation, visibility and spacing based on the area of
* the side bar
*/
void updateOrientation();
/**
* Convenience function to ease dock container access
*/
CDockContainerWidget* dockContainer() const
{
return DockWidget ? DockWidget->dockContainer() : nullptr;
}
/**
* Forward this event to the dock container
*/
void forwardEventToDockContainer(QEvent* event)
{
auto DockContainer = dockContainer();
if (DockContainer)
{
DockContainer->handleAutoHideWidgetEvent(event, _this);
}
}
}; // struct DockWidgetTabPrivate
//============================================================================
AutoHideTabPrivate::AutoHideTabPrivate(CAutoHideTab* _public) :
_this(_public)
{
}
//============================================================================
void AutoHideTabPrivate::updateOrientation()
{
bool IconOnly = CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideSideBarsIconOnly);
if (IconOnly && !_this->icon().isNull())
{
_this->setText("");
_this->setOrientation(Qt::Horizontal);
}
else
{
auto area = SideBar->sideBarLocation();
_this->setOrientation((area == SideBarBottom || area == SideBarTop) ? Qt::Horizontal : Qt::Vertical);
}
}
//============================================================================
void CAutoHideTab::setSideBar(CAutoHideSideBar* SideTabBar)
{
d->SideBar = SideTabBar;
if (d->SideBar)
{
d->updateOrientation();
}
}
//============================================================================
CAutoHideSideBar* CAutoHideTab::sideBar() const
{
return d->SideBar;
}
//============================================================================
void CAutoHideTab::removeFromSideBar()
{
if (d->SideBar == nullptr)
{
return;
}
d->SideBar->removeTab(this);
setSideBar(nullptr);
}
//============================================================================
CAutoHideTab::CAutoHideTab(QWidget* parent) :
CPushButton(parent),
d(new AutoHideTabPrivate(this))
{
setAttribute(Qt::WA_NoMousePropagation);
setFocusPolicy(Qt::NoFocus);
}
//============================================================================
CAutoHideTab::~CAutoHideTab()
{
ADS_PRINT("~CDockWidgetSideTab()");
delete d;
}
//============================================================================
void CAutoHideTab::updateStyle()
{
internal::repolishStyle(this, internal::RepolishDirectChildren);
update();
}
//============================================================================
SideBarLocation CAutoHideTab::sideBarLocation() const
{
if (d->SideBar)
{
return d->SideBar->sideBarLocation();
}
return SideBarLeft;
}
//============================================================================
void CAutoHideTab::setOrientation(Qt::Orientation Orientation)
{
d->Orientation = Orientation;
if (orientation() == Qt::Horizontal)
{
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
}
else
{
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
}
CPushButton::setButtonOrientation((Qt::Horizontal == Orientation)
? CPushButton::Horizontal : CPushButton::VerticalTopToBottom);
updateStyle();
}
//============================================================================
Qt::Orientation CAutoHideTab::orientation() const
{
return d->Orientation;
}
//============================================================================
bool CAutoHideTab::isActiveTab() const
{
if (d->DockWidget && d->DockWidget->autoHideDockContainer())
{
return d->DockWidget->autoHideDockContainer()->isVisible();
}
return false;
}
//============================================================================
CDockWidget* CAutoHideTab::dockWidget() const
{
return d->DockWidget;
}
//============================================================================
void CAutoHideTab::setDockWidget(CDockWidget* DockWidget)
{
if (!DockWidget)
{
return;
}
d->DockWidget = DockWidget;
setText(DockWidget->windowTitle());
setIcon(d->DockWidget->icon());
setToolTip(DockWidget->windowTitle());
}
//============================================================================
bool CAutoHideTab::event(QEvent* event)
{
if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideShowOnMouseOver))
{
return Super::event(event);
}
switch (event->type())
{
case QEvent::Enter:
case QEvent::Leave:
d->forwardEventToDockContainer(event);
break;
case QEvent::MouseButtonPress:
// If AutoHideShowOnMouseOver is active, then the showing is triggered
// by a MousePressEvent sent to this tab. To prevent accidental hiding
// of the tab by a mouse click, we wait at least 500 ms before we accept
// the mouse click
if (!event->spontaneous())
{
d->TimeSinceHoverMousePress.restart();
d->forwardEventToDockContainer(event);
}
else if (d->TimeSinceHoverMousePress.hasExpired(500))
{
d->forwardEventToDockContainer(event);
}
break;
default:
break;
}
return Super::event(event);
}
//============================================================================
bool CAutoHideTab::iconOnly() const
{
return CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideSideBarsIconOnly) && !icon().isNull();
}
}

141
src/AutoHideTab.h Normal file
View File

@@ -0,0 +1,141 @@
#ifndef AutoHideTabH
#define AutoHideTabH
/*******************************************************************************
** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
//============================================================================
/// \file AutoHideTab.h
/// \author Syarif Fakhri
/// \date 05.09.2022
/// \brief Declaration of CAutoHideTab class
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include "PushButton.h"
#include "ads_globals.h"
namespace ads
{
struct AutoHideTabPrivate;
class CDockWidget;
class CAutoHideSideBar;
class CDockWidgetTab;
class DockContainerWidgetPrivate;
/**
* A dock widget Side tab that shows a title or an icon.
* The dock widget tab is shown in the side tab bar to switch between
* pinned dock widgets
*/
class ADS_EXPORT CAutoHideTab : public CPushButton
{
Q_OBJECT
Q_PROPERTY(int sideBarLocation READ sideBarLocation)
Q_PROPERTY(Qt::Orientation orientation READ orientation)
Q_PROPERTY(bool activeTab READ isActiveTab)
Q_PROPERTY(bool iconOnly READ iconOnly)
private:
AutoHideTabPrivate* d; ///< private data (pimpl)
friend struct AutoHideTabPrivate;
friend class CDockWidget;
friend class CAutoHideDockContainer;
friend class CAutoHideSideBar;
friend class CDockAreaWidget;
friend class CDockContainerWidget;
friend DockContainerWidgetPrivate;
protected:
void setSideBar(CAutoHideSideBar *SideTabBar);
void removeFromSideBar();
virtual bool event(QEvent* event) override;
public:
using Super = CPushButton;
/**
* Default Constructor
* param[in] DockWidget The dock widget this title bar belongs to
* param[in] parent The parent widget of this title bar
*/
CAutoHideTab(QWidget* parent = nullptr);
/**
* Virtual Destructor
*/
virtual ~CAutoHideTab();
/**
* Update stylesheet style if a property changes
*/
void updateStyle();
/**
* Getter for side tab bar area property
*/
SideBarLocation sideBarLocation() const;
/**
* Set orientation vertical or horizontal
*/
void setOrientation(Qt::Orientation Orientation);
/**
* Returns the current orientation
*/
Qt::Orientation orientation() const;
/**
* Returns true, if this is the active tab. The tab is active if the auto
* hide widget is visible
*/
bool isActiveTab() const;
/**
* returns the dock widget this belongs to
*/
CDockWidget* dockWidget() const;
/**
* Sets the dock widget that is controlled by this tab
*/
void setDockWidget(CDockWidget* DockWidget);
/**
* Returns true if the auto hide config flag AutoHideSideBarsIconOnly
* is set and if the tab has an icon - that means the icon is not null
*/
bool iconOnly() const;
/**
* Returns the side bar that contains this tab or a nullptr if the tab is
* not in a side bar
*/
CAutoHideSideBar* sideBar() const;
}; // class AutoHideTab
}
// namespace ads
//-----------------------------------------------------------------------------
#endif

View File

@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.5)
project(QtAdvancedDockingSystem LANGUAGES CXX VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Widgets REQUIRED)
if (UNIX AND NOT APPLE)
include_directories(${Qt${QT_VERSION_MAJOR}Gui_PRIVATE_INCLUDE_DIRS})
endif()
@@ -27,6 +27,11 @@ set(ads_SRCS
FloatingDragPreview.cpp
IconProvider.cpp
DockComponentsFactory.cpp
AutoHideSideBar.cpp
AutoHideTab.cpp
AutoHideDockContainer.cpp
PushButton.cpp
ResizeHandle.cpp
ads.qrc
)
set(ads_HEADERS
@@ -48,6 +53,11 @@ set(ads_HEADERS
FloatingDragPreview.h
IconProvider.h
DockComponentsFactory.h
AutoHideSideBar.h
AutoHideTab.h
AutoHideDockContainer.h
PushButton.h
ResizeHandle.h
)
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
if (UNIX AND NOT APPLE)
@@ -61,14 +71,18 @@ else()
add_library(qtadvanceddocking SHARED ${ads_SRCS} ${ads_HEADERS})
target_compile_definitions(qtadvanceddocking PRIVATE ADS_SHARED_EXPORT)
endif()
add_library(ads::qtadvanceddocking ALIAS qtadvanceddocking)
target_link_libraries(qtadvanceddocking PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
if (UNIX AND NOT APPLE)
target_link_libraries(qtadvanceddocking PUBLIC xcb)
endif()
set_target_properties(qtadvanceddocking PROPERTIES
AUTOMOC ON
AUTORCC ON
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
VERSION ${VERSION_SHORT}
EXPORT_NAME "qtadvanceddocking"
@@ -76,6 +90,16 @@ set_target_properties(qtadvanceddocking PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/bin"
)
if(QT_VERSION_MAJOR STREQUAL "5")
set_target_properties(qtadvanceddocking PROPERTIES
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON)
elseif(QT_VERSION_MAJOR STREQUAL "6")
set_target_properties(qtadvanceddocking PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON)
endif()
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"qtadvanceddockingConfigVersion.cmake"
@@ -87,9 +111,9 @@ install(FILES ${ads_HEADERS}
COMPONENT headers
)
install(FILES
"${CMAKE_SOURCE_DIR}/LICENSE"
"${CMAKE_SOURCE_DIR}/gnu-lgpl-v2.1.md"
DESTINATION license
"${CMAKE_CURRENT_SOURCE_DIR}/../LICENSE"
"${CMAKE_CURRENT_SOURCE_DIR}/../gnu-lgpl-v2.1.md"
DESTINATION license/ads
COMPONENT license
)
install(TARGETS qtadvanceddocking

View File

@@ -203,7 +203,7 @@ void CDockAreaTabBar::insertTab(int Index, CDockWidgetTab* Tab)
connect(Tab, SIGNAL(clicked()), this, SLOT(onTabClicked()));
connect(Tab, SIGNAL(closeRequested()), this, SLOT(onTabCloseRequested()));
connect(Tab, SIGNAL(closeOtherTabsRequested()), this, SLOT(onCloseOtherTabsRequested()));
connect(Tab, SIGNAL(moved(const QPoint&)), this, SLOT(onTabWidgetMoved(const QPoint&)));
connect(Tab, SIGNAL(moved(QPoint)), this, SLOT(onTabWidgetMoved(QPoint)));
connect(Tab, SIGNAL(elidedChanged(bool)), this, SIGNAL(elidedChanged(bool)));
Tab->installEventFilter(this);
Q_EMIT tabInserted(Index);

View File

@@ -38,6 +38,7 @@
#include <QMouseEvent>
#include <QDebug>
#include <QPointer>
#include <QApplication>
#include "DockAreaTitleBar_p.h"
#include "ads_globals.h"
@@ -49,14 +50,17 @@
#include "DockWidget.h"
#include "DockWidgetTab.h"
#include "DockAreaTabBar.h"
#include "IconProvider.h"
#include "DockComponentsFactory.h"
#include "DockFocusController.h"
#include "ElidingLabel.h"
#include "AutoHideDockContainer.h"
#include "IconProvider.h"
#include <iostream>
namespace ads
{
static const char* const LocationProperty = "Location";
/**
* Private data class of CDockAreaTitleBar class (pimpl)
@@ -65,11 +69,13 @@ struct DockAreaTitleBarPrivate
{
CDockAreaTitleBar* _this;
QPointer<tTitleBarButton> TabsMenuButton;
QPointer<tTitleBarButton> AutoHideButton;
QPointer<tTitleBarButton> UndockButton;
QPointer<tTitleBarButton> CloseButton;
QBoxLayout* Layout;
CDockAreaWidget* DockArea;
CDockAreaTabBar* TabBar;
CElidingLabel* AutoHideTitleLabel;
bool MenuOutdated = true;
QMenu* TabsMenu;
QList<tTitleBarButton*> DockWidgetActionsButtons;
@@ -89,7 +95,13 @@ struct DockAreaTitleBarPrivate
*/
void createButtons();
/**
* Creates the auto hide title label, only displayed when the dock area is overlayed
*/
void createAutoHideTitleLabel();
/**
* Creates the internal TabBar
*/
void createTabBar();
@@ -111,6 +123,15 @@ struct DockAreaTitleBarPrivate
return CDockManager::testConfigFlag(Flag);
}
/**
* Returns true if the given config flag is set
* Convenience function to ease config flag testing
*/
static bool testAutoHideConfigFlag(CDockManager::eAutoHideFlag Flag)
{
return CDockManager::testAutoHideConfigFlag(Flag);
}
/**
* Test function for current drag state
*/
@@ -119,7 +140,6 @@ struct DockAreaTitleBarPrivate
return this->DragState == dragState;
}
/**
* Starts floating
*/
@@ -129,6 +149,19 @@ struct DockAreaTitleBarPrivate
* Makes the dock area floating
*/
IFloatingWidget* makeAreaFloating(const QPoint& Offset, eDragState DragState);
/**
* Helper function to create and initialize the menu entries for
* the "Auto Hide Group To..." menu
*/
QAction* createAutoHideToAction(const QString& Title, SideBarLocation Location,
QMenu* Menu)
{
auto Action = Menu->addAction(Title);
Action->setProperty("Location", Location);
QObject::connect(Action, &QAction::triggered, _this, &CDockAreaTitleBar::onAutoHideToActionClicked);
return Action;
}
};// struct DockAreaTitleBarPrivate
//============================================================================
@@ -172,19 +205,25 @@ void DockAreaTitleBarPrivate::createButtons()
Layout->addWidget(UndockButton, 0);
_this->connect(UndockButton, SIGNAL(clicked()), SLOT(onUndockButtonClicked()));
// AutoHide Button
const auto autoHideEnabled = testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled);
AutoHideButton = new CTitleBarButton(testAutoHideConfigFlag(CDockManager::DockAreaHasAutoHideButton) && autoHideEnabled);
AutoHideButton->setObjectName("dockAreaAutoHideButton");
AutoHideButton->setAutoRaise(true);
internal::setToolTip(AutoHideButton, _this->titleBarButtonToolTip(TitleBarButtonAutoHide));
internal::setButtonIcon(AutoHideButton, QStyle::SP_DialogOkButton, ads::AutoHideIcon);
AutoHideButton->setSizePolicy(ButtonSizePolicy);
AutoHideButton->setCheckable(testAutoHideConfigFlag(CDockManager::AutoHideButtonCheckable));
AutoHideButton->setChecked(false);
Layout->addWidget(AutoHideButton, 0);
_this->connect(AutoHideButton, SIGNAL(clicked()), SLOT(onAutoHideButtonClicked()));
// Close button
CloseButton = new CTitleBarButton(testConfigFlag(CDockManager::DockAreaHasCloseButton));
CloseButton->setObjectName("dockAreaCloseButton");
CloseButton->setAutoRaise(true);
internal::setButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton, ads::DockAreaCloseIcon);
if (testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
{
internal::setToolTip(CloseButton, QObject::tr("Close Active Tab"));
}
else
{
internal::setToolTip(CloseButton, QObject::tr("Close Group"));
}
internal::setToolTip(CloseButton, _this->titleBarButtonToolTip(TitleBarButtonClose));
CloseButton->setSizePolicy(ButtonSizePolicy);
CloseButton->setIconSize(QSize(16, 16));
Layout->addWidget(CloseButton, 0);
@@ -192,6 +231,15 @@ void DockAreaTitleBarPrivate::createButtons()
}
//============================================================================
void DockAreaTitleBarPrivate::createAutoHideTitleLabel()
{
AutoHideTitleLabel = new CElidingLabel("");
AutoHideTitleLabel->setObjectName("autoHideTitleLabel");
Layout->addWidget(AutoHideTitleLabel);
}
//============================================================================
void DockAreaTitleBarPrivate::createTabBar()
{
@@ -249,7 +297,12 @@ IFloatingWidget* DockAreaTitleBarPrivate::makeAreaFloating(const QPoint& Offset,
//============================================================================
void DockAreaTitleBarPrivate::startFloating(const QPoint& Offset)
{
if (DockArea->autoHideDockContainer() != nullptr)
{
DockArea->autoHideDockContainer()->hide();
}
FloatingWidget = makeAreaFloating(Offset, DraggingFloatingWidget);
qApp->postEvent(DockArea, new QEvent((QEvent::Type)internal::DockedWidgetDragStartEvent));
}
@@ -268,6 +321,8 @@ CDockAreaTitleBar::CDockAreaTitleBar(CDockAreaWidget* parent) :
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
d->createTabBar();
d->createAutoHideTitleLabel();
d->AutoHideTitleLabel->setVisible(false); // Default hidden
d->Layout->addWidget(new CSpacerWidget(this));
d->createButtons();
@@ -373,6 +428,11 @@ void CDockAreaTitleBar::onUndockButtonClicked()
{
if (d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
{
if (d->DockArea->autoHideDockContainer())
{
d->DockArea->autoHideDockContainer()->cleanupAndDelete();
}
d->makeAreaFloating(mapFromGlobal(QCursor::pos()), DraggingInactive);
}
}
@@ -390,7 +450,13 @@ void CDockAreaTitleBar::onTabsMenuActionTriggered(QAction* Action)
//============================================================================
void CDockAreaTitleBar::updateDockWidgetActionsButtons()
{
CDockWidget* DockWidget = d->TabBar->currentTab()->dockWidget();
auto Tab = d->TabBar->currentTab();
if (!Tab)
{
return;
}
CDockWidget* DockWidget = Tab->dockWidget();
if (!d->DockWidgetActionsButtons.isEmpty())
{
for (auto Button : d->DockWidgetActionsButtons)
@@ -439,6 +505,36 @@ void CDockAreaTitleBar::onCurrentTabChanged(int Index)
}
//============================================================================
void CDockAreaTitleBar::onAutoHideButtonClicked()
{
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideButtonTogglesArea)
|| qApp->keyboardModifiers().testFlag(Qt::ControlModifier))
{
d->DockArea->toggleAutoHide();
}
else
{
d->DockArea->currentDockWidget()->toggleAutoHide();
}
}
//============================================================================
void CDockAreaTitleBar::onAutoHideDockAreaActionClicked()
{
d->DockArea->toggleAutoHide();
}
//============================================================================
void CDockAreaTitleBar::onAutoHideToActionClicked()
{
int Location = sender()->property(LocationProperty).toInt();
d->DockArea->toggleAutoHide((SideBarLocation)Location);
}
//============================================================================
QAbstractButton* CDockAreaTitleBar::button(TitleBarButton which) const
{
@@ -447,12 +543,20 @@ QAbstractButton* CDockAreaTitleBar::button(TitleBarButton which) const
case TitleBarButtonTabsMenu: return d->TabsMenuButton;
case TitleBarButtonUndock: return d->UndockButton;
case TitleBarButtonClose: return d->CloseButton;
case TitleBarButtonAutoHide: return d->AutoHideButton;
default:
return nullptr;
}
}
//============================================================================
CElidingLabel* CDockAreaTitleBar::autoHideTitleLabel() const
{
return d->AutoHideTitleLabel;
}
//============================================================================
void CDockAreaTitleBar::setVisible(bool Visible)
{
@@ -472,7 +576,6 @@ void CDockAreaTitleBar::mousePressEvent(QMouseEvent* ev)
if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
{
//d->TabBar->currentTab()->setFocus(Qt::OtherFocusReason);
d->dockManager()->dockFocusController()->setDockWidgetTabFocused(d->TabBar->currentTab());
}
return;
@@ -523,7 +626,8 @@ void CDockAreaTitleBar::mouseMoveEvent(QMouseEvent* ev)
// sense to move it to a new floating widget and leave this one
// empty
if (d->DockArea->dockContainer()->isFloating()
&& d->DockArea->dockContainer()->visibleDockAreaCount() == 1)
&& d->DockArea->dockContainer()->visibleDockAreaCount() == 1
&& !d->DockArea->isAutoHide())
{
return;
}
@@ -542,7 +646,7 @@ void CDockAreaTitleBar::mouseMoveEvent(QMouseEvent* ev)
int DragDistance = (d->DragStartMousePos - ev->pos()).manhattanLength();
if (DragDistance >= CDockManager::startDragDistance())
{
ADS_PRINT("CDockAreaTitlBar::startFloating");
ADS_PRINT("CDockAreaTitleBar::startFloating");
d->startFloating(d->DragStartMousePos);
auto Overlay = d->DockArea->dockManager()->containerOverlay();
Overlay->setAllowedAreas(OuterDockAreas);
@@ -567,6 +671,11 @@ void CDockAreaTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
return;
}
if (d->DockArea->autoHideDockContainer())
{
d->DockArea->autoHideDockContainer()->cleanupAndDelete();
}
d->makeAreaFloating(event->pos(), DraggingInactive);
}
@@ -580,13 +689,39 @@ void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev)
return;
}
const bool isAutoHide = d->DockArea->isAutoHide();
const bool isTopLevelArea = d->DockArea->isTopLevelArea();
QAction* Action;
QMenu Menu(this);
auto Action = Menu.addAction(tr("Detach Group"), this, SLOT(onUndockButtonClicked()));
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable));
Menu.addSeparator();
Action = Menu.addAction(tr("Close Group"), this, SLOT(onCloseButtonClicked()));
if (!isTopLevelArea)
{
Action = Menu.addAction(isAutoHide ? tr("Detach") : tr("Detach Group"),
this, SLOT(onUndockButtonClicked()));
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable));
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
{
Action = Menu.addAction(isAutoHide ? tr("Unpin (Dock)") : tr("Pin Group"), this, SLOT(onAutoHideDockAreaActionClicked()));
auto AreaIsPinnable = d->DockArea->features().testFlag(CDockWidget::DockWidgetPinnable);
Action->setEnabled(AreaIsPinnable);
if (!isAutoHide)
{
auto menu = Menu.addMenu(tr("Pin Group To..."));
menu->setEnabled(AreaIsPinnable);
d->createAutoHideToAction(tr("Top"), SideBarTop, menu);
d->createAutoHideToAction(tr("Left"), SideBarLeft, menu);
d->createAutoHideToAction(tr("Right"), SideBarRight, menu);
d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu);
}
}
Menu.addSeparator();
}
Action = Menu.addAction(isAutoHide ? tr("Close") : tr("Close Group"), this, SLOT(onCloseButtonClicked()));
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable));
Menu.addAction(tr("Close Other Groups"), d->DockArea, SLOT(closeOtherAreas()));
if (!isAutoHide && !isTopLevelArea)
{
Action = Menu.addAction(tr("Close Other Groups"), d->DockArea, SLOT(closeOtherAreas()));
}
Menu.exec(ev->globalPos());
}
@@ -604,6 +739,50 @@ int CDockAreaTitleBar::indexOf(QWidget *widget) const
return d->Layout->indexOf(widget);
}
//============================================================================
QString CDockAreaTitleBar::titleBarButtonToolTip(TitleBarButton Button) const
{
switch (Button)
{
case TitleBarButtonAutoHide:
if (d->DockArea->isAutoHide())
{
return tr("Unpin (Dock)");
}
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideButtonTogglesArea))
{
return tr("Pin Group");
}
else
{
return tr("Pin Active Tab (Press Ctrl to Pin Group)");
}
break;
case TitleBarButtonClose:
if (d->DockArea->isAutoHide())
{
return tr("Close");
}
if (CDockManager::testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
{
return tr("Close Active Tab");
}
else
{
return tr("Close Group");
}
break;
default:
break;
}
return QString();
}
//============================================================================
CTitleBarButton::CTitleBarButton(bool visible, QWidget* parent)
: tTitleBarButton(parent),

View File

@@ -41,6 +41,7 @@ namespace ads
class CDockAreaTabBar;
class CDockAreaWidget;
struct DockAreaTitleBarPrivate;
class CElidingLabel;
/**
* Title bar of a dock area.
@@ -60,9 +61,12 @@ private Q_SLOTS:
void onUndockButtonClicked();
void onTabsMenuActionTriggered(QAction* Action);
void onCurrentTabChanged(int Index);
void onAutoHideButtonClicked();
void onAutoHideDockAreaActionClicked();
void onAutoHideToActionClicked();
protected:
/**
/**
* Stores mouse position to detect dragging
*/
virtual void mousePressEvent(QMouseEvent* ev) override;
@@ -119,6 +123,11 @@ public:
*/
QAbstractButton* button(TitleBarButton which) const;
/**
* Returns the auto hide title label, used when the dock area is expanded and auto hidden
*/
CElidingLabel* autoHideTitleLabel() const;
/**
* Updates the visibility of the dock widget actions in the title bar
*/
@@ -148,6 +157,12 @@ public:
*/
int indexOf(QWidget *widget) const;
/**
* Close group tool tip based on the current state
* Auto hide widgets can only have one dock widget so it does not make sense for the tooltip to show close group
*/
QString titleBarButtonToolTip(TitleBarButton Button) const;
Q_SIGNALS:
/**
* This signal is emitted if a tab in the tab bar is clicked by the user

View File

@@ -28,22 +28,21 @@
//============================================================================
// INCLUDES
//============================================================================
#include <AutoHideDockContainer.h>
#include <AutoHideTab.h>
#include "DockAreaWidget.h"
#include <QStackedLayout>
#include <QScrollBar>
#include <QScrollArea>
#include <QWheelEvent>
#include <QStyle>
#include <QPushButton>
#include <QDebug>
#include <QMenu>
#include <QSplitter>
#include <QXmlStreamWriter>
#include <QVector>
#include <QList>
#include "ElidingLabel.h"
#include "DockContainerWidget.h"
#include "DockWidget.h"
#include "FloatingDockContainer.h"
@@ -54,6 +53,7 @@
#include "DockAreaTitleBar.h"
#include "DockComponentsFactory.h"
#include "DockWidgetTab.h"
#include "DockingStateReader.h"
namespace ads
@@ -61,6 +61,15 @@ namespace ads
static const char* const INDEX_PROPERTY = "index";
static const char* const ACTION_PROPERTY = "action";
/**
* Check, if auto hide is enabled
*/
static bool isAutoHideFeatureEnabled()
{
return CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled);
}
/**
* Internal dock area layout mimics stack layout but only inserts the current
* widget into the internal QLayout object.
@@ -249,6 +258,7 @@ struct DockAreaWidgetPrivate
DockAreaLayout* ContentsLayout = nullptr;
CDockAreaTitleBar* TitleBar = nullptr;
CDockManager* DockManager = nullptr;
CAutoHideDockContainer* AutoHideDockContainer = nullptr;
bool UpdateTitleBarButtons = false;
DockWidgetAreas AllowedAreas = DefaultAllowedAreas;
QSize MinSizeHint;
@@ -310,6 +320,11 @@ struct DockAreaWidgetPrivate
*/
void updateTitleBarButtonStates();
/**
* Udpates the enable state of the close and detach button
*/
void updateTitleBarButtonVisibility(bool isTopLevel);
/**
* Scans all contained dock widgets for the max. minimum size hint
*/
@@ -358,11 +373,40 @@ void DockAreaWidgetPrivate::updateTitleBarButtonStates()
_this->features().testFlag(CDockWidget::DockWidgetClosable));
TitleBar->button(TitleBarButtonUndock)->setEnabled(
_this->features().testFlag(CDockWidget::DockWidgetFloatable));
TitleBar->button(TitleBarButtonAutoHide)->setEnabled(
_this->features().testFlag(CDockWidget::DockWidgetPinnable));
TitleBar->updateDockWidgetActionsButtons();
UpdateTitleBarButtons = false;
}
//============================================================================
void DockAreaWidgetPrivate::updateTitleBarButtonVisibility(bool IsTopLevel)
{
auto *const container = _this->dockContainer();
if (!container)
{
return;
}
if (IsTopLevel)
{
TitleBar->button(TitleBarButtonClose)->setVisible(!container->isFloating());
TitleBar->button(TitleBarButtonAutoHide)->setVisible(!container->isFloating());
// Undock and tabs should never show when auto hidden
TitleBar->button(TitleBarButtonUndock)->setVisible(!container->isFloating() && !_this->isAutoHide());
TitleBar->button(TitleBarButtonTabsMenu)->setVisible(!_this->isAutoHide());
}
else
{
TitleBar->button(TitleBarButtonClose)->setVisible(true);
TitleBar->button(TitleBarButtonAutoHide)->setVisible(true);
TitleBar->button(TitleBarButtonUndock)->setVisible(!_this->isAutoHide());
TitleBar->button(TitleBarButtonTabsMenu)->setVisible(!_this->isAutoHide());
}
}
//============================================================================
CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent) :
QFrame(parent),
@@ -404,6 +448,26 @@ CDockContainerWidget* CDockAreaWidget::dockContainer() const
return internal::findParent<CDockContainerWidget*>(this);
}
//============================================================================
CAutoHideDockContainer* CDockAreaWidget::autoHideDockContainer() const
{
return d->AutoHideDockContainer;
}
//============================================================================
bool CDockAreaWidget::isAutoHide() const
{
return d->AutoHideDockContainer != nullptr;
}
//============================================================================
void CDockAreaWidget::setAutoHideDockContainer(CAutoHideDockContainer* AutoHideDockContainer)
{
d->AutoHideDockContainer = AutoHideDockContainer;
updateAutoHideButtonCheckState();
updateTitleBarButtonsToolTips();
}
//============================================================================
void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget)
@@ -416,6 +480,10 @@ void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget)
void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
bool Activate)
{
if (index < 0 || index > d->ContentsLayout->count())
{
index = d->ContentsLayout->count();
}
d->ContentsLayout->insertWidget(index, DockWidget);
DockWidget->setDockArea(this);
DockWidget->tabWidget()->setDockAreaWidget(this);
@@ -426,12 +494,14 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
d->tabBar()->insertTab(index, TabWidget);
d->tabBar()->blockSignals(false);
TabWidget->setVisible(!DockWidget->isClosed());
d->TitleBar->autoHideTitleLabel()->setText(DockWidget->windowTitle());
DockWidget->setProperty(INDEX_PROPERTY, index);
d->MinSizeHint.setHeight(qMax(d->MinSizeHint.height(), DockWidget->minimumSizeHint().height()));
d->MinSizeHint.setWidth(qMax(d->MinSizeHint.width(), DockWidget->minimumSizeHint().width()));
if (Activate)
{
setCurrentIndex(index);
DockWidget->setClosedState(false); // Set current index can show the widget without changing the close state, added to keep the close state consistent
}
// If this dock area is hidden, then we need to make it visible again
// by calling DockWidget->toggleViewInternal(true);
@@ -448,6 +518,20 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
{
ADS_PRINT("CDockAreaWidget::removeDockWidget");
if (!DockWidget)
{
return;
}
// If this dock area is in a auto hide container, then we can delete
// the auto hide container now
if (isAutoHide())
{
autoHideDockContainer()->cleanupAndDelete();
return;
}
auto CurrentDockWidget = currentDockWidget();
auto NextOpenDockWidget = (DockWidget == CurrentDockWidget) ? nextOpenDockWidget(DockWidget) : nullptr;
@@ -530,6 +614,10 @@ void CDockAreaWidget::hideAreaWithNoVisibleContent()
{
FloatingWidget->hide();
}
if (isAutoHide())
{
autoHideDockContainer()->hide();
}
}
@@ -538,7 +626,7 @@ void CDockAreaWidget::onTabCloseRequested(int Index)
{
ADS_PRINT("CDockAreaWidget::onTabCloseRequested " << Index);
auto* DockWidget = dockWidget(Index);
if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) || DockWidget->features().testFlag(CDockWidget::CustomCloseHandling))
{
DockWidget->closeDockWidgetInternal();
}
@@ -584,6 +672,7 @@ void CDockAreaWidget::internalSetCurrentDockWidget(CDockWidget* DockWidget)
}
setCurrentIndex(Index);
DockWidget->setClosedState(false); // Set current index can show the widget without changing the close state, added to keep the close state consistent
}
@@ -747,17 +836,27 @@ void CDockAreaWidget::updateTitleBarVisibility()
return;
}
if (CDockManager::testConfigFlag(CDockManager::AlwaysShowTabs))
if (!d->TitleBar)
{
return;
return;
}
if (d->TitleBar)
{
bool IsAutoHide = isAutoHide();
if (!CDockManager::testConfigFlag(CDockManager::AlwaysShowTabs))
{
bool Hidden = Container->hasTopLevelDockWidget() && (Container->isFloating()
|| CDockManager::testConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar));
Hidden |= (d->Flags.testFlag(HideSingleWidgetTitleBar) && openDockWidgetsCount() == 1);
Hidden &= !IsAutoHide; // Titlebar must always be visible when auto hidden so it can be dragged
d->TitleBar->setVisible(!Hidden);
}
if (isAutoHideFeatureEnabled())
{
auto tabBar = d->TitleBar->tabBar();
tabBar->setVisible(!IsAutoHide); // Never show tab bar when auto hidden
d->TitleBar->autoHideTitleLabel()->setVisible(IsAutoHide); // Always show when auto hidden, never otherwise
updateTitleBarButtonVisibility(Container->topLevelDockArea() == this);
}
}
@@ -772,6 +871,32 @@ void CDockAreaWidget::markTitleBarMenuOutdated()
}
//============================================================================
void CDockAreaWidget::updateAutoHideButtonCheckState()
{
auto autoHideButton = titleBarButton(TitleBarButtonAutoHide);
autoHideButton->blockSignals(true);
autoHideButton->setChecked(isAutoHide());
autoHideButton->blockSignals(false);
}
//============================================================================
void CDockAreaWidget::updateTitleBarButtonVisibility(bool IsTopLevel) const
{
d->updateTitleBarButtonVisibility(IsTopLevel);
}
//============================================================================
void CDockAreaWidget::updateTitleBarButtonsToolTips()
{
internal::setToolTip(titleBarButton(TitleBarButtonClose),
titleBar()->titleBarButtonToolTip(TitleBarButtonClose));
internal::setToolTip(titleBarButton(TitleBarButtonAutoHide),
titleBar()->titleBarButtonToolTip(TitleBarButtonAutoHide));
}
//============================================================================
void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
@@ -781,8 +906,7 @@ void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
auto CurrentDockWidget = currentDockWidget();
QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : "";
s.writeAttribute("Current", Name);
// To keep the saved XML data small, we only save the allowed areas and the
// dock area flags if the values are different from the default values
if (d->AllowedAreas != DefaultAllowedAreas)
{
s.writeAttribute("AllowedAreas", QString::number(d->AllowedAreas, 16));
@@ -802,6 +926,103 @@ void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
}
//============================================================================
bool CDockAreaWidget::restoreState(CDockingStateReader& s, CDockAreaWidget*& CreatedWidget,
bool Testing, CDockContainerWidget* Container)
{
bool Ok;
#ifdef ADS_DEBUG_PRINT
int Tabs = s.attributes().value("Tabs").toInt(&Ok);
if (!Ok)
{
return false;
}
#endif
QString CurrentDockWidget = s.attributes().value("Current").toString();
ADS_PRINT("Restore NodeDockArea Tabs: " << Tabs << " Current: "
<< CurrentDockWidget);
auto DockManager = Container->dockManager();
CDockAreaWidget* DockArea = nullptr;
if (!Testing)
{
DockArea = new CDockAreaWidget(DockManager, Container);
const auto AllowedAreasAttribute = s.attributes().value("AllowedAreas");
if (!AllowedAreasAttribute.isEmpty())
{
DockArea->setAllowedAreas((DockWidgetArea)AllowedAreasAttribute.toInt(nullptr, 16));
}
const auto FlagsAttribute = s.attributes().value("Flags");
if (!FlagsAttribute.isEmpty())
{
DockArea->setDockAreaFlags((CDockAreaWidget::DockAreaFlags)FlagsAttribute.toInt(nullptr, 16));
}
}
while (s.readNextStartElement())
{
if (s.name() != QLatin1String("Widget"))
{
continue;
}
auto ObjectName = s.attributes().value("Name");
if (ObjectName.isEmpty())
{
return false;
}
bool Closed = s.attributes().value("Closed").toInt(&Ok);
if (!Ok)
{
return false;
}
s.skipCurrentElement();
CDockWidget* DockWidget = DockManager->findDockWidget(ObjectName.toString());
if (!DockWidget || Testing)
{
continue;
}
ADS_PRINT("Dock Widget found - parent " << DockWidget->parent());
if (DockWidget->autoHideDockContainer())
{
DockWidget->autoHideDockContainer()->cleanupAndDelete();
}
// We hide the DockArea here to prevent the short display (the flashing)
// of the dock areas during application startup
DockArea->hide();
DockArea->addDockWidget(DockWidget);
DockWidget->setToggleViewActionChecked(!Closed);
DockWidget->setClosedState(Closed);
DockWidget->setProperty(internal::ClosedProperty, Closed);
DockWidget->setProperty(internal::DirtyProperty, false);
}
if (Testing)
{
return true;
}
if (!DockArea->dockWidgetsCount())
{
delete DockArea;
DockArea = nullptr;
}
else
{
DockArea->setProperty("currentDockWidget", CurrentDockWidget);
}
CreatedWidget = DockArea;
return true;
}
//============================================================================
CDockWidget* CDockAreaWidget::nextOpenDockWidget(CDockWidget* DockWidget) const
{
@@ -956,9 +1177,13 @@ QAbstractButton* CDockAreaWidget::titleBarButton(TitleBarButton which) const
void CDockAreaWidget::closeArea()
{
// If there is only one single dock widget and this widget has the
// DeleteOnClose feature, then we delete the dock widget now
// DeleteOnClose feature or CustomCloseHandling, then we delete the dock widget now;
// in the case of CustomCloseHandling, the CDockWidget class will emit its
// closeRequested signal and not actually delete unless the signal is handled in a way that deletes it
auto OpenDockWidgets = openedDockWidgets();
if (OpenDockWidgets.count() == 1 && OpenDockWidgets[0]->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
if (OpenDockWidgets.count() == 1 &&
(OpenDockWidgets[0]->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) || OpenDockWidgets[0]->features().testFlag(CDockWidget::CustomCloseHandling))
&& !isAutoHide())
{
OpenDockWidgets[0]->closeDockWidgetInternal();
}
@@ -966,15 +1191,172 @@ void CDockAreaWidget::closeArea()
{
for (auto DockWidget : openedDockWidgets())
{
if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) && DockWidget->features().testFlag(CDockWidget::DockWidgetForceCloseWithArea))
if ((DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) && DockWidget->features().testFlag(CDockWidget::DockWidgetForceCloseWithArea)) ||
DockWidget->features().testFlag(CDockWidget::CustomCloseHandling))
{
DockWidget->closeDockWidgetInternal();
}
else if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) && isAutoHide())
{
DockWidget->closeDockWidgetInternal();
}
else
{
DockWidget->toggleView(false);
}
}
}
}
enum eBorderLocation
{
BorderNone = 0,
BorderLeft = 0x01,
BorderRight = 0x02,
BorderTop = 0x04,
BorderBottom = 0x08,
BorderVertical = BorderLeft | BorderRight,
BorderHorizontal = BorderTop | BorderBottom,
BorderTopLeft = BorderTop | BorderLeft,
BorderTopRight = BorderTop | BorderRight,
BorderBottomLeft = BorderBottom | BorderLeft,
BorderBottomRight = BorderBottom | BorderRight,
BorderVerticalBottom = BorderVertical | BorderBottom,
BorderVerticalTop = BorderVertical | BorderTop,
BorderHorizontalLeft = BorderHorizontal | BorderLeft,
BorderHorizontalRight = BorderHorizontal | BorderRight,
BorderAll = BorderVertical | BorderHorizontal
};
//============================================================================
SideBarLocation CDockAreaWidget::calculateSideTabBarArea() const
{
auto Container = dockContainer();
auto ContentRect = Container->contentRect();
int borders = BorderNone; // contains all borders that are touched by the dock ware
auto DockAreaTopLeft = mapTo(Container, rect().topLeft());
auto DockAreaRect = rect();
DockAreaRect.moveTo(DockAreaTopLeft);
const qreal aspectRatio = DockAreaRect.width() / (qMax(1, DockAreaRect.height()) * 1.0);
const qreal sizeRatio = (qreal)ContentRect.width() / DockAreaRect.width();
static const int MinBorderDistance = 16;
bool HorizontalOrientation = (aspectRatio > 1.0) && (sizeRatio < 3.0);
// measure border distances - a distance less than 16 px means we touch the
// border
int BorderDistance[4];
int Distance = qAbs(ContentRect.topLeft().y() - DockAreaRect.topLeft().y());
BorderDistance[SideBarLocation::SideBarTop] = (Distance < MinBorderDistance) ? 0 : Distance;
if (!BorderDistance[SideBarLocation::SideBarTop])
{
borders |= BorderTop;
}
Distance = qAbs(ContentRect.bottomRight().y() - DockAreaRect.bottomRight().y());
BorderDistance[SideBarLocation::SideBarBottom] = (Distance < MinBorderDistance) ? 0 : Distance;
if (!BorderDistance[SideBarLocation::SideBarBottom])
{
borders |= BorderBottom;
}
Distance = qAbs(ContentRect.topLeft().x() - DockAreaRect.topLeft().x());
BorderDistance[SideBarLocation::SideBarLeft] = (Distance < MinBorderDistance) ? 0 : Distance;
if (!BorderDistance[SideBarLocation::SideBarLeft])
{
borders |= BorderLeft;
}
Distance = qAbs(ContentRect.bottomRight().x() - DockAreaRect.bottomRight().x());
BorderDistance[SideBarLocation::SideBarRight] = (Distance < MinBorderDistance) ? 0 : Distance;
if (!BorderDistance[SideBarLocation::SideBarRight])
{
borders |= BorderRight;
}
auto SideTab = SideBarLocation::SideBarRight;
switch (borders)
{
// 1. It's touching all borders
case BorderAll: SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarRight; break;
// 2. It's touching 3 borders
case BorderVerticalBottom : SideTab = SideBarLocation::SideBarBottom; break;
case BorderVerticalTop : SideTab = SideBarLocation::SideBarTop; break;
case BorderHorizontalLeft: SideTab = SideBarLocation::SideBarLeft; break;
case BorderHorizontalRight: SideTab = SideBarLocation::SideBarRight; break;
// 3. Its touching horizontal or vertical borders
case BorderVertical : SideTab = SideBarLocation::SideBarBottom; break;
case BorderHorizontal: SideTab = SideBarLocation::SideBarRight; break;
// 4. Its in a corner
case BorderTopLeft : SideTab = HorizontalOrientation ? SideBarLocation::SideBarTop : SideBarLocation::SideBarLeft; break;
case BorderTopRight : SideTab = HorizontalOrientation ? SideBarLocation::SideBarTop : SideBarLocation::SideBarRight; break;
case BorderBottomLeft : SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarLeft; break;
case BorderBottomRight : SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarRight; break;
// 5 Ists touching only one border
case BorderLeft: SideTab = SideBarLocation::SideBarLeft; break;
case BorderRight: SideTab = SideBarLocation::SideBarRight; break;
case BorderTop: SideTab = SideBarLocation::SideBarTop; break;
case BorderBottom: SideTab = SideBarLocation::SideBarBottom; break;
}
return SideTab;
}
//============================================================================
void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location)
{
if (!isAutoHideFeatureEnabled())
{
return;
}
if (!Enable)
{
if (isAutoHide())
{
autoHideDockContainer()->moveContentsToParent();
}
return;
}
auto area = (SideBarNone == Location) ? calculateSideTabBarArea() : Location;
for (const auto DockWidget : openedDockWidgets())
{
if (Enable == isAutoHide())
{
continue;
}
if (!DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable))
{
continue;
}
dockContainer()->createAndSetupAutoHideContainer(area, DockWidget);
}
}
//============================================================================
void CDockAreaWidget::toggleAutoHide(SideBarLocation Location)
{
if (!isAutoHideFeatureEnabled())
{
return;
}
setAutoHide(!isAutoHide(), Location);
}
//============================================================================
void CDockAreaWidget::closeOtherAreas()
{
@@ -997,7 +1379,23 @@ bool CDockAreaWidget::isCentralWidgetArea() const
return false;
}
return dockManager()->centralWidget() == dockWidgets()[0];
return dockManager()->centralWidget() == dockWidgets().constFirst();
}
//============================================================================
bool CDockAreaWidget::containsCentralWidget() const
{
auto centralWidget = dockManager()->centralWidget();
for (const auto &dockWidget : dockWidgets())
{
if (dockWidget == centralWidget)
{
return true;
}
}
return false;
}
@@ -1030,6 +1428,19 @@ void CDockAreaWidget::onDockWidgetFeaturesChanged()
}
//============================================================================
bool CDockAreaWidget::isTopLevelArea() const
{
auto Container = dockContainer();
if (!Container)
{
return false;
}
return (Container->topLevelDockArea() == this);
}
#ifdef Q_OS_WIN
//============================================================================
bool CDockAreaWidget::event(QEvent *e)

View File

@@ -33,6 +33,7 @@
#include <QFrame>
#include "ads_globals.h"
#include "AutoHideTab.h"
#include "DockWidget.h"
QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
@@ -45,6 +46,7 @@ class CDockManager;
class CDockContainerWidget;
class DockContainerWidgetPrivate;
class CDockAreaTitleBar;
class CDockingStateReader;
/**
@@ -65,6 +67,7 @@ private:
friend class CDockWidget;
friend struct DockManagerPrivate;
friend class CDockManager;
friend class CAutoHideDockContainer;
void onDockWidgetFeaturesChanged();
private Q_SLOTS:
@@ -76,6 +79,22 @@ private Q_SLOTS:
*/
void reorderDockWidget(int fromIndex, int toIndex);
/*
* Update the auto hide button checked state based on if it's contained in an auto hide container or not
*/
void updateAutoHideButtonCheckState();
/*
* Update the title bar button tooltips
*/
void updateTitleBarButtonsToolTips();
/**
* Calculate the auto hide side bar location depending on the dock area
* widget position in the container
*/
SideBarLocation calculateSideTabBarArea() const;
protected:
#ifdef Q_OS_WIN
@@ -149,6 +168,11 @@ protected:
*/
void markTitleBarMenuOutdated();
/*
* Update the title bar button visibility based on if it's top level or not
*/
void updateTitleBarButtonVisibility(bool IsTopLevel) const;
protected Q_SLOTS:
void toggleView(bool Open);
@@ -186,6 +210,23 @@ public:
*/
CDockContainerWidget* dockContainer() const;
/**
* Returns the auto hide dock container widget this dock area widget belongs to or 0
* if there is no
*/
CAutoHideDockContainer* autoHideDockContainer() const;
/**
* Returns true if the dock area is in an auto hide container
*/
bool isAutoHide() const;
/**
* Sets the current auto hide dock container
*/
void setAutoHideDockContainer(CAutoHideDockContainer* AutoHideDockContainer);
/**
* Returns the largest minimumSizeHint() of the dock widgets in this
* area.
@@ -262,6 +303,13 @@ public:
*/
void saveState(QXmlStreamWriter& Stream) const;
/**
* Restores a dock area.
* \see restoreChildNodes() for details
*/
static bool restoreState(CDockingStateReader& Stream, CDockAreaWidget*& CreatedWidget,
bool Testing, CDockContainerWidget* ParentContainer);
/**
* This functions returns the dock widget features of all dock widget in
* this area.
@@ -319,10 +367,22 @@ public:
void setDockAreaFlag(eDockAreaFlag Flag, bool On);
/**
* Returns true if the area contains the central widget of it's manager.
* Returns true if the area has a single dock widget and contains the central widget of it's manager.
*/
bool isCentralWidgetArea() const;
/**
* Returns true if the area contains the central widget of it's manager.
*/
bool containsCentralWidget() const;
/**
* If this dock area is the one and only visible area in a container, then
* this function returns true
*/
bool isTopLevelArea() const;
public Q_SLOTS:
/**
* This activates the tab for the given tab index.
@@ -337,6 +397,19 @@ public Q_SLOTS:
void closeArea();
/**
* Sets the dock area into auto hide mode or into normal mode.
* If the dock area is switched to auto hide mode, then all dock widgets
* that are pinable will be added to the sidebar
*/
void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone);
/**
* Switches the dock area to auto hide mode or vice versa depending on its
* current state.
*/
void toggleAutoHide(SideBarLocation Location = SideBarNone);
/**
* This function closes all other areas except of this area
*/
void closeOtherAreas();
@@ -367,7 +440,8 @@ Q_SIGNALS:
*/
void viewToggled(bool Open);
}; // class DockAreaWidget
}
// namespace ads
} // namespace ads
Q_DECLARE_OPERATORS_FOR_FLAGS(ads::CDockAreaWidget::DockAreaFlags)
//-----------------------------------------------------------------------------
#endif // DockAreaWidgetH

View File

@@ -8,6 +8,7 @@
//============================================================================
// INCLUDES
//============================================================================
#include <AutoHideTab.h>
#include "DockComponentsFactory.h"
#include <memory>
@@ -29,6 +30,12 @@ CDockWidgetTab* CDockComponentsFactory::createDockWidgetTab(CDockWidget* DockWid
return new CDockWidgetTab(DockWidget);
}
//============================================================================
CAutoHideTab* CDockComponentsFactory::createDockWidgetSideTab(CDockWidget *DockWidget) const
{
return new CAutoHideTab(DockWidget);
}
//============================================================================
CDockAreaTabBar* CDockComponentsFactory::createDockAreaTabBar(CDockAreaWidget* DockArea) const

View File

@@ -19,6 +19,7 @@ class CDockAreaTitleBar;
class CDockAreaTabBar;
class CDockAreaWidget;
class CDockWidget;
class CAutoHideTab;
@@ -46,6 +47,12 @@ public:
*/
virtual CDockWidgetTab* createDockWidgetTab(CDockWidget* DockWidget) const;
/**
* This default implementation just creates a dock widget side tab with
* new CDockWidgetTab(DockWidget).
*/
virtual CAutoHideTab* createDockWidgetSideTab(CDockWidget* DockWidget) const;
/**
* This default implementation just creates a dock area tab bar with
* new CDockAreaTabBar(DockArea).

View File

@@ -38,6 +38,11 @@
#include <QDebug>
#include <QXmlStreamWriter>
#include <QAbstractButton>
#include <QLabel>
#include <QTimer>
#include <QMetaObject>
#include <QMetaType>
#include <QApplication>
#include "DockManager.h"
#include "DockAreaWidget.h"
@@ -47,6 +52,12 @@
#include "DockOverlay.h"
#include "ads_globals.h"
#include "DockSplitter.h"
#include "DockWidgetTab.h"
#include "DockAreaTitleBar.h"
#include "DockFocusController.h"
#include "AutoHideDockContainer.h"
#include "AutoHideSideBar.h"
#include "AutoHideTab.h"
#include <functional>
#include <iostream>
@@ -131,12 +142,17 @@ public:
QPointer<CDockManager> DockManager;
unsigned int zOrderIndex = 0;
QList<CDockAreaWidget*> DockAreas;
QList<CAutoHideDockContainer*> AutoHideWidgets;
QMap<SideBarLocation, CAutoHideSideBar*> SideTabBarWidgets;
QGridLayout* Layout = nullptr;
QSplitter* RootSplitter = nullptr;
bool isFloating = false;
CDockAreaWidget* LastAddedAreaCache[5];
int VisibleDockAreaCount = -1;
CDockAreaWidget* TopLevelDockArea = nullptr;
QTimer DelayedAutoHideTimer;
CAutoHideTab* DelayedAutoHideTab;
bool DelayedAutoHideShow = false;
/**
* Private data constructor
@@ -153,7 +169,7 @@ public:
* Adds dock widget to a existing DockWidgetArea
*/
CDockAreaWidget* addDockWidgetToDockArea(DockWidgetArea area, CDockWidget* Dockwidget,
CDockAreaWidget* TargetDockArea);
CDockAreaWidget* TargetDockArea, int Index = -1);
/**
* Add dock area to this container
@@ -212,6 +228,11 @@ public:
void saveChildNodesState(QXmlStreamWriter& Stream, QWidget* Widget);
/**
* Save state of auto hide widgets
*/
void saveAutoHideWidgetsState(QXmlStreamWriter& Stream);
/**
* Restore state of child nodes.
* \param[in] Stream The data stream that contains the serialized state
* \param[out] CreatedWidget The widget created from parsed data or 0 if
@@ -236,6 +257,12 @@ public:
bool restoreDockArea(CDockingStateReader& Stream, QWidget*& CreatedWidget,
bool Testing);
/**
* Restores a auto hide side bar
*/
bool restoreSideBar(CDockingStateReader& Stream, QWidget*& CreatedWidget,
bool Testing);
/**
* Helper function for recursive dumping of layout
*/
@@ -351,6 +378,13 @@ DockContainerWidgetPrivate::DockContainerWidgetPrivate(CDockContainerWidget* _pu
_this(_public)
{
std::fill(std::begin(LastAddedAreaCache),std::end(LastAddedAreaCache), nullptr);
DelayedAutoHideTimer.setSingleShot(true);
DelayedAutoHideTimer.setInterval(500);
QObject::connect(&DelayedAutoHideTimer, &QTimer::timeout, [this](){
auto GlobalPos = DelayedAutoHideTab->mapToGlobal(QPoint(0, 0));
qApp->sendEvent(DelayedAutoHideTab, new QMouseEvent(QEvent::MouseButtonPress,
QPoint(0, 0), GlobalPos, Qt::LeftButton, {Qt::LeftButton}, Qt::NoModifier));
});
}
@@ -402,13 +436,11 @@ void DockContainerWidgetPrivate::onVisibleDockAreaCountChanged()
if (TopLevelDockArea)
{
this->TopLevelDockArea = TopLevelDockArea;
TopLevelDockArea->titleBarButton(TitleBarButtonUndock)->setVisible(false || !_this->isFloating());
TopLevelDockArea->titleBarButton(TitleBarButtonClose)->setVisible(false || !_this->isFloating());
TopLevelDockArea->updateTitleBarButtonVisibility(true);
}
else if (this->TopLevelDockArea)
{
this->TopLevelDockArea->titleBarButton(TitleBarButtonUndock)->setVisible(true);
this->TopLevelDockArea->titleBarButton(TitleBarButtonClose)->setVisible(true);
this->TopLevelDockArea->updateTitleBarButtonVisibility(false);
this->TopLevelDockArea = nullptr;
}
}
@@ -520,8 +552,9 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
return;
}
CDockContainerWidget* FloatingContainer = FloatingWidget->dockContainer();
auto InsertParam = internal::dockAreaInsertParameters(area);
auto NewDockAreas = FloatingWidget->dockContainer()->findChildren<CDockAreaWidget*>(
auto NewDockAreas = FloatingContainer->findChildren<CDockAreaWidget*>(
QString(), Qt::FindChildrenRecursively);
QSplitter* TargetAreaSplitter = internal::findParent<QSplitter*>(TargetArea);
@@ -534,9 +567,7 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
TargetAreaSplitter = Splitter;
}
int AreaIndex = TargetAreaSplitter->indexOf(TargetArea);
auto Widget = FloatingWidget->dockContainer()->findChild<QWidget*>(QString(), Qt::FindDirectChildrenOnly);
auto FloatingSplitter = qobject_cast<QSplitter*>(Widget);
auto FloatingSplitter = FloatingContainer->rootSplitter();
if (TargetAreaSplitter->orientation() == InsertParam.orientation())
{
auto Sizes = TargetAreaSplitter->sizes();
@@ -544,7 +575,7 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
bool AdjustSplitterSizes = true;
if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1)
{
TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), Widget);
TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), FloatingSplitter);
updateSplitterHandles(TargetAreaSplitter);
}
else
@@ -568,13 +599,12 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
}
else
{
QList<int> NewSplitterSizes;
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
bool AdjustSplitterSizes = true;
if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1)
{
NewSplitter->addWidget(Widget);
NewSplitter->addWidget(FloatingSplitter);
updateSplitterHandles(NewSplitter);
}
else
@@ -692,7 +722,6 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg
}
else
{
auto Sizes = TargetAreaSplitter->sizes();
int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
NewSplitter->addWidget(TargetArea);
@@ -805,8 +834,8 @@ void DockContainerWidgetPrivate::addDockAreasToList(const QList<CDockAreaWidget*
// likely hidden. We need to ensure, that it is visible
for (auto DockArea : NewDockAreas)
{
DockArea->titleBarButton(TitleBarButtonUndock)->setVisible(true);
DockArea->titleBarButton(TitleBarButtonClose)->setVisible(true);
DockArea->titleBarButton(TitleBarButtonAutoHide)->setVisible(true);
}
// We need to ensure, that the dock area title bar is visible. The title bar
@@ -874,6 +903,21 @@ void DockContainerWidgetPrivate::saveChildNodesState(QXmlStreamWriter& s, QWidge
}
//============================================================================
void DockContainerWidgetPrivate::saveAutoHideWidgetsState(QXmlStreamWriter& s)
{
for (const auto sideTabBar : SideTabBarWidgets.values())
{
if (!sideTabBar->tabCount())
{
continue;
}
sideTabBar->saveState(s);
}
}
//============================================================================
bool DockContainerWidgetPrivate::restoreSplitter(CDockingStateReader& s,
QWidget*& CreatedWidget, bool Testing)
@@ -994,90 +1038,88 @@ bool DockContainerWidgetPrivate::restoreSplitter(CDockingStateReader& s,
bool DockContainerWidgetPrivate::restoreDockArea(CDockingStateReader& s,
QWidget*& CreatedWidget, bool Testing)
{
CDockAreaWidget* DockArea = nullptr;
auto Result = CDockAreaWidget::restoreState(s, DockArea, Testing, _this);
if (Result && DockArea)
{
appendDockAreas({DockArea});
}
CreatedWidget = DockArea;
return Result;
}
//============================================================================
bool DockContainerWidgetPrivate::restoreSideBar(CDockingStateReader& s,
QWidget*& CreatedWidget, bool Testing)
{
Q_UNUSED(CreatedWidget)
// Simply ignore side bar auto hide widgets from saved state if
// auto hide support is disabled
if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
{
return true;
}
bool Ok;
#ifdef ADS_DEBUG_PRINT
int Tabs = s.attributes().value("Tabs").toInt(&Ok);
auto Area = (ads::SideBarLocation)s.attributes().value("Area").toInt(&Ok);
if (!Ok)
{
return false;
}
#endif
QString CurrentDockWidget = s.attributes().value("Current").toString();
ADS_PRINT("Restore NodeDockArea Tabs: " << Tabs << " Current: "
<< CurrentDockWidget);
CDockAreaWidget* DockArea = nullptr;
if (!Testing)
{
DockArea = new CDockAreaWidget(DockManager, _this);
const auto AllowedAreasAttribute = s.attributes().value("AllowedAreas");
if (!AllowedAreasAttribute.isEmpty())
{
DockArea->setAllowedAreas((DockWidgetArea)AllowedAreasAttribute.toInt(nullptr, 16));
}
const auto FlagsAttribute = s.attributes().value("Flags");
if (!FlagsAttribute.isEmpty())
{
DockArea->setDockAreaFlags((CDockAreaWidget::DockAreaFlags)FlagsAttribute.toInt(nullptr, 16));
}
}
while (s.readNextStartElement())
{
if (s.name() != QLatin1String("Widget"))
if (s.name() != QLatin1String("Widget"))
{
continue;
}
auto ObjectName = s.attributes().value("Name");
if (ObjectName.isEmpty())
auto Name = s.attributes().value("Name");
if (Name.isEmpty())
{
return false;
}
bool Ok;
bool Closed = s.attributes().value("Closed").toInt(&Ok);
if (!Ok)
{
return false;
}
int Size = s.attributes().value("Size").toInt(&Ok);
if (!Ok)
{
return false;
}
s.skipCurrentElement();
CDockWidget* DockWidget = DockManager->findDockWidget(ObjectName.toString());
CDockWidget* DockWidget = DockManager->findDockWidget(Name.toString());
if (!DockWidget || Testing)
{
continue;
}
ADS_PRINT("Dock Widget found - parent " << DockWidget->parent());
// We hide the DockArea here to prevent the short display (the flashing)
// of the dock areas during application startup
DockArea->hide();
DockArea->addDockWidget(DockWidget);
DockWidget->setToggleViewActionChecked(!Closed);
DockWidget->setClosedState(Closed);
DockWidget->setProperty(internal::ClosedProperty, Closed);
auto SideBar = _this->sideTabBar(Area);
CAutoHideDockContainer* AutoHideContainer;
if (DockWidget->isAutoHide())
{
AutoHideContainer = DockWidget->autoHideDockContainer();
if (AutoHideContainer->sideBar() != SideBar)
{
SideBar->addAutoHideWidget(AutoHideContainer);
}
}
else
{
AutoHideContainer = SideBar->insertDockWidget(-1, DockWidget);
}
AutoHideContainer->setSize(Size);
DockWidget->setProperty(internal::ClosedProperty, Closed);
DockWidget->setProperty(internal::DirtyProperty, false);
}
if (Testing)
{
return true;
}
if (!DockArea->dockWidgetsCount())
{
delete DockArea;
DockArea = nullptr;
}
else
{
DockArea->setProperty("currentDockWidget", CurrentDockWidget);
appendDockAreas({DockArea});
}
CreatedWidget = DockArea;
return true;
}
@@ -1099,6 +1141,11 @@ bool DockContainerWidgetPrivate::restoreChildNodes(CDockingStateReader& s,
Result = restoreDockArea(s, CreatedWidget, Testing);
ADS_PRINT("DockAreaWidget");
}
else if (s.name() == QLatin1String("SideBar"))
{
Result = restoreSideBar(s, CreatedWidget, Testing);
ADS_PRINT("SideBar");
}
else
{
s.skipCurrentElement();
@@ -1228,11 +1275,11 @@ void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget)
//============================================================================
CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetArea area,
CDockWidget* Dockwidget, CDockAreaWidget* TargetDockArea)
CDockWidget* Dockwidget, CDockAreaWidget* TargetDockArea, int Index)
{
if (CenterDockWidgetArea == area)
{
TargetDockArea->addDockWidget(Dockwidget);
TargetDockArea->insertDockWidget(Index, Dockwidget);
TargetDockArea->updateTitleBarVisibility();
return TargetDockArea;
}
@@ -1286,8 +1333,10 @@ CDockContainerWidget::CDockContainerWidget(CDockManager* DockManager, QWidget *p
d->isFloating = floatingWidget() != nullptr;
d->Layout = new QGridLayout();
d->Layout->setContentsMargins(0, 1, 0, 1);
d->Layout->setContentsMargins(0, 0, 0, 0);
d->Layout->setSpacing(0);
d->Layout->setColumnStretch(1, 1);
d->Layout->setRowStretch(1, 1);
setLayout(d->Layout);
// The function d->newSplitter() accesses the config flags from dock
@@ -1299,9 +1348,11 @@ CDockContainerWidget::CDockContainerWidget(CDockManager* DockManager, QWidget *p
{
d->DockManager->registerDockContainer(this);
createRootSplitter();
createSideTabBarWidgets();
}
}
//============================================================================
CDockContainerWidget::~CDockContainerWidget()
{
@@ -1309,14 +1360,16 @@ CDockContainerWidget::~CDockContainerWidget()
{
d->DockManager->removeDockContainer(this);
}
delete d;
}
//============================================================================
CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
CDockAreaWidget* DockAreaWidget)
CDockAreaWidget* DockAreaWidget, int Index)
{
auto TopLevelDockWidget = topLevelDockWidget();
CDockAreaWidget* OldDockArea = Dockwidget->dockAreaWidget();
if (OldDockArea)
{
@@ -1324,16 +1377,50 @@ CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockW
}
Dockwidget->setDockManager(d->DockManager);
CDockAreaWidget* DockArea;
if (DockAreaWidget)
{
return d->addDockWidgetToDockArea(area, Dockwidget, DockAreaWidget);
DockArea = d->addDockWidgetToDockArea(area, Dockwidget, DockAreaWidget, Index);
}
else
{
return d->addDockWidgetToContainer(area, Dockwidget);
DockArea = d->addDockWidgetToContainer(area, Dockwidget);
}
if (TopLevelDockWidget)
{
auto NewTopLevelDockWidget = topLevelDockWidget();
// If the container contained only one visible dock widget, the we need
// to emit a top level event for this widget because it is not the one and
// only visible docked widget anymore
if (!NewTopLevelDockWidget)
{
CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidget, false);
}
}
return DockArea;
}
//============================================================================
CAutoHideDockContainer* CDockContainerWidget::createAndSetupAutoHideContainer(
SideBarLocation area, CDockWidget* DockWidget)
{
if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
{
Q_ASSERT_X(false, "CDockContainerWidget::createAndInitializeDockWidgetOverlayContainer",
"Requested area does not exist in config");
return nullptr;
}
if (d->DockManager != DockWidget->dockManager())
{
DockWidget->setDockManager(d->DockManager); // Auto hide Dock Container needs a valid dock manager
}
return sideTabBar(area)->insertDockWidget(-1, DockWidget);
}
//============================================================================
void CDockContainerWidget::removeDockWidget(CDockWidget* Dockwidget)
{
@@ -1375,6 +1462,13 @@ bool CDockContainerWidget::event(QEvent *e)
}
//============================================================================
QList<CAutoHideDockContainer*> CDockContainerWidget::autoHideWidgets() const
{
return d->AutoHideWidgets;
}
//============================================================================
void CDockContainerWidget::addDockArea(CDockAreaWidget* DockAreaWidget,
DockWidgetArea area)
@@ -1393,6 +1487,13 @@ void CDockContainerWidget::addDockArea(CDockAreaWidget* DockAreaWidget,
void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
{
ADS_PRINT("CDockContainerWidget::removeDockArea");
// If it is an auto hide area, then there is nothing much to do
if (area->isAutoHide())
{
area->setAutoHideDockContainer(nullptr);
return;
}
area->disconnect(this);
d->DockAreas.removeAll(area);
CDockSplitter* Splitter = internal::findParent<CDockSplitter*>(area);
@@ -1564,6 +1665,14 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
}
}
// Remove the auto hide widgets from the FloatingWidget and insert
// them into this widget
for (auto AutohideWidget : FloatingWidget->dockContainer()->autoHideWidgets())
{
auto SideBar = sideTabBar(AutohideWidget->sideBarLocation());
SideBar->addAutoHideWidget(AutohideWidget);
}
if (Dropped)
{
// Fix https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/351
@@ -1625,6 +1734,37 @@ QList<CDockAreaWidget*> CDockContainerWidget::openedDockAreas() const
}
//============================================================================
QList<CDockWidget*> CDockContainerWidget::openedDockWidgets() const
{
QList<CDockWidget*> DockWidgetList;
for (auto DockArea : d->DockAreas)
{
if (!DockArea->isHidden())
{
DockWidgetList.append(DockArea->openedDockWidgets());
}
}
return DockWidgetList;
}
//============================================================================
bool CDockContainerWidget::hasOpenDockAreas() const
{
for (auto DockArea : d->DockAreas)
{
if (!DockArea->isHidden())
{
return true;
}
}
return false;
}
//============================================================================
void CDockContainerWidget::saveState(QXmlStreamWriter& s) const
{
@@ -1644,6 +1784,7 @@ void CDockContainerWidget::saveState(QXmlStreamWriter& s) const
#endif
}
d->saveChildNodesState(s, d->RootSplitter);
d->saveAutoHideWidgetsState(s);
s.writeEndElement();
}
@@ -1654,7 +1795,7 @@ bool CDockContainerWidget::restoreState(CDockingStateReader& s, bool Testing)
bool IsFloating = s.attributes().value("Floating").toInt();
ADS_PRINT("Restore CDockContainerWidget Floating" << IsFloating);
QWidget*NewRootSplitter {};
QWidget* NewRootSplitter {};
if (!Testing)
{
d->VisibleDockAreaCount = -1;// invalidate the dock area count
@@ -1680,7 +1821,10 @@ bool CDockContainerWidget::restoreState(CDockingStateReader& s, bool Testing)
if (!Testing)
{
CFloatingDockContainer* FloatingWidget = floatingWidget();
FloatingWidget->restoreGeometry(Geometry);
if (FloatingWidget)
{
FloatingWidget->restoreGeometry(Geometry);
}
}
}
@@ -1725,7 +1869,41 @@ void CDockContainerWidget::createRootSplitter()
return;
}
d->RootSplitter = d->newSplitter(Qt::Horizontal);
d->Layout->addWidget(d->RootSplitter);
d->Layout->addWidget(d->RootSplitter, 1, 1); // Add it to the center - the 0 and 2 indexes are used for the SideTabBar widgets
}
//============================================================================
void CDockContainerWidget::createSideTabBarWidgets()
{
if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
{
return;
}
{
auto Area = SideBarLocation::SideBarLeft;
d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area);
d->Layout->addWidget(d->SideTabBarWidgets[Area], 1, 0);
}
{
auto Area = SideBarLocation::SideBarRight;
d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area);
d->Layout->addWidget(d->SideTabBarWidgets[Area], 1, 2);
}
{
auto Area = SideBarLocation::SideBarBottom;
d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area);
d->Layout->addWidget(d->SideTabBarWidgets[Area], 2, 1);
}
{
auto Area = SideBarLocation::SideBarTop;
d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area);
d->Layout->addWidget(d->SideTabBarWidgets[Area], 0, 1);
}
}
@@ -1807,13 +1985,25 @@ QList<CDockWidget*> CDockContainerWidget::dockWidgets() const
return Result;
}
//============================================================================
void CDockContainerWidget::updateSplitterHandles(QSplitter* splitter)
{
d->updateSplitterHandles(splitter);
}
//============================================================================
void CDockContainerWidget::registerAutoHideWidget(CAutoHideDockContainer* AutohideWidget)
{
d->AutoHideWidgets.append(AutohideWidget);
Q_EMIT autoHideWidgetCreated(AutohideWidget);
ADS_PRINT("d->AutoHideWidgets.count() " << d->AutoHideWidgets.count());
}
//============================================================================
void CDockContainerWidget::removeAutoHideWidget(CAutoHideDockContainer* AutohideWidget)
{
d->AutoHideWidgets.removeAll(AutohideWidget);
}
//============================================================================
CDockWidget::DockWidgetFeatures CDockContainerWidget::features() const
@@ -1860,7 +2050,123 @@ void CDockContainerWidget::closeOtherAreas(CDockAreaWidget* KeepOpenArea)
}
}
//============================================================================
CAutoHideSideBar* CDockContainerWidget::sideTabBar(SideBarLocation area) const
{
return d->SideTabBarWidgets[area];
}
//============================================================================
QRect CDockContainerWidget::contentRect() const
{
if (!d->RootSplitter)
{
return QRect();
}
return d->RootSplitter->geometry();
}
//===========================================================================
QRect CDockContainerWidget::contentRectGlobal() const
{
if (!d->RootSplitter)
{
return QRect();
}
return internal::globalGeometry(d->RootSplitter);
}
//===========================================================================
CDockManager* CDockContainerWidget::dockManager() const
{
return d->DockManager;
}
//===========================================================================
void CDockContainerWidget::handleAutoHideWidgetEvent(QEvent* e, QWidget* w)
{
if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideShowOnMouseOver))
{
return;
}
if (dockManager()->isRestoringState())
{
return;
}
auto AutoHideTab = qobject_cast<CAutoHideTab*>(w);
if (AutoHideTab)
{
switch (e->type())
{
case QEvent::Enter:
if (!AutoHideTab->dockWidget()->isVisible())
{
d->DelayedAutoHideTab = AutoHideTab;
d->DelayedAutoHideShow = true;
d->DelayedAutoHideTimer.start();
}
else
{
d->DelayedAutoHideTimer.stop();
}
break;
case QEvent::MouseButtonPress:
d->DelayedAutoHideTimer.stop();
break;
case QEvent::Leave:
if (AutoHideTab->dockWidget()->isVisible())
{
d->DelayedAutoHideTab = AutoHideTab;
d->DelayedAutoHideShow = false;
d->DelayedAutoHideTimer.start();
}
else
{
d->DelayedAutoHideTimer.stop();
}
break;
default:
break;
}
return;
}
auto AutoHideContainer = qobject_cast<CAutoHideDockContainer*>(w);
if (AutoHideContainer)
{
switch (e->type())
{
case QEvent::Enter:
case QEvent::Hide:
d->DelayedAutoHideTimer.stop();
break;
case QEvent::Leave:
if (AutoHideContainer->isVisible())
{
d->DelayedAutoHideTab = AutoHideContainer->autoHideTab();
d->DelayedAutoHideShow = false;
d->DelayedAutoHideTimer.start();
}
break;
default:
break;
}
return;
return;
}
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@@ -33,6 +33,7 @@
#include <QFrame>
#include "ads_globals.h"
#include "AutoHideTab.h"
#include "DockWidget.h"
QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
@@ -50,6 +51,11 @@ struct FloatingDockContainerPrivate;
class CFloatingDragPreview;
struct FloatingDragPreviewPrivate;
class CDockingStateReader;
class CAutoHideSideBar;
class CAutoHideTab;
struct AutoHideTabPrivate;
struct AutoHideDockContainerPrivate;
/**
* Container that manages a number of dock areas with single dock widgets
@@ -73,6 +79,11 @@ private:
friend class CDockWidget;
friend class CFloatingDragPreview;
friend struct FloatingDragPreviewPrivate;
friend CAutoHideDockContainer;
friend CAutoHideTab;
friend AutoHideTabPrivate;
friend AutoHideDockContainerPrivate;
friend CAutoHideSideBar;
protected:
/**
@@ -85,11 +96,23 @@ protected:
*/
QSplitter* rootSplitter() const;
/**
* Creates and initializes a dockwidget auto hide container into the given area.
* Initializing inserts the tabs into the side tab widget and hides it
* Returns nullptr if you try and insert into an area where the configuration is not enabled
*/
CAutoHideDockContainer* createAndSetupAutoHideContainer(SideBarLocation area, CDockWidget* DockWidget);
/**
* Helper function for creation of the root splitter
*/
void createRootSplitter();
/**
* Helper function for creation of the side tab bar widgets
*/
void createSideTabBarWidgets();
/**
* Drop floating widget into the container
*/
@@ -141,7 +164,8 @@ protected:
CDockWidget* topLevelDockWidget() const;
/**
* Returns the top level dock area.
* If the container has only one single visible dock area, then this
* functions returns this top level dock area
*/
CDockAreaWidget* topLevelDockArea() const;
@@ -161,6 +185,24 @@ protected:
*/
void updateSplitterHandles(QSplitter* splitter);
/**
* Registers the given floating widget in the internal list of
* auto hide widgets
*/
void registerAutoHideWidget(CAutoHideDockContainer* AutoHideWidget);
/**
* Remove the given auto hide widget from the list of registered auto hide
* widgets
*/
void removeAutoHideWidget(CAutoHideDockContainer* AutoHideWidget);
/**
* Handles widget events of auto hide widgets to trigger delayed show
* or hide actions for auto hide container on auto hide tab mouse over
*/
void handleAutoHideWidgetEvent(QEvent* e, QWidget* w);
public:
/**
* Default Constructor
@@ -180,7 +222,7 @@ public:
* \return Returns the dock area widget that contains the new DockWidget
*/
CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
CDockAreaWidget* DockAreaWidget = nullptr);
CDockAreaWidget* DockAreaWidget = nullptr, int Index = -1);
/**
* Removes dockwidget
@@ -216,6 +258,18 @@ public:
*/
QList<CDockAreaWidget*> openedDockAreas() const;
/**
* Returns a list for all open dock widgets in all open dock areas
*/
QList<CDockWidget*> openedDockWidgets() const;
/**
* This function returns true, if the container has open dock areas.
* This functions is a little bit faster than calling openedDockAreas().isEmpty()
* because it returns as soon as it finds an open dock area
*/
bool hasOpenDockAreas() const;
/**
* This function returns true if this dock area has only one single
* visible dock widget.
@@ -265,6 +319,36 @@ public:
*/
void closeOtherAreas(CDockAreaWidget* KeepOpenArea);
/**
* Returns the side tab widget for the given area
*/
CAutoHideSideBar* sideTabBar(SideBarLocation area) const;
/**
* Access function for auto hide widgets
*/
QList<CAutoHideDockContainer*> autoHideWidgets() const;
/**
* Returns the content rectangle without the autohide side bars
*/
QRect contentRect() const;
/**
* Returns the content rectangle mapped to global space.
* The content rectangle is the rectangle of the dock manager widget minus
* the auto hide side bars. So that means, it is the geometry of the
* internal root splitter mapped to global space.
*/
QRect contentRectGlobal() const;
/**
* Returns the dock manager that owns this container
*/
CDockManager* dockManager() const;
Q_SIGNALS:
/**
* This signal is emitted if one or multiple dock areas has been added to
@@ -273,6 +357,11 @@ Q_SIGNALS:
*/
void dockAreasAdded();
/**
* This signal is emitted, if a new auto hide widget has been created.
*/
void autoHideWidgetCreated(ads::CAutoHideDockContainer* AutoHideWidget);
/**
* This signal is emitted if one or multiple dock areas has been removed
*/

View File

@@ -8,6 +8,7 @@
//============================================================================
// INCLUDES
//============================================================================
#include <AutoHideTab.h>
#include "DockFocusController.h"
#include <algorithm>
@@ -32,6 +33,8 @@
namespace ads
{
static const char* const FocusedDockWidgetProperty = "FocusedDockWidget";
/**
* Private data class of CDockFocusController class (pimpl)
*/
@@ -40,7 +43,7 @@ struct DockFocusControllerPrivate
CDockFocusController *_this;
QPointer<CDockWidget> FocusedDockWidget = nullptr;
QPointer<CDockAreaWidget> FocusedArea = nullptr;
CDockWidget* OldFocusedDockWidget = nullptr;
QPointer<CDockWidget> OldFocusedDockWidget = nullptr;
#ifdef Q_OS_LINUX
QPointer<CFloatingDockContainer> FloatingWidget = nullptr;
#endif
@@ -57,8 +60,8 @@ struct DockFocusControllerPrivate
* the dock area that it belongs to
*/
void updateDockWidgetFocus(CDockWidget* DockWidget);
};
// struct DockFocusControllerPrivate
}; // struct DockFocusControllerPrivate
//===========================================================================
@@ -125,7 +128,7 @@ void DockFocusControllerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget)
if (Window)
{
Window->setProperty("FocusedDockWidget", QVariant::fromValue<CDockWidget*>(DockWidget));
Window->setProperty(FocusedDockWidgetProperty, QVariant::fromValue(QPointer<CDockWidget>(DockWidget)));
}
CDockAreaWidget* NewFocusedDockArea = nullptr;
if (FocusedDockWidget)
@@ -161,7 +164,7 @@ void DockFocusControllerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget)
if (NewFloatingWidget)
{
NewFloatingWidget->setProperty("FocusedDockWidget", QVariant::fromValue(DockWidget));
NewFloatingWidget->setProperty(FocusedDockWidgetProperty, QVariant::fromValue(QPointer<CDockWidget>(DockWidget)));
}
@@ -183,7 +186,7 @@ void DockFocusControllerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget)
}
#endif
if (old == DockWidget && !ForceFocusChangedSignal)
if (old == DockWidget && !ForceFocusChangedSignal)
{
return;
}
@@ -243,13 +246,13 @@ void CDockFocusController::onFocusWindowChanged(QWindow *focusWindow)
return;
}
auto vDockWidget = focusWindow->property("FocusedDockWidget");
auto vDockWidget = focusWindow->property(FocusedDockWidgetProperty);
if (!vDockWidget.isValid())
{
return;
}
auto DockWidget = vDockWidget.value<CDockWidget*>();
auto DockWidget = vDockWidget.value<QPointer<CDockWidget>>();
if (!DockWidget)
{
return;
@@ -262,7 +265,7 @@ void CDockFocusController::onFocusWindowChanged(QWindow *focusWindow)
//===========================================================================
void CDockFocusController::onApplicationFocusChanged(QWidget* focusedOld, QWidget* focusedNow)
{
Q_UNUSED(focusedOld);
Q_UNUSED(focusedOld);
if (d->DockManager->isRestoringState())
{
@@ -309,6 +312,14 @@ void CDockFocusController::setDockWidgetTabFocused(CDockWidgetTab* Tab)
}
//===========================================================================
void CDockFocusController::clearDockWidgetFocus(CDockWidget* dockWidget)
{
dockWidget->clearFocus();
updateDockWidgetFocusStyle(dockWidget, false);
}
//===========================================================================
void CDockFocusController::setDockWidgetFocused(CDockWidget* focusedNow)
{
@@ -376,13 +387,13 @@ void CDockFocusController::notifyFloatingWidgetDrop(CFloatingDockContainer* Floa
return;
}
auto vDockWidget = FloatingWidget->property("FocusedDockWidget");
auto vDockWidget = FloatingWidget->property(FocusedDockWidgetProperty);
if (!vDockWidget.isValid())
{
return;
}
auto DockWidget = vDockWidget.value<CDockWidget*>();
auto DockWidget = vDockWidget.value<QPointer<CDockWidget>>();
if (DockWidget)
{
DockWidget->dockAreaWidget()->setCurrentDockWidget(DockWidget);

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