Compare commits

...

108 Commits

Author SHA1 Message Date
Uwe Kindler
224676836d Improved CDockAreaTabBar::wheelEvent to use pixelDelta() if available (i.e. on Mac) and fall back to angleDelta() if not 2024-12-05 13:11:48 +01:00
Federico Fuga
f2378636e2 Add ability to customize the DockArea Title Bar and DockWidget Tab context menu 2024-11-20 15:38:39 +01:00
Federico Fuga
509b2356d1 Fix missing declarations 2024-11-20 15:38:21 +01:00
Uwe Kindler
30b802bd10 Fixed Qt5 build issues 2024-11-20 15:31:31 +01:00
Uwe Kindler
e857421fdf Added all build* subfolders to .gitignore 2024-10-28 15:41:46 +01:00
Uwe Kindler
8dcdc8fad2 Improved autohidedragndrop example to check, if it also works when dragging with multiple auto hide tabs 2024-10-28 15:40:32 +01:00
Uwe Kindler
f964ce2c68 Refactored, fixed and improved drag hover functionality 2024-10-28 15:39:29 +01:00
Uwe Kindler
eb9b439d11 Added support for setting config parameters to CDockManager 2024-10-28 15:30:29 +01:00
TheBoje
a13ed7e4d6 Add AutoHideDragNDrop example 2024-10-22 22:36:53 +02:00
TheBoje
8cfa5c8e0e Fix formatting#2 (#663) 2024-10-04 22:27:15 +02:00
TheBoje
2878559ee6 Fix formatting (#663) 2024-10-04 22:23:40 +02:00
TheBoje
6ff39bccf8 Add open auto-hide dock on hover from drag and drop (#663) 2024-10-04 22:17:42 +02:00
gavininfinity
952131a1e9 Make startDragging public (#658) 2024-08-19 07:37:51 +02:00
Uwe Kindler
5edbcc1970 Fixed issue #654 - Wheel event on DockAreaTabBar 2024-07-25 08:42:30 +02:00
Uwe Kindler
04f6d9168e Fixed #642 - The floating window can not back to normal size after maximizing it 2024-07-08 14:32:33 +02:00
Uwe Kindler
cea1327dac Fixed #653 - DisablingTabTextEliding not letting DockAreaDynamicTabsMenuButtonVisibility to function and program crashes 2024-07-08 12:15:00 +02:00
Uwe Kindler
1c41cbff82 Fixed issue #641 - Unexpected behaviour with tab drag on scrollable tab bar 2024-07-08 10:43:02 +02:00
invisibleGG
06e8451fc0 Update DockAreaTabBar.cpp (#640)
This fix seems to have introduced a regression when _this is deleted before the lambda slot occurred, for example deleting the DockManager (and consequently _this) immediately after the execution of updateTabs function (we encountered this problem in linux)
2024-06-03 08:29:59 +02:00
Uwe Kindler
3ff6918b1f Added configflags example to test use of CDockManager config flags 2024-05-21 08:37:35 +02:00
Uwe Kindler
ac3af4c6cd Merge branch 'master' of https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System 2024-05-08 14:44:44 +02:00
Uwe Kindler
41bb861417 Fixed problem in AutoHideSideBar that prevented the dock container, that contained a vertical sidebar with many tabs, from shrinking vertically 2024-05-08 14:43:53 +02:00
Stefan Gerlach
6e63418798 Fix "extra ;" warning (#624) 2024-04-08 11:40:06 +02:00
Nicolas Elie
65781b7cac Include GNUInstallDirs for CMAKE_INSTALL_* vars to be defined (#621) 2024-04-03 23:49:37 +02:00
Nicolas Elie
d7e6c613c6 Update PyQt bindings to 4.3.0 (#622) 2024-04-03 23:49:08 +02:00
UnlimitedStack
8da0713bf0 Ensure that TabWidget was not deleted by using it as context object (#612)
Co-authored-by: Marcus Venturi <marcus.venturi@visu-it.de>
2024-03-16 01:23:42 +01:00
NeroBurner
08da925fde readme: small wording improvements (#610)
Removes an extra `the` in the Readme about the tested Linux versions
2024-02-28 20:45:32 +01:00
Dominik Nussbaumer
fb58c435ef Fix ODR violations when using CMake unity builds. (#609) 2024-02-28 13:25:20 +01:00
Dominik Nussbaumer
6bf593ef4b fix forward declarations of QXmlStreamWriter (#608) 2024-02-27 17:34:42 +01:00
Uwe Kindler
6b3b7750cb Fixed #604 - AutoHide widgets disapears when last open DockWidget is closed 2024-02-12 08:18:33 +01:00
Uwe Kindler
541db8e214 Fixed wrong hiding/showing of dock area title bar buttons when DockAreaHideDisabledButtons flag is enabled 2024-02-12 08:11:56 +01:00
Uwe Kindler
644c828f00 Fixed crash caused by changes related to issue #594 - deletion of CFloatingWidget caused crash when loading a state from XML 2024-01-26 16:31:04 +01:00
Uwe Kindler
ed6636ae26 Added CDockManager::lockDockWidgetFeaturesGlobally functionality to globally "freeze" the current docking layout 2024-01-23 13:29:41 +01:00
Stefan Gerlach
1a543e946d Fix 'zero as null pointer constant' warning (#598) 2024-01-16 14:05:42 +01:00
Uwe Kindler
9bdefd6055 Fixed issue #597 - Crashes when the floating widget moves to the dock manager and then tries to drag it back 2024-01-16 14:03:53 +01:00
Uwe Kindler
8fd691968c Merge branch 'master' of https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System 2024-01-04 08:31:57 +01:00
Uwe Kindler
7abc698d09 Fixed #594 - Destruction of CDockWidget inside a CFloatingDockContainer 2024-01-04 08:31:18 +01:00
Uwe Kindler
5b23248fb8 Fixed debug output issues and improved debug output for CDockWidget destructor 2024-01-04 08:30:17 +01:00
Uwe Kindler
46a5cee9c9 Added .clang-format file 2024-01-02 09:11:36 +01:00
Benjamin Buch
6c2c9888be respect customized CMake install locations (#593) 2023-12-12 13:54:51 +01:00
Uwe Kindler
44ff9e9956 Fixed some compiler warnings on Ubuntu 22.04 2023-12-08 07:58:36 +01:00
tmartsum
f848df74c3 Improve safety in code (#588)
Delete areas later so that that they can be accessed by
(inherited) dock widgets in dtor. Add some QPointer to
prevent crashes.

Hence allow users to do more while dock widgets etc
are being destroyed.
2023-12-08 06:47:02 +01:00
tmartsum
6c98c29855 Update documentation regarding central widget (#589) 2023-12-07 10:00:30 +01:00
tmartsum
c34d479d5c Avoid dock manager double delete (crashes) (#587)
If a dockwidget has been manually deleted, the dockmanager
would delete it again when deleting the area in its dtor.
The 'optimal' solution would likely have been changing
CDockWidget::~CDockWidget to add
if (d->DockArea) d->DockArea->removeDockWidget(this);
(before delete d).
However, it is not trivial (for me) to conclude that such
a change would be safe on program shutdown.

Co-authored-by: Thorbjørn Lund Martsum <thorbjorn@luxion.com>
2023-12-06 15:12:48 +01:00
jporcher
a7a97e6978 Fix https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/585 (#586) 2023-12-05 14:44:31 +01:00
Uwe Kindler
ec018a4c70 Added documentation for new "ShowTabTextOnlyForActiveTab" config flag 2023-12-04 09:24:59 +01:00
Uwe Kindler
0fabebb0fe Merge branch 'master' of https://github.com/nitramr/Qt-Advanced-Docking-System into nitramr-master 2023-12-04 09:10:34 +01:00
Uwe Kindler
521e1fbe39 Updated default AutoHide config to use Minimize button 2023-12-04 09:10:02 +01:00
Uwe Kindler
5f2aeaef00 Updated gitignore 2023-12-04 09:09:37 +01:00
nitramr
818e568f4a new configuration of icon only tabs 2023-12-02 14:48:43 +01:00
tmartsum
5d6831d179 Fix DockWidget crach when area is a nullptr. (#582)
When requesting hide on a dockwidget that has been added
to a dockmanager, but isn't yet visible, there was a creash.
The crash has been fixed by moving the code to the existing
guard check for the area.

Co-authored-by: Thorbjørn Lund Martsum <thorbjorn@luxion.com>
2023-12-01 15:13:45 +01:00
Uwe Kindler
a2c94c16b5 Fixed bug in focus_highlighting.css stylesheet 2023-11-27 22:04:45 +01:00
Uwe Kindler
68f1084bf0 Added parentSplitter() fucntion to DockArea and removed dead code from DockContainerWidget 2023-11-27 21:48:14 +01:00
Uwe Kindler
761bfc50d6 Fixed #581 - FocusHighlighting is broken after detaching a dock widget 2023-11-24 13:54:19 +01:00
Uwe Kindler
59b4dfb89c Updated documentation 2023-11-07 12:23:01 +01:00
Uwe Kindler
bfa5124999 Merge branch 'master' of https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System 2023-11-06 12:18:40 +01:00
Uwe Kindler
234cf9ac58 Improved disabled pin button 2023-11-06 12:17:39 +01:00
Uwe Kindler
8f77f4b42a Added documentation for new Auto Hide Minimize button 2023-11-06 12:08:31 +01:00
Uwe Kindler
fa94da00d4 Added optional Minimize button to AutoHide dock widget title bar 2023-11-06 11:06:12 +01:00
gafusss
40beef964b Fix memory leak in CDockContainerWidget::restoreState (#576)
delete old root splitter layout item
2023-11-04 06:49:01 +01:00
Uwe Kindler
420baeedfe Added support for global dock manager toolbar style and custom dock widget toolbar style for dock widgets 2023-10-19 10:25:23 +02:00
Uwe Kindler
0f8096e314 Added minimize and close action to Auto Hide context menu 2023-10-19 09:10:26 +02:00
uggas
9ec97a8867 Add ability to set user defined toggle view action (#562)
Co-authored-by: Harbinder Saggu <harbinder.saggu@safe.com>
2023-10-19 08:07:55 +02:00
Nate Skulic
55ef6ef863 Improve Python Support (#567)
- Reduce requirements for the python build.
- Fix version number.
- Generate type hints for *.pyi files.
- Make functional for sip-build
- Reduced the unnecessary depth of the package.

NOTE: This is a breaking change for python users, where, `from PyQtAds import QtAds` is changed to `import PyQtAds as QtAds`( or simply `import PyQtAds`)
2023-10-05 07:23:54 +02:00
Henning
c0985f6497 Fix empty floating widget on linux (#563) 2023-09-22 20:03:02 +02:00
Uwe Kindler
2f1ef61f82 Fixed documentation issue - wrong location of picture 2023-09-19 08:53:04 +02:00
Uwe Kindler
62d2dd213d Implemented #554 - Add a configuration that avoid tab label eliding 2023-09-19 08:44:31 +02:00
vhutter
3c941a2312 Enabled modifying MSVC runtime in cmake (#559) 2023-09-11 14:57:09 +02:00
603185423
4634b5617c CMake Script - Add debug postfix "d" (#406) (#558)
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/406
2023-09-11 12:56:32 +02:00
André Meyer
2178b52621 Delete implicit ScrollArea when content Widget is deleted in hideDockWidget() (#551) 2023-08-24 11:20:32 +02:00
Ahmad Syarifuddin
61573cba16 Fix crash in auto hide tab (#552)
- Crash is caused by dragging an autohide tab out when it is an icon only.
- The crash can actually happen with non icon only tabs, but is masked by the orientation check.
- Soln: Check if auto hide container exists first on mouse finish dragging event.
2023-08-24 11:15:43 +02:00
Joel Bodenmann
2d2de53dcd Fix CMake scripts for FreeBSD (#550)
This fixes linking of the XCB library on FreeBSD.
2023-08-17 17:57:16 +02:00
luzpaz
0d10c6e2d9 Fix various typos (#547)
Typos found via `codespell -q 3 -L te,ridiculus,varius`
2023-08-08 19:46:12 +02:00
Uwe Kindler
767933d0cb Merge branch 'master' of https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System 2023-08-03 15:58:07 +02:00
Uwe Kindler
7a362b7ee3 Fixed issue #544 - crash in CDockAreaTabBar::currentTab() 2023-08-03 15:57:57 +02:00
Nicolas Elie
77ed9b0661 Update PyQt bindings to 4.1.1 (#542) 2023-08-02 20:23:49 +02:00
Uwe Kindler
65600a4dcd Removed unimolemented superfluous function definitions 2023-07-14 08:07:37 +02:00
Uwe Kindler
ac1879d5cb Added missing README images 2023-07-13 13:59:48 +02:00
Uwe Kindler
f00ef60fb3 Merge remote-tracking branch 'remotes/origin/autohide_drag' 2023-07-13 13:58:08 +02:00
Uwe Kindler
1a1352e456 Updated README.md for 4.1 release 2023-07-13 13:53:29 +02:00
Uwe Kindler
65ae86a46d Removed debug output 2023-07-13 07:25:09 +02:00
Uwe Kindler
e239cdb354 Improved sizing of AutoHideWidgets when dragging between side bars 2023-07-12 14:37:45 +02:00
Uwe Kindler
7140e5e32a Properly handle dragging of dock widget into DockWidgetTabBar and AutoHideSideBar 2023-07-12 14:22:05 +02:00
Uwe Kindler
f5cfe9e05a Fixed tab insertion when dragging side tab 2023-07-12 14:01:39 +02:00
Uwe Kindler
be727c5890 Added initial support for inserting dropped dock widgets at a certain sidebar position 2023-07-12 10:42:24 +02:00
Uwe Kindler
f4fc0dab29 Added support for dropping dock widget to a certain tab postion of a dock area 2023-07-12 09:39:20 +02:00
Uwe Kindler
39bc7f1780 Properly consider pinnable flag of dock widget when painting the drop overlays - no auto hide overlay for non pinnable dock widgets 2023-07-11 10:28:17 +02:00
Uwe Kindler
364ee33f9c Removed some std::cout debug output 2023-07-11 10:27:08 +02:00
Uwe Kindler
cb5e9f60a1 Changed default auto hide config - added flag AutoHideCloseButtonCollapsesDock 2023-07-11 08:26:03 +02:00
Uwe Kindler
2760fb1fe9 AutoHide dock area now always shows pin button independently from DockAreaHasAutoHideButton flag 2023-07-11 08:25:34 +02:00
Uwe Kindler
8a82e4cf57 Removed debug output and fixed painting of SideBar drag overlays 2023-07-10 12:07:44 +02:00
Uwe Kindler
0627b3183f Added "Close" action to AutoHideTab context menu 2023-07-10 10:38:21 +02:00
Uwe Kindler
df1bc94d9e Added Auto-Hide tab unpin context menu entry 2023-07-10 10:18:09 +02:00
Uwe Kindler
6924e69b6b Fixed detaching of auto hide widgets in a floating widget 2023-07-10 10:10:37 +02:00
Uwe Kindler
0a6c58fd66 Properly implemented drag and drop of auto hide tabs 2023-07-10 09:34:11 +02:00
Uwe Kindler
bf22e54fc3 Improved support for AutoHideTab drag and drop 2023-07-07 15:20:43 +02:00
Uwe Kindler
4307f48d99 Implemented initial support for dragging auto hide tabs 2023-07-07 14:42:13 +02:00
Uwe Kindler
4bdc04e9d8 Implemented Pin To functionality for Auto Hide Tabs 2023-07-07 13:35:55 +02:00
Uwe Kindler
1c6d86e70f Added support for make auto hide widget floating via double click or context menu 2023-07-07 11:21:54 +02:00
Nicolas Elie
6e642ec423 Update PyQt bindings to 4.0.4 (#532) 2023-07-03 14:09:48 +02:00
Uwe Kindler
0b3c3f0123 Merge branch 'master' into autohide_drag 2023-07-01 21:28:07 +02:00
Uwe Kindler
e2929ade14 Fixed DockContainerWidget.cpp contentRect() function to work properly even if no dock widget is visible in container 2023-06-28 15:59:26 +02:00
Uwe Kindler
b801f0655d Improved dragging of widgets into AutoHideArea 2023-06-28 14:01:08 +02:00
Uwe Kindler
f6ccaba6aa Added dropIntoAutoHideSideBar() function 2023-06-28 10:19:59 +02:00
Uwe Kindler
21189759dd Removed drop icons for sidebar drops 2023-06-28 07:32:49 +02:00
Uwe Kindler
047ea3c494 Implemented new dock overlay icons for sidebar areas 2023-06-27 20:43:44 +02:00
Uwe Kindler
f71c8ffe5d Tested various pin buttons 2023-06-27 12:43:12 +02:00
Uwe Kindler
381acb2449 Merge branch 'master' into autohide_drag 2023-06-27 10:20:00 +02:00
Uwe Kindler
b9479dbd3d Started implementing autohide drag functionality 2023-06-27 10:12:51 +02:00
118 changed files with 3595 additions and 554 deletions

146
.clang-format Normal file
View File

@@ -0,0 +1,146 @@
---
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: None
AlignConsecutiveAssignments: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: Inline
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: AfterColon
BreakStringLiterals: true
ColumnLimit: 82
CommentPragmas: '^(!.*|@c)'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
FixNamespaceComments: true
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<windows(\.h)?>' # windows headers
Priority: -1
- Regex: '^<labbcan[[:alnum:]._/]+' # labbcan headers
Priority: 1
- Regex: '^<diag[[:alnum:]._/]+' # usl headers
Priority: 1
- Regex: '^<usl[[:alnum:]._/]+' # usl headers
Priority: 1
- Regex: '^<qt5compat[[:alnum:]._/]+' # qtlabb headers
Priority: 2
- Regex: '^<qtcoreaddons[[:alnum:]._/]+' # qtlabb headers
Priority: 2
- Regex: '^<qtlabb[[:alnum:]._/]+' # qtlabb headers
Priority: 2
- Regex: '<Q[[:alnum:].]+>' # Qt headers
Priority: 3
- Regex: '^<sila_cpp[[:alnum:]._/]+' # sila_cpp headers
Priority: 4
- Regex: '<[[:alnum:]._/]+\.h>' # other headers
Priority: 5
- Regex: '<[[:alnum:]._/]+>' # system headers
Priority: 6
- Regex: '.*'
Priority: 7
IncludeIsMainRegex: '(_p)?$'
IndentCaseBlocks: false
IndentCaseLabels: false
IndentPPDirectives: AfterHash
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
PenaltyBreakAssignment: 20
PenaltyBreakBeforeFirstCallParameter: 15
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 5
# PenaltyBreakOpenParenthesis: 30
PenaltyBreakString: 150
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 100
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 150
PointerAlignment: Left
ReflowComments: true
SortIncludes: CaseSensitive
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: Never
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: c++17
StatementMacros: [ 'Q_UNUSED', 'PIMPL_D', 'PIMPL_Q', 'OD_ENTRY', 'OD_ENTRY_PROCIMG' ]
TabWidth: 4
UseTab: Never

5
.gitignore vendored
View File

@@ -1,4 +1,4 @@
*.pro.user *.pro.user*
/build /build
*.o *.o
*.dylib *.dylib
@@ -7,6 +7,9 @@ qrc_*
moc_* moc_*
ui_* ui_*
Makefile Makefile
*.dll
*.a
build*
# IDEs # IDEs
.idea .idea

View File

@@ -1,4 +1,8 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if (POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif (POLICY CMP0091)
# By default, the version information is extracted from the git index. However, # By default, the version information is extracted from the git index. However,
# we can override this behavior by explicitly setting ADS_VERSION and # we can override this behavior by explicitly setting ADS_VERSION and

View File

@@ -22,6 +22,70 @@ integrated development environments (IDEs) such as Visual Studio.
## New and Noteworthy ## New and Noteworthy
Release [4.1](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/latest) significantly improves the Auto-Hide functionality and also brings improvements
for Drag and Drop of dock widgets into dock area tabs. These are the highlights of the new version:
#### Drag & Drop to Auto-Hide
Now you can easily drag any dock widget or any floating widget to the
borders of a window to pin it as a auto-hide tab in one of the 4 sidebars.
If you drag a dock widget close the one of the four window borders, special
drop overlays will be shown to indicate the drop area for auto-hide widgets:
![Auo-Hide drag to Sidebar](doc/AutoHide_Drag_to_Sidebar.gif)
Of course, this also works with dock areas:
![Auo-Hide drag Dock Area](doc/AutoHide_Drag_DockArea.gif)
If you drag a dock widget or dock area into a sidebar, then you even have
control over where tabs are inserted. Simply drag your mouse over a specific
auto-hide tab, and your dragged dock widget will be inserted before this tab.
Drag to the sidebar area behind the last tab, and the dragged widget will be
appended as last tab. In the following screen capture, the **Image Viewer 1** will
be inserted before the **Table 0** Auto-Hide tab and the **Image Viewer 2**
is appende behind the last tab:
![Auo-Hide tab insert order](doc/AutoHide_Tab_Insert_Order.gif)
#### Auto-Hide Tab Insertion Order
It is also possible to drag Auto-Hide tabs to a new auto-hide position.
That means, you can drag them to a different border or sidebar:
![Auto-Hide change sidebar](doc/AutoHide_Change_Sidebar.gif)
#### Auto-Hide Tab Sorting
You can drag Auto-Hide tabs to a new position in the current sidebar
to sort them:
![Auo-Hide sort tabs](doc/AutoHide_Sort_Tabs.gif)
#### Auto-Hide Drag to Float / Dock
But that is not all. You can also simply move Auto-Hide tabs to another
floating widget or dock them via drag and drop:
![Auo-Hide drag to float or dock](doc/AutoHide_Drag_to_Float_or_Dock.gif)
#### Auto-Hide Context Menu
All Auto-Hide tabs now have a context menu, that provides all the functionality
that you know from Dock widget tabs. With the **Pin To...** item from the
context menu it is very easy to move an Auto-Hide tab to a different Auto-Hide
sidebar:
![Auo-Hide context menu](doc/AutoHide_Context_Menu.png)
#### Dock Area Tab Insert Order
And last but not least the new version also improves the docking of widgets
into the tabs of a Dock area. Just as with Auto-Hide tabs, you can now determine the position at which a tab is inserted by moving the mouse over an already existing tab (insertion before the tab) or behind the last tab
(appending):
![Dock area tab insert order](doc/DockArea_Tab_Insertion_Order.gif)
The [release 4.0](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/latest) The [release 4.0](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/latest)
adds the following features: adds the following features:
@@ -77,6 +141,12 @@ know it from Visual Studio.
### Overview ### Overview
- [New and Noteworthy](#new-and-noteworthy) - [New and Noteworthy](#new-and-noteworthy)
- [Drag \& Drop to Auto-Hide](#drag--drop-to-auto-hide)
- [Auto-Hide Tab Insertion Order](#auto-hide-tab-insertion-order)
- [Auto-Hide Tab Sorting](#auto-hide-tab-sorting)
- [Auto-Hide Drag to Float / Dock](#auto-hide-drag-to-float--dock)
- [Auto-Hide Context Menu](#auto-hide-context-menu)
- [Dock Area Tab Insert Order](#dock-area-tab-insert-order)
- [Features](#features) - [Features](#features)
- [Overview](#overview) - [Overview](#overview)
- [Docking everywhere - no central widget](#docking-everywhere---no-central-widget) - [Docking everywhere - no central widget](#docking-everywhere---no-central-widget)
@@ -298,7 +368,7 @@ The application can be compiled for macOS. A user reported, that the library wor
[![Build Status](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System.svg?branch=master)](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System) [![Build Status](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System.svg?branch=master)](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
[![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://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)
Unfortunately, there is no such thing as a Linux operating system. Linux is a heterogeneous environment with a variety of different distributions. So it is not possible to support "Linux" like this is possible for Windows. It is only possible to support and test a small subset of Linux distributions. The library can be compiled for and has been developed and tested with the some Linux distributions. Depending on the used window manager or compositor, dock widgets Unfortunately, there is no such thing as a Linux operating system. Linux is a heterogeneous environment with a variety of different distributions. So it is not possible to support "Linux" like it is possible for Windows. It is only possible to support and test a small subset of Linux distributions. The library can be compiled for and has been developed and tested with some Linux distributions. Depending on the used window manager or compositor, dock widgets
with native title bars are supported or not. If native title bars are not supported, with native title bars are supported or not. If native title bars are not supported,
the library switches to `QWidget` based title bars. the library switches to `QWidget` based title bars.

View File

@@ -75,18 +75,17 @@
#endif #endif
#endif #endif
#include "DockManager.h"
#include "DockWidget.h"
#include "DockAreaWidget.h"
#include "DockAreaTitleBar.h"
#include "DockAreaTabBar.h" #include "DockAreaTabBar.h"
#include "FloatingDockContainer.h" #include "DockAreaTitleBar.h"
#include "DockAreaWidget.h"
#include "DockComponentsFactory.h" #include "DockComponentsFactory.h"
#include "StatusDialog.h" #include "DockManager.h"
#include "DockSplitter.h" #include "DockSplitter.h"
#include "DockWidget.h"
#include "FloatingDockContainer.h"
#include "ImageViewer.h" #include "ImageViewer.h"
#include "MyDockAreaTitleBar.h"
#include "StatusDialog.h"
/** /**
* Returns a random number from 0 to highest - 1 * Returns a random number from 0 to highest - 1
@@ -147,7 +146,7 @@ public:
using Super = ads::CDockComponentsFactory; using Super = ads::CDockComponentsFactory;
ads::CDockAreaTitleBar* createDockAreaTitleBar(ads::CDockAreaWidget* DockArea) const override ads::CDockAreaTitleBar* createDockAreaTitleBar(ads::CDockAreaWidget* DockArea) const override
{ {
auto TitleBar = new ads::CDockAreaTitleBar(DockArea); auto TitleBar = new MyDockAreaTitleBar(DockArea);
auto CustomButton = new QToolButton(DockArea); auto CustomButton = new QToolButton(DockArea);
CustomButton->setToolTip(QObject::tr("Help")); CustomButton->setToolTip(QObject::tr("Help"));
CustomButton->setIcon(svgIcon(":/adsdemo/images/help_outline.svg")); CustomButton->setIcon(svgIcon(":/adsdemo/images/help_outline.svg"));
@@ -271,6 +270,10 @@ struct MainWindowPrivate
auto ToolBar = DockWidget->createDefaultToolBar(); auto ToolBar = DockWidget->createDefaultToolBar();
ToolBar->addAction(ui.actionSaveState); ToolBar->addAction(ui.actionSaveState);
ToolBar->addAction(ui.actionRestoreState); ToolBar->addAction(ui.actionRestoreState);
// For testing all calendar dock widgets have a the tool button style
// Qt::ToolButtonTextUnderIcon
DockWidget->setToolBarStyleSource(ads::CDockWidget::ToolBarStyleFromDockWidget);
DockWidget->setToolBarStyle(Qt::ToolButtonTextUnderIcon, ads::CDockWidget::StateFloating);
return DockWidget; return DockWidget;
} }
@@ -448,8 +451,8 @@ void MainWindowPrivate::createContent()
// For this Special Dock Area we want to avoid dropping on the center of it (i.e. we don't want this widget to be ever tabbified): // For this Special Dock Area we want to avoid dropping on the center of it (i.e. we don't want this widget to be ever tabbified):
{ {
SpecialDockArea->setAllowedAreas(ads::OuterDockAreas); //SpecialDockArea->setAllowedAreas(ads::OuterDockAreas);
//SpecialDockArea->setAllowedAreas({ads::LeftDockWidgetArea, ads::RightDockWidgetArea}); // just for testing SpecialDockArea->setAllowedAreas({ads::LeftDockWidgetArea, ads::RightDockWidgetArea, ads::TopDockWidgetArea}); // just for testing
} }
DockWidget = createLongTextLabelDockWidget(); DockWidget = createLongTextLabelDockWidget();
@@ -517,7 +520,9 @@ void MainWindowPrivate::createContent()
// Test dock area docking // Test dock area docking
auto RighDockArea = DockManager->addDockWidget(ads::RightDockWidgetArea, createLongTextLabelDockWidget(), TopDockArea); auto RighDockArea = DockManager->addDockWidget(ads::RightDockWidgetArea, createLongTextLabelDockWidget(), TopDockArea);
DockManager->addDockWidget(ads::TopDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea); DockWidget = createLongTextLabelDockWidget();
DockWidget->setFeature(ads::CDockWidget::DockWidgetPinnable, false);
DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget, RighDockArea);
auto BottomDockArea = DockManager->addDockWidget(ads::BottomDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea); auto BottomDockArea = DockManager->addDockWidget(ads::BottomDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea);
DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea); DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea);
auto LabelDockWidget = createLongTextLabelDockWidget(); auto LabelDockWidget = createLongTextLabelDockWidget();
@@ -525,6 +530,7 @@ void MainWindowPrivate::createContent()
// Tests CustomCloseHandling without DeleteOnClose // Tests CustomCloseHandling without DeleteOnClose
LabelDockWidget->setFeature(ads::CDockWidget::CustomCloseHandling, true); LabelDockWidget->setFeature(ads::CDockWidget::CustomCloseHandling, true);
LabelDockWidget->setWindowTitle(LabelDockWidget->windowTitle() + " [Custom Close]");
QObject::connect(LabelDockWidget, &ads::CDockWidget::closeRequested, [LabelDockWidget, this]() QObject::connect(LabelDockWidget, &ads::CDockWidget::closeRequested, [LabelDockWidget, this]()
{ {
int Result = QMessageBox::question(_this, "Custom Close Request", int Result = QMessageBox::question(_this, "Custom Close Request",
@@ -585,19 +591,29 @@ void MainWindowPrivate::createActions()
ui.toolBar->addAction(ui.actionRestoreState); ui.toolBar->addAction(ui.actionRestoreState);
ui.actionRestoreState->setIcon(svgIcon(":/adsdemo/images/restore.svg")); ui.actionRestoreState->setIcon(svgIcon(":/adsdemo/images/restore.svg"));
SavePerspectiveAction = new QAction("Create Perspective", _this); ui.toolBar->addSeparator();
SavePerspectiveAction->setIcon(svgIcon(":/adsdemo/images/picture_in_picture.svg"));
_this->connect(SavePerspectiveAction, SIGNAL(triggered()), SLOT(savePerspective())); QAction* a = ui.toolBar->addAction("Lock Workspace");
a->setIcon(svgIcon(":/adsdemo/images/lock_outline.svg"));
a->setCheckable(true);
a->setChecked(false);
QObject::connect(a, &QAction::triggered, _this, &CMainWindow::lockWorkspace);
PerspectiveListAction = new QWidgetAction(_this); PerspectiveListAction = new QWidgetAction(_this);
PerspectiveComboBox = new QComboBox(_this); PerspectiveComboBox = new QComboBox(_this);
PerspectiveComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); PerspectiveComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
PerspectiveComboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); PerspectiveComboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
PerspectiveListAction->setDefaultWidget(PerspectiveComboBox); PerspectiveListAction->setDefaultWidget(PerspectiveComboBox);
ui.toolBar->addSeparator();
ui.toolBar->addAction(PerspectiveListAction); ui.toolBar->addAction(PerspectiveListAction);
a = SavePerspectiveAction = ui.toolBar->addAction("Create Perspective");
a->setIcon(svgIcon(":/adsdemo/images/picture_in_picture.svg"));
QObject::connect(a, &QAction::triggered, _this, &CMainWindow::savePerspective);
ui.toolBar->addAction(SavePerspectiveAction); ui.toolBar->addAction(SavePerspectiveAction);
QAction* a = ui.toolBar->addAction("Create Floating Editor"); ui.toolBar->addSeparator();
a = ui.toolBar->addAction("Create Floating Editor");
a->setProperty("Floating", true); a->setProperty("Floating", true);
a->setToolTip("Creates floating dynamic dockable editor windows that are deleted on close"); a->setToolTip("Creates floating dynamic dockable editor windows that are deleted on close");
a->setIcon(svgIcon(":/adsdemo/images/note_add.svg")); a->setIcon(svgIcon(":/adsdemo/images/note_add.svg"));
@@ -619,6 +635,7 @@ void MainWindowPrivate::createActions()
_this->connect(a, SIGNAL(triggered()), SLOT(createEditor())); _this->connect(a, SIGNAL(triggered()), SLOT(createEditor()));
ui.menuTests->addAction(a); ui.menuTests->addAction(a);
ui.toolBar->addSeparator();
a = ui.toolBar->addAction("Create Floating Table"); a = ui.toolBar->addAction("Create Floating Table");
a->setToolTip("Creates floating dynamic dockable table with millions of entries"); a->setToolTip("Creates floating dynamic dockable table with millions of entries");
a->setIcon(svgIcon(":/adsdemo/images/grid_on.svg")); a->setIcon(svgIcon(":/adsdemo/images/grid_on.svg"));
@@ -761,6 +778,7 @@ CMainWindow::CMainWindow(QWidget *parent) :
// Now create the dock manager and its content // Now create the dock manager and its content
d->DockManager = new CDockManager(this); d->DockManager = new CDockManager(this);
d->DockManager->setDockWidgetToolBarStyle(Qt::ToolButtonIconOnly, ads::CDockWidget::StateFloating);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
connect(d->PerspectiveComboBox, SIGNAL(activated(QString)), connect(d->PerspectiveComboBox, SIGNAL(activated(QString)),
@@ -1022,3 +1040,17 @@ void CMainWindow::createImageViewer()
} }
} }
//============================================================================
void CMainWindow::lockWorkspace(bool Value)
{
if (Value)
{
d->DockManager->lockDockWidgetFeaturesGlobally();
}
else
{
d->DockManager->lockDockWidgetFeaturesGlobally(ads::CDockWidget::NoDockWidgetFeatures);
}
}

View File

@@ -68,6 +68,7 @@ private slots:
void toggleDockWidgetWindowTitle(); void toggleDockWidgetWindowTitle();
void applyVsStyle(); void applyVsStyle();
void createImageViewer(); void createImageViewer();
void lockWorkspace(bool Value);
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

34
demo/MyDockAreaTitleBar.h Normal file
View File

@@ -0,0 +1,34 @@
//
// Created by fuga on 08 nov 2024.
//
#ifndef QTADS_MYDOCKAREATITLEBAR_H
#define QTADS_MYDOCKAREATITLEBAR_H
#include <DockAreaTitleBar.h>
class MyDockAreaTitleBar : public ads::CDockAreaTitleBar {
public:
explicit MyDockAreaTitleBar(ads::CDockAreaWidget* parent)
: CDockAreaTitleBar(parent)
{}
QMenu* buildContextMenu(QMenu*) override
{
auto menu = ads::CDockAreaTitleBar::buildContextMenu(nullptr);
menu->addSeparator();
auto action = menu->addAction(tr("Format HardDrive"));
connect(action, &QAction::triggered, this, [this](){
QMessageBox msgBox;
msgBox.setText("No, just kidding");
msgBox.setStandardButtons(QMessageBox::Abort);
msgBox.setDefaultButton(QMessageBox::Abort);
msgBox.exec();
});
return menu;
}
};
#endif // QTADS_MYDOCKAREATITLEBAR_H

View File

@@ -36,5 +36,8 @@
<file>images/panorama.svg</file> <file>images/panorama.svg</file>
<file>images/ads_icon2.svg</file> <file>images/ads_icon2.svg</file>
<file>images/font_download.svg</file> <file>images/font_download.svg</file>
<file>images/lock_outline.svg</file>
<file>images/lock.svg</file>
<file>images/lock_open.svg</file>
</qresource> </qresource>
</RCC> </RCC>

6
demo/images/lock.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>lock 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="M853.33,426.67v426.66c0,46.93 -38.4,85.34 -85.33,85.34h-512c-46.93,0 -85.33,-38.41 -85.33,-85.34v-426.66c0,-46.93 38.4,-85.34 85.33,-85.34h42.67v-85.33c0,-117.76 95.57,-213.33 213.33,-213.33c117.76,0 213.33,95.57 213.33,213.33v85.33h42.67c46.93,0 85.33,38.41 85.33,85.34zM644.27,256c0,-72.96 -59.31,-132.27 -132.27,-132.27c-72.96,0 -132.27,59.31 -132.27,132.27v85.33h264.54zM597.33,640c0,-46.93 -38.4,-85.33 -85.33,-85.33c-46.93,0 -85.33,38.4 -85.33,85.33c0,46.93 38.4,85.33 85.33,85.33c46.93,0 85.33,-38.4 85.33,-85.33z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 932 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>lock_open 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="M853.33,426.67v426.66c0,46.93 -38.4,85.34 -85.33,85.34h-512c-46.93,0 -85.33,-38.41 -85.33,-85.34v-426.66c0,-46.93 38.4,-85.34 85.33,-85.34h388.27v-85.33c0,-72.96 -59.31,-132.27 -132.27,-132.27c-72.96,0 -132.27,59.31 -132.27,132.27h-81.06c0,-117.76 95.57,-213.33 213.33,-213.33c117.76,0 213.33,95.57 213.33,213.33v85.33h42.67c46.93,0 85.33,38.41 85.33,85.34zM768,426.67h-512v426.66h512zM426.67,640c0,-46.93 38.4,-85.33 85.33,-85.33c46.93,0 85.33,38.4 85.33,85.33c0,46.93 -38.4,85.33 -85.33,85.33c-46.93,0 -85.33,-38.4 -85.33,-85.33z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 948 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>lock_outline 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="M853.33,426.67v426.66c0,46.93 -38.4,85.34 -85.33,85.34h-512c-46.93,0 -85.33,-38.41 -85.33,-85.34v-426.66c0,-46.93 38.4,-85.34 85.33,-85.34h42.67v-85.33c0,-117.76 95.57,-213.33 213.33,-213.33c117.76,0 213.33,95.57 213.33,213.33v85.33h42.67c46.93,0 85.33,38.41 85.33,85.34zM768,426.67h-512v426.66h512zM379.73,341.33h264.54v-85.33c0,-72.96 -59.31,-132.27 -132.27,-132.27c-72.96,0 -132.27,59.31 -132.27,132.27zM426.67,640c0,-46.93 38.4,-85.33 85.33,-85.33c46.93,0 85.33,38.4 85.33,85.33c0,46.93 -38.4,85.33 -85.33,85.33c-46.93,0 -85.33,-38.4 -85.33,-85.33z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 972 B

View File

@@ -2,7 +2,7 @@ import os
import sys import sys
from PyQt5 import uic from PyQt5 import uic
from PyQtAds import QtAds import PyQtAds as QtAds
UI_FILE = os.path.join(os.path.dirname(__file__), 'StatusDialog.ui') UI_FILE = os.path.join(os.path.dirname(__file__), 'StatusDialog.ui')
StatusDialogUI, StatusDialogBase = uic.loadUiType(UI_FILE) StatusDialogUI, StatusDialogBase = uic.loadUiType(UI_FILE)

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 642 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 KiB

BIN
doc/AutoHide_Sort_Tabs.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

View File

@@ -12,10 +12,10 @@ styles as much as possible.
## Features ## Features
### Docking everywhere - no central widget ### Docking everywhere - with or without a central widget
There is no central widget like in the Qt docking system. You can dock on every The Advanced Docking System works with or without a central widget.
border of the main window or you can dock into each dock area - so you are You can dock on every border of the main window or you can dock into each dock area - so you are
free to dock almost everywhere. free to dock almost everywhere.
![Dropping widgets](https://raw.githubusercontent.com/githubuser0xFFFF/Qt-Advanced-Docking-System/master/doc/preview-dragndrop.png) ![Dropping widgets](https://raw.githubusercontent.com/githubuser0xFFFF/Qt-Advanced-Docking-System/master/doc/preview-dragndrop.png)
@@ -65,7 +65,7 @@ If this flag is cleared, the widget resizing is deferred until the mouse button
### Opaque and non-opaque undocking ### 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: The drag preview widget can be configured by a number of global dock manager flags:

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -27,10 +27,17 @@
- [`FloatingContainerForceNativeTitleBar` (Linux only)](#floatingcontainerforcenativetitlebar-linux-only) - [`FloatingContainerForceNativeTitleBar` (Linux only)](#floatingcontainerforcenativetitlebar-linux-only)
- [`FloatingContainerForceQWidgetTitleBar` (Linux only)](#floatingcontainerforceqwidgettitlebar-linux-only) - [`FloatingContainerForceQWidgetTitleBar` (Linux only)](#floatingcontainerforceqwidgettitlebar-linux-only)
- [`MiddleMouseButtonClosesTab`](#middlemousebuttonclosestab) - [`MiddleMouseButtonClosesTab`](#middlemousebuttonclosestab)
- [`DisableTabTextEliding`](#disabletabtexteliding)
- [`ShowTabTextOnlyForActiveTab`](#showtabtextonlyforactivetab)
- [Auto-Hide Configuration Flags](#auto-hide-configuration-flags) - [Auto-Hide Configuration Flags](#auto-hide-configuration-flags)
- [Auto Hide Dock Widgets](#auto-hide-dock-widgets) - [Auto Hide Dock Widgets](#auto-hide-dock-widgets)
- [Pinning Auto-Hide Widgets to a certain border](#pinning-auto-hide-widgets-to-a-certain-border) - [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) - [Show / Hide Auto-Hide Widgets via Mouse Over](#show--hide-auto-hide-widgets-via-mouse-over)
- [Drag \& Drop to Auto-Hide](#drag--drop-to-auto-hide)
- [Auto-Hide Tab Insertion Order](#auto-hide-tab-insertion-order)
- [Auto-Hide Tab Sorting](#auto-hide-tab-sorting)
- [Auto-Hide Drag to Float / Dock](#auto-hide-drag-to-float--dock)
- [Auto-Hide Context Menu](#auto-hide-context-menu)
- [Adding Auto Hide Widgets](#adding-auto-hide-widgets) - [Adding Auto Hide Widgets](#adding-auto-hide-widgets)
- [Setting Auto-Hide Flags](#setting-auto-hide-flags) - [Setting Auto-Hide Flags](#setting-auto-hide-flags)
- [`AutoHideFeatureEnabled`](#autohidefeatureenabled) - [`AutoHideFeatureEnabled`](#autohidefeatureenabled)
@@ -40,6 +47,9 @@
- [`AutoHideSideBarsIconOnly`](#autohidesidebarsicononly) - [`AutoHideSideBarsIconOnly`](#autohidesidebarsicononly)
- [`AutoHideShowOnMouseOver`](#autohideshowonmouseover) - [`AutoHideShowOnMouseOver`](#autohideshowonmouseover)
- [`AutoHideCloseButtonCollapsesDock`](#autohideclosebuttoncollapsesdock) - [`AutoHideCloseButtonCollapsesDock`](#autohideclosebuttoncollapsesdock)
- [`AutoHideHasCloseButton`](#autohidehasclosebutton)
- [`AutoHideHasMinimizeButton`](#autohidehasminimizebutton)
- [`AutoHideOpenOnDragHover`](#autohideopenondraghover)
- [DockWidget Feature Flags](#dockwidget-feature-flags) - [DockWidget Feature Flags](#dockwidget-feature-flags)
- [`DockWidgetClosable`](#dockwidgetclosable) - [`DockWidgetClosable`](#dockwidgetclosable)
- [`DockWidgetMovable`](#dockwidgetmovable) - [`DockWidgetMovable`](#dockwidgetmovable)
@@ -294,8 +304,9 @@ or to close it via the close button.
![HideSingleCentralWidgetTitleBar true](cfg_flag_HideSingleCentralWidgetTitleBar_true.png) ![HideSingleCentralWidgetTitleBar true](cfg_flag_HideSingleCentralWidgetTitleBar_true.png)
The Advanced Docking System is meant for applications without a static central Unless a central widget explicitly has been set with setCentralWidget, the
widget and normally does not know anything about a central static widget. Advanced Docking System is without a static central widget and it wouldn't know
about a central static widget.
Therefore this flag is disabled by default and a central single dock widget Therefore this flag is disabled by default and a central single dock widget
still has a titlebar to drag it out of the main window. still has a titlebar to drag it out of the main window.
@@ -467,6 +478,24 @@ possible in various web browsers.
![MiddleMouseButtonClosesTab true](cfg_flag_MiddleMouseButtonClosesTab.gif) ![MiddleMouseButtonClosesTab true](cfg_flag_MiddleMouseButtonClosesTab.gif)
### `DisableTabTextEliding`
Set this flag to disable eliding of tab texts in dock area tabs:
![DisableTabTextEliding true](cfg_flag_DisableTabTextEliding_true.png)
The flag is disabled by default and the text in all tabs is elided to show as
many tabs as possible even if there is not much space:
![DisableTabTextEliding false](cfg_flag_DisableTabTextEliding_false.png)
### `ShowTabTextOnlyForActiveTab`
Set this flag (default = false) to show label texts in dock area tabs only
for active tabs. Inactive tabs only show their icon:
![MShowTabTextOnlyForActiveTab true](cfg_flag_ShowTabTextOnlyForActiveTab_true.png)
## Auto-Hide Configuration Flags ## Auto-Hide Configuration Flags
### Auto Hide Dock Widgets ### Auto Hide Dock Widgets
@@ -481,7 +510,7 @@ Enabling this feature adds a button with a pin icon to each dock area.
![DockAreaHasAutoHideButton true](cfg_flag_DockAreaHasAutoHideButton.png) ![DockAreaHasAutoHideButton true](cfg_flag_DockAreaHasAutoHideButton.png)
By clicking this button, the current dock widget (or the complete area - depending on the 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 configuration flags) will be pinned to a certain border. The border is chosen
depending on the location of the dock area. If you click the pin button while 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 holding down the **Ctrl** key, the whole dock area will be pinned to a certain
border. border.
@@ -503,6 +532,59 @@ 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 collapsed if the mouse cursor leaves the Auto-Hide widget. Showing and hiding
by mouse click still works if this feature is enabled. by mouse click still works if this feature is enabled.
### Drag & Drop to Auto-Hide
You can easily drag any dock widget or any floating widget to the
borders of a window to pin it as a auto-hide tab in one of the 4 sidebars.
If you drag a dock widget close the one of the four window borders, special
drop overlays will be shown to indicate the drop area for auto-hide widgets:
![Auo-Hide drag to Sidebar](AutoHide_Drag_to_Sidebar.gif)
Of course, this also works with dock areas:
![Auo-Hide drag Dock Area](AutoHide_Drag_DockArea.gif)
If you drag a dock widget or dock area into a sidebar, then you even have
control over where tabs are inserted. Simply drag your mouse over a specific
auto-hide tab, and your dragged dock widget will be inserted before this tab.
Drag to the sidebar area behind the last tab, and the dragged widget will be
appended as last tab. In the following screen capture, the **Image Viewer 1** will
be inserted before the **Table 0** Auto-Hide tab and the **Image Viewer 2**
is appended behind the last tab:
![Auo-Hide tab insert order](AutoHide_Tab_Insert_Order.gif)
### Auto-Hide Tab Insertion Order
It is also possible to drag Auto-Hide tabs to a new auto-hide position.
That means, you can drag them to a different border or sidebar:
![Auto-Hide change sidebar](AutoHide_Change_Sidebar.gif)
### Auto-Hide Tab Sorting
You can drag Auto-Hide tabs to a new position in the current sidebar
to sort them:
![Auo-Hide sort tabs](AutoHide_Sort_Tabs.gif)
### Auto-Hide Drag to Float / Dock
But that is not all. You can also simply move Auto-Hide tabs to another
floating widget or dock them via drag and drop:
![Auo-Hide drag to float or dock](AutoHide_Drag_to_Float_or_Dock.gif)
### Auto-Hide Context Menu
All Auto-Hide tabs now have a context menu, that provides all the functionality
that you know from Dock widget tabs. With the **Pin To...** item from the
context menu it is very easy to move an Auto-Hide tab to a different Auto-Hide
sidebar:
![Auo-Hide context menu](AutoHide_Context_Menu.png)
### Adding Auto Hide Widgets ### Adding Auto Hide Widgets
Adding an auto hide widget is similar to adding a dock widget, simply call Adding an auto hide widget is similar to adding a dock widget, simply call
@@ -605,6 +687,33 @@ closing it.
![AutoHideCloseButtonCollapsesDock true](cfg_flag_AutoHideCloseButtonCollapsesDock_true.gif) ![AutoHideCloseButtonCollapsesDock true](cfg_flag_AutoHideCloseButtonCollapsesDock_true.gif)
If you enable the `AutoHideHasMinimizeButton` flag, you should disable this
flag our you will have two buttons with minimize functionality.
### `AutoHideHasCloseButton`
If this flag is set (default), then each auto hide widget has a close button:
![AutoHideHasCloseButton](cfg_flag_AutoHideHasCloseButton.png)
The functionality of the close button (close or minimize) is configured by the
`AutoHideCloseButtonCollapsesDock` flag.
### `AutoHideHasMinimizeButton`
If this flag is set (disabled by default), then each auto hide widget has a minimize button.
![AutoHideHasMinimizeButton](cfg_flag_AutoHideHasMinimizeButton.png)
### `AutoHideOpenOnDragHover`
If this flag is set (disabled by default), then holding a dragging cursor hover an auto-hide collapsed dock's tab will open said dock:
![AutoHideOpenOnDragHover](cfg_flag_AutoHideOpenOnDragHover.gif)
Said dock must be set to accept drops to hide when cursor leaves its scope. See `AutoHideDragNDropExample` for more details.
## DockWidget Feature Flags ## DockWidget Feature Flags
### `DockWidgetClosable` ### `DockWidgetClosable`

View File

@@ -6,5 +6,6 @@ add_subdirectory(sidebar)
add_subdirectory(deleteonclose) add_subdirectory(deleteonclose)
add_subdirectory(centralwidget) add_subdirectory(centralwidget)
add_subdirectory(autohide) add_subdirectory(autohide)
add_subdirectory(autohidedragndrop)
add_subdirectory(emptydockarea) add_subdirectory(emptydockarea)
add_subdirectory(dockindock) add_subdirectory(dockindock)

View File

@@ -8,7 +8,7 @@ from PyQt5.QtWidgets import (QApplication, QLabel, QCalendarWidget, QFrame, QTre
QTableWidget, QFileSystemModel, QPlainTextEdit, QToolBar, QTableWidget, QFileSystemModel, QPlainTextEdit, QToolBar,
QWidgetAction, QComboBox, QAction, QSizePolicy, QInputDialog) QWidgetAction, QComboBox, QAction, QSizePolicy, QInputDialog)
from PyQtAds import QtAds import PyQtAds as QtAds
UI_FILE = os.path.join(os.path.dirname(__file__), 'mainwindow.ui') UI_FILE = os.path.join(os.path.dirname(__file__), 'mainwindow.ui')
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE) MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)

View File

@@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 3.5)
project(ads_example_autohide_dragndrop 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(AutoHideDragNDropExample WIN32
main.cpp
mainwindow.cpp
mainwindow.ui
droppableitem.cpp
)
target_include_directories(AutoHideDragNDropExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(AutoHideDragNDropExample PRIVATE qt${QT_VERSION_MAJOR}advanceddocking)
target_link_libraries(AutoHideDragNDropExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
set_target_properties(AutoHideDragNDropExample 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 With Drag N Drop 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,36 @@
ADS_OUT_ROOT = $${OUT_PWD}/../..
QT += core gui widgets
TARGET = AutoHideDragNDropExample
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 \
droppableitem.cpp
HEADERS += \
mainwindow.h \
droppableitem.h
FORMS += \
mainwindow.ui
LIBS += -L$${ADS_OUT_ROOT}/lib
include(../../ads.pri)
INCLUDEPATH += ../../src
DEPENDPATH += ../../src

View File

@@ -0,0 +1,38 @@
#include "droppableitem.h"
#include <QDragEnterEvent>
#include <QDragLeaveEvent>
#include <QDropEvent>
#include <QMimeData>
#include <qsizepolicy.h>
DroppableItem::DroppableItem(const QString& text, QWidget* parent)
: QPushButton(text, parent)
{
setAcceptDrops(true);
setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding);
}
void DroppableItem::dragEnterEvent(QDragEnterEvent* event)
{
if (event->mimeData()->hasText())
{
event->acceptProposedAction();
setCursor(Qt::DragMoveCursor);
}
}
void DroppableItem::dragLeaveEvent(QDragLeaveEvent* event)
{
Q_UNUSED(event);
unsetCursor();
}
void DroppableItem::dropEvent(QDropEvent* event)
{
if (event->mimeData()->hasText())
{
event->acceptProposedAction();
setText(event->mimeData()->text());
}
}

View File

@@ -0,0 +1,19 @@
#include <QObject>
#include <QPushButton>
class QDragEnterEvent;
class QDragLeaveEvent;
class QDropEvent;
class DroppableItem : public QPushButton
{
Q_OBJECT;
public:
DroppableItem(const QString& text = QString(), QWidget* parent = nullptr);
protected:
void dragEnterEvent(QDragEnterEvent* event) override;
void dragLeaveEvent(QDragLeaveEvent* event) override;
void dropEvent(QDropEvent* event) override;
};

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();
}

View File

@@ -0,0 +1,84 @@
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)
import PyQtAds as 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)
QtAds.CDockManager.setAutoHideConfigFlag(QtAds.CDockManager.AutoHideOpenOnDragHover, 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)
droppable_item = DroppableItem("Drop text here.")
drop_dock_widget = QtAds.CDockWidget("Tab")
drop_dock_widget.setWidget(droppable_item)
drop_dock_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget)
drop_dock_widget.setMinimumSize(200, 150)
drop_dock_widget.setAcceptDrops(True)
drop_area = self.dock_manager.addDockWidget(QtAds.DockWidgetArea.LeftDockWidgetArea, drop_dock_widget)
drop_area.setAcceptDrops(True)
self.menuView.addAction(drop_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,131 @@
#include "mainwindow.h"
#include "droppableitem.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);
CDockManager::setAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover, true);
CDockManager::setConfigParam(CDockManager::AutoHideOpenOnDragHoverDelay_ms, 500);
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);
{
DroppableItem* droppableItem = new DroppableItem("Drop text here.");
CDockWidget* dropDockWidget = new CDockWidget("Tab 1");
dropDockWidget->setWidget(droppableItem);
dropDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
dropDockWidget->setMinimumSize(200,150);
dropDockWidget->setAcceptDrops(true);
const auto autoHideContainer = DockManager->addAutoHideDockWidget(SideBarLocation::SideBarLeft, dropDockWidget);
autoHideContainer->setSize(480);
autoHideContainer->setAcceptDrops(true);
ui->menuView->addAction(dropDockWidget->toggleViewAction());
}
{
DroppableItem* droppableItem = new DroppableItem("Drop text here.");
CDockWidget* dropDockWidget = new CDockWidget("Tab 2");
dropDockWidget->setWidget(droppableItem);
dropDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
dropDockWidget->setMinimumSize(200,150);
dropDockWidget->setAcceptDrops(true);
const auto autoHideContainer = DockManager->addAutoHideDockWidget(SideBarLocation::SideBarRight, dropDockWidget);
autoHideContainer->setSize(480);
autoHideContainer->setAcceptDrops(true);
ui->menuView->addAction(dropDockWidget->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

@@ -8,7 +8,7 @@ from PyQt5.QtWidgets import (QApplication, QLabel, QCalendarWidget, QFrame, QTre
QTableWidget, QFileSystemModel, QPlainTextEdit, QToolBar, QTableWidget, QFileSystemModel, QPlainTextEdit, QToolBar,
QWidgetAction, QComboBox, QAction, QSizePolicy, QInputDialog) QWidgetAction, QComboBox, QAction, QSizePolicy, QInputDialog)
from PyQtAds import QtAds import PyQtAds as QtAds
UI_FILE = os.path.join(os.path.dirname(__file__), 'mainwindow.ui') UI_FILE = os.path.join(os.path.dirname(__file__), 'mainwindow.ui')
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE) MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)

View File

@@ -0,0 +1,28 @@
cmake_minimum_required(VERSION 3.5)
project(ads_example_centralwidget 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(configFlagsExample WIN32
main.cpp
mainwindow.cpp
mainwindow.ui
)
target_include_directories(CentralWidgetExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(CentralWidgetExample PRIVATE qt${QT_VERSION_MAJOR}advanceddocking)
target_link_libraries(CentralWidgetExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
set_target_properties(CentralWidgetExample 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 Central Widget 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 = ConfigFlagsExample
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();
}

View File

@@ -0,0 +1,65 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QLabel>
#include <QToolBar>
#include "DockAreaWidget.h"
#include "DockAreaTitleBar.h"
using namespace ads;
CMainWindow::CMainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::CMainWindow)
{
ui->setupUi(this);
// Add the toolbar
auto toolbar_ = addToolBar("Top Toolbar");
// Create the dock manager
ads::CDockManager::setConfigFlags(ads::CDockManager::DefaultOpaqueConfig);
ads::CDockManager::setConfigFlag(ads::CDockManager::DockAreaHasCloseButton,
false);
ads::CDockManager::setConfigFlag(ads::CDockManager::DockAreaHasUndockButton,
false);
ads::CDockManager::setConfigFlag(
ads::CDockManager::DockAreaHasTabsMenuButton, false);
auto DockManager = new ads::CDockManager(this);
// Create a dockable widget
QLabel *l1 = new QLabel();
l1->setWordWrap(true);
l1->setAlignment(Qt::AlignTop | Qt::AlignLeft);
l1->setText("Docking widget 1");
ads::CDockWidget *dockWidget1 = new ads::CDockWidget("Dock 1");
dockWidget1->setWidget(l1);
DockManager->addDockWidget(ads::LeftDockWidgetArea, dockWidget1);
QLabel *l2 = new QLabel();
l2->setWordWrap(true);
l2->setAlignment(Qt::AlignTop | Qt::AlignLeft);
l2->setText("Docking widget 2");
ads::CDockWidget *dockWidget2 = new ads::CDockWidget("Dock 2");
dockWidget2->setWidget(l2);
DockManager->addDockWidget(ads::RightDockWidgetArea, dockWidget2);
// Add menu actions
ui->menuView->addAction(dockWidget1->toggleViewAction());
ui->menuView->addAction(dockWidget2->toggleViewAction());
toolbar_->addAction(dockWidget1->toggleViewAction());
toolbar_->addAction(dockWidget2->toggleViewAction());
}
CMainWindow::~CMainWindow()
{
delete ui;
}

View File

@@ -0,0 +1,27 @@
#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();
private:
Ui::CMainWindow *ui;
};
#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

@@ -1,6 +1,6 @@
import sys import sys
from PyQtAds import QtAds import PyQtAds as QtAds
from PyQt5.QtGui import QCloseEvent from PyQt5.QtGui import QCloseEvent
from PyQt5.QtCore import (qDebug, pyqtSlot, QObject, pyqtSignal) from PyQt5.QtCore import (qDebug, pyqtSlot, QObject, pyqtSignal)
from PyQt5.QtWidgets import (QMainWindow, QAction, QTextEdit, QApplication, from PyQt5.QtWidgets import (QMainWindow, QAction, QTextEdit, QApplication,

View File

@@ -3,7 +3,7 @@ import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QMessageBox, from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QMessageBox,
QInputDialog, QMenu, QLineEdit) QInputDialog, QMenu, QLineEdit)
from PyQt5.QtGui import QIcon from PyQt5.QtGui import QIcon
from PyQtAds import QtAds import PyQtAds as QtAds
from dockindockmanager import DockInDockManager from dockindockmanager import DockInDockManager
from perspectiveactions import LoadPerspectiveAction, RemovePerspectiveAction from perspectiveactions import LoadPerspectiveAction, RemovePerspectiveAction

View File

@@ -1,7 +1,7 @@
from PyQt5.QtWidgets import QAction, QMenu, QInputDialog, QLineEdit from PyQt5.QtWidgets import QAction, QMenu, QInputDialog, QLineEdit
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from PyQtAds import QtAds import PyQtAds as QtAds
CHILD_PREFIX = "Child-" CHILD_PREFIX = "Child-"

View File

@@ -1,5 +1,5 @@
#include <QApplication> #include <QApplication>
#include "../../examples/simple/MainWindow.h" #include "mainframe.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {

View File

@@ -4,7 +4,7 @@ import atexit
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQtAds import QtAds import PyQtAds as QtAds
from perspectives import PerspectivesManager from perspectives import PerspectivesManager
from dockindock import DockInDockWidget from dockindock import DockInDockWidget

View File

@@ -4,7 +4,7 @@ import shutil
import atexit import atexit
from PyQt5.QtCore import pyqtSignal, QSettings, QObject from PyQt5.QtCore import pyqtSignal, QSettings, QObject
from PyQtAds import QtAds import PyQtAds as QtAds
from dockindockmanager import DockInDockManager from dockindockmanager import DockInDockManager
from dockindock import DockInDockWidget from dockindock import DockInDockWidget

View File

@@ -6,7 +6,7 @@ from PyQt5.QtCore import Qt, QSignalBlocker
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QComboBox, QTableWidget, from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QComboBox, QTableWidget,
QAction, QWidgetAction, QSizePolicy, QInputDialog) QAction, QWidgetAction, QSizePolicy, QInputDialog)
from PyQt5.QtGui import QCloseEvent from PyQt5.QtGui import QCloseEvent
from PyQtAds import QtAds import PyQtAds as QtAds
UI_FILE = os.path.join(os.path.dirname(__file__), 'mainwindow.ui') UI_FILE = os.path.join(os.path.dirname(__file__), 'mainwindow.ui')

View File

@@ -2,10 +2,12 @@ TEMPLATE = subdirs
SUBDIRS = \ SUBDIRS = \
autohide \ autohide \
autohidedragndrop \
centralwidget \ centralwidget \
simple \ simple \
hideshow \ hideshow \
sidebar \ sidebar \
deleteonclose \ deleteonclose \
emptydockarea \ emptydockarea \
dockindock dockindock \
configflags

View File

@@ -5,7 +5,7 @@ from PyQt5 import uic
from PyQt5.QtCore import Qt, QMargins from PyQt5.QtCore import Qt, QMargins
from PyQt5.QtWidgets import QApplication, QLabel, QVBoxLayout, QPlainTextEdit from PyQt5.QtWidgets import QApplication, QLabel, QVBoxLayout, QPlainTextEdit
from PyQtAds import QtAds import PyQtAds as QtAds
UI_FILE = os.path.join(os.path.dirname(__file__), 'MainWindow.ui') UI_FILE = os.path.join(os.path.dirname(__file__), 'MainWindow.ui')
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE) MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)

View File

@@ -6,7 +6,7 @@ from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QCloseEvent from PyQt5.QtGui import QCloseEvent
from PyQt5.QtWidgets import QApplication, QLabel from PyQt5.QtWidgets import QApplication, QLabel
from PyQtAds import QtAds import PyQtAds as QtAds
UI_FILE = os.path.join(os.path.dirname(__file__), 'MainWindow.ui') UI_FILE = os.path.join(os.path.dirname(__file__), 'MainWindow.ui')
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE) MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)

View File

@@ -1,12 +1,12 @@
# Specify the build system. # Specify the build system.
[build-system] [build-system]
requires = ["sip >=6.0.2, <6.3", "PyQt-builder >=1.6, <2", "PyQt5==5.15.4", "PyQt5-sip<13,>=12.8"] requires = ["sip >=6.0.2", "PyQt-builder >=1.6", "PyQt5>=5.15", "PyQt5-sip>=12.8"]
build-backend = "sipbuild.api" build-backend = "sipbuild.api"
# Specify the PEP 566 metadata for the project. # Specify the PEP 566 metadata for the project.
[tool.sip.metadata] [tool.sip.metadata]
name = "PyQtAds" name = "PyQtAds"
version = "4.0.2" version = "4.4.1"
summary = "Python bindings for Qt Advanced Docking System" summary = "Python bindings for Qt Advanced Docking System"
home-page = "https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/" home-page = "https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/"
license = "LGPL v2.1" license = "LGPL v2.1"
@@ -16,8 +16,10 @@ description-content-type = "text/markdown"
[tool.sip.project] [tool.sip.project]
tag-prefix = "QtAds" tag-prefix = "QtAds"
dunder-init = true
[tool.sip.bindings.ads] [tool.sip.bindings.ads]
pep484-pyi = true
define-macros = ["ADS_SHARED_EXPORT"] define-macros = ["ADS_SHARED_EXPORT"]
sip-file = "ads.sip" sip-file = "ads.sip"
include-dirs = ["src"] include-dirs = ["src"]

View File

@@ -24,9 +24,10 @@ public:
CAutoHideDockContainer(ads::CDockWidget* DockWidget /Transfer/, ads::SideBarLocation area, CAutoHideDockContainer(ads::CDockWidget* DockWidget /Transfer/, ads::SideBarLocation area,
ads::CDockContainerWidget* parent /TransferThis/); ads::CDockContainerWidget* parent /TransferThis/);
virtual ~CAutoHideDockContainer(); virtual ~CAutoHideDockContainer();
ads::CAutoHideSideBar* sideBar() const; ads::CAutoHideSideBar* autoHideSideBar() const;
ads::CAutoHideTab* autoHideTab() const; ads::CAutoHideTab* autoHideTab() const;
ads::CDockWidget* dockWidget() const; ads::CDockWidget* dockWidget() const;
int tabIndex() const;
void addDockWidget(ads::CDockWidget* DockWidget /Transfer/); void addDockWidget(ads::CDockWidget* DockWidget /Transfer/);
ads::SideBarLocation sideBarLocation() const; ads::SideBarLocation sideBarLocation() const;
void setSideBarLocation(ads::SideBarLocation SideBarLocation); void setSideBarLocation(ads::SideBarLocation SideBarLocation);
@@ -38,7 +39,9 @@ public:
void collapseView(bool Enable); void collapseView(bool Enable);
void toggleCollapseState(); void toggleCollapseState();
void setSize(int Size); void setSize(int Size);
void resetToInitialDockWidgetSize();
Qt::Orientation orientation() const;
void moveToNewSideBarLocation(ads::SideBarLocation);
}; };
}; };

View File

@@ -24,10 +24,15 @@ public:
void removeTab(ads::CAutoHideTab* SideTab) /TransferBack/; void removeTab(ads::CAutoHideTab* SideTab) /TransferBack/;
ads::CAutoHideDockContainer* insertDockWidget(int Index, ads::CDockWidget* DockWidget /Transfer/); ads::CAutoHideDockContainer* insertDockWidget(int Index, ads::CDockWidget* DockWidget /Transfer/);
void removeAutoHideWidget(ads::CAutoHideDockContainer* AutoHideWidget) /TransferBack/; void removeAutoHideWidget(ads::CAutoHideDockContainer* AutoHideWidget) /TransferBack/;
void addAutoHideWidget(ads::CAutoHideDockContainer* AutoHideWidget); void addAutoHideWidget(ads::CAutoHideDockContainer* AutoHideWidget, int Index);
Qt::Orientation orientation() const; Qt::Orientation orientation() const;
ads::CAutoHideTab* tabAt(int index) const; ads::CAutoHideTab* tab(int index) const;
int tabCount() const; int tabAt(const QPoint& Pos) const;
int tabInsertIndexAt(const QPoint& Pos) const;
int indexOfTab(const CAutoHideTab& Tab) const;
int count() const;
int visibleTabCount() const;
bool hasVisibleTabs() const;
ads::SideBarLocation sideBarLocation() const; ads::SideBarLocation sideBarLocation() const;
virtual QSize minimumSizeHint() const; virtual QSize minimumSizeHint() const;
virtual QSize sizeHint() const; virtual QSize sizeHint() const;

View File

@@ -16,6 +16,10 @@ protected:
void setSideBar(ads::CAutoHideSideBar *SideTabBar); void setSideBar(ads::CAutoHideSideBar *SideTabBar);
void removeFromSideBar(); void removeFromSideBar();
virtual bool event(QEvent* event); virtual bool event(QEvent* event);
virtual void contextMenuEvent(QContextMenuEvent* ev);
virtual void mousePressEvent(QMouseEvent* ev);
virtual void mouseReleaseEvent(QMouseEvent* ev);
virtual void mouseMoveEvent(QMouseEvent* ev);
public: public:
CAutoHideTab(QWidget* parent /TransferThis/ = 0); CAutoHideTab(QWidget* parent /TransferThis/ = 0);
@@ -29,6 +33,10 @@ public:
void setDockWidget(ads::CDockWidget* DockWidget); void setDockWidget(ads::CDockWidget* DockWidget);
bool iconOnly() const; bool iconOnly() const;
ads::CAutoHideSideBar* sideBar() const; ads::CAutoHideSideBar* sideBar() const;
int tabIndex() const;
void setDockWidgetFloating();
void unpinDockWidget();
void requestCloseDockWidget();
}; };
}; };

View File

@@ -23,6 +23,8 @@ public:
int currentIndex() const; int currentIndex() const;
ads::CDockWidgetTab* currentTab() const; ads::CDockWidgetTab* currentTab() const;
ads::CDockWidgetTab* tab(int Index) const; ads::CDockWidgetTab* tab(int Index) const;
int tabAt(const QPoint& Pos) const;
int tabInsertIndexAt(const QPoint& Pos) const;
virtual bool eventFilter(QObject *watched, QEvent *event); virtual bool eventFilter(QObject *watched, QEvent *event);
bool isTabOpen(int Index) const; bool isTabOpen(int Index) const;
virtual QSize minimumSizeHint() const; virtual QSize minimumSizeHint() const;

View File

@@ -5,6 +5,26 @@
namespace ads namespace ads
{ {
class CTitleBarButton : QToolButton
{
%TypeHeaderCode
#include <DockAreaTitleBar.h>
%End
public:
CTitleBarButton(bool ShowInTitleBar, bool HideWhenDisabled, TitleBarButton ButtonId,
QWidget* /TransferThis/ = Q_NULLPTR );
virtual void setVisible(bool);
void setShowInTitleBar(bool);
TitleBarButton buttonId() const;
ads::CDockAreaTitleBar* titleBar() const;
bool isInAutoHideArea() const;
protected:
bool event(QEvent *ev);
};
class CDockAreaTitleBar : QFrame class CDockAreaTitleBar : QFrame
{ {
%TypeHeaderCode %TypeHeaderCode
@@ -26,14 +46,17 @@ public:
CDockAreaTitleBar(ads::CDockAreaWidget* parent /TransferThis/); CDockAreaTitleBar(ads::CDockAreaWidget* parent /TransferThis/);
virtual ~CDockAreaTitleBar(); virtual ~CDockAreaTitleBar();
ads::CDockAreaTabBar* tabBar() const; ads::CDockAreaTabBar* tabBar() const;
QAbstractButton* button(ads::TitleBarButton which) const; ads::CTitleBarButton* button(ads::TitleBarButton which) const;
ads::CElidingLabel* autoHideTitleLabel() const; ads::CElidingLabel* autoHideTitleLabel() const;
ads::CDockAreaWidget* dockAreaWidget() const;
void updateDockWidgetActionsButtons(); void updateDockWidgetActionsButtons();
virtual void setVisible(bool Visible); virtual void setVisible(bool Visible);
void insertWidget(int index, QWidget *widget /Transfer/ ); void insertWidget(int index, QWidget *widget /Transfer/ );
int indexOf(QWidget *widget) const; int indexOf(QWidget *widget) const;
QString titleBarButtonToolTip(ads::TitleBarButton Button) const; QString titleBarButtonToolTip(ads::TitleBarButton Button) const;
void setAreaFloating();
void showAutoHideControls(bool Show);
bool isAutoHide() const;
signals: signals:
void tabBarClicked(int index); void tabBarClicked(int index);

View File

@@ -5,21 +5,6 @@
namespace ads namespace ads
{ {
class CTitleBarButton : QToolButton
{
%TypeHeaderCode
#include <DockAreaTitleBar_p.h>
%End
protected:
bool event(QEvent *ev);
public:
CTitleBarButton(bool visible = true, QWidget* parent /TransferThis/ = Q_NULLPTR );
virtual void setVisible(bool visible);
};
class CSpacerWidget : QWidget class CSpacerWidget : QWidget
{ {
%TypeHeaderCode %TypeHeaderCode

View File

@@ -40,6 +40,10 @@ public:
virtual ~CDockAreaWidget(); virtual ~CDockAreaWidget();
ads::CDockManager* dockManager() const; ads::CDockManager* dockManager() const;
ads::CDockContainerWidget* dockContainer() const; ads::CDockContainerWidget* dockContainer() const;
ads::CAutoHideDockContainer* autoHideDockContainer() const;
ads::CDockSplitter* parentSplitter() const;
bool isAutoHide() const;
void setAutoHideDockContainer(CAutoHideDockContainer*);
virtual QSize minimumSizeHint() const; virtual QSize minimumSizeHint() const;
QRect titleBarGeometry() const; QRect titleBarGeometry() const;
QRect contentAreaGeometry() const; QRect contentAreaGeometry() const;
@@ -74,7 +78,10 @@ public:
public slots: public slots:
void setCurrentIndex(int index); void setCurrentIndex(int index);
void closeArea(); void closeArea();
void setAutoHide(bool Enable, SideBarLocation Location = ads::SideBarNone, int TabIndex = -1);
void toggleAutoHide(SideBarLocation Location = ads::SideBarNone);
void closeOtherAreas(); void closeOtherAreas();
void setFloating();
signals: signals:
void tabBarClicked(int index); void tabBarClicked(int index);

View File

@@ -9,8 +9,8 @@ namespace ads
* Container that manages a number of dock areas with single dock widgets * Container that manages a number of dock areas with single dock widgets
* or tabyfied dock widgets in each area. * or tabyfied dock widgets in each area.
* Each window that support docking has a DockContainerWidget. That means * Each window that support docking has a DockContainerWidget. That means
* the main application window and all floating windows are ore contain * the main application window and all floating windows contain a
* an DockContainerWidget. * DockContainerWidget.
*/ */
class CDockContainerWidget : QFrame class CDockContainerWidget : QFrame
{ {
@@ -20,13 +20,14 @@ class CDockContainerWidget : QFrame
protected: protected:
virtual bool event(QEvent *e); virtual bool event(QEvent *e);
QSplitter* rootSplitter() const; ads::CDockSplitter* rootSplitter() const;
ads::CAutoHideDockContainer* createAndSetupAutoHideContainer(ads::SideBarLocation area, ads::CDockWidget* DockWidget /Transfer/); ads::CAutoHideDockContainer* createAndSetupAutoHideContainer(ads::SideBarLocation area, ads::CDockWidget* DockWidget /Transfer/, int TabIndex = -1);
void createRootSplitter(); void createRootSplitter();
void dropFloatingWidget(ads::CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos); void dropFloatingWidget(ads::CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos);
void dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget); void dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget, int TabIndex = -1);
void addDockArea(ads::CDockAreaWidget* DockAreaWidget /Transfer/, ads::DockWidgetArea area = ads::CenterDockWidgetArea); void addDockArea(ads::CDockAreaWidget* DockAreaWidget /Transfer/, ads::DockWidgetArea area = ads::CenterDockWidgetArea);
void removeDockArea(ads::CDockAreaWidget* area /TransferBack/); void removeDockArea(ads::CDockAreaWidget* area /TransferBack/);
/*QList<QPointer<ads::CDockAreaWidget>> removeAllDockAreas();*/
void saveState(QXmlStreamWriter& Stream) const; void saveState(QXmlStreamWriter& Stream) const;
bool restoreState(CDockingStateReader& Stream, bool Testing); bool restoreState(CDockingStateReader& Stream, bool Testing);
ads::CDockAreaWidget* lastAddedDockAreaWidget(ads::DockWidgetArea area) const; ads::CDockAreaWidget* lastAddedDockAreaWidget(ads::DockWidgetArea area) const;
@@ -59,7 +60,7 @@ public:
ads::CDockWidget::DockWidgetFeatures features() const; ads::CDockWidget::DockWidgetFeatures features() const;
ads::CFloatingDockContainer* floatingWidget() const; ads::CFloatingDockContainer* floatingWidget() const;
void closeOtherAreas(ads::CDockAreaWidget* KeepOpenArea); void closeOtherAreas(ads::CDockAreaWidget* KeepOpenArea);
ads::CAutoHideSideBar* sideTabBar(SideBarLocation area) const; ads::CAutoHideSideBar* autoHideSideBar(SideBarLocation area) const;
QList<ads::CAutoHideDockContainer*> autoHideWidgets() const; QList<ads::CAutoHideDockContainer*> autoHideWidgets() const;
QRect contentRect() const; QRect contentRect() const;
QRect contentRectGlobal() const; QRect contentRectGlobal() const;

View File

@@ -23,6 +23,7 @@ public:
ads::CDockWidget* focusedDockWidget() const; ads::CDockWidget* focusedDockWidget() const;
void setDockWidgetTabFocused(ads::CDockWidgetTab* Tab); void setDockWidgetTabFocused(ads::CDockWidgetTab* Tab);
void clearDockWidgetFocus(ads::CDockWidget* dockWidget); void clearDockWidgetFocus(ads::CDockWidget* dockWidget);
void setDockWidgetTabPressed(bool Value);
public slots: public slots:
void setDockWidgetFocused(ads::CDockWidget* focusedNow); void setDockWidgetFocused(ads::CDockWidget* focusedNow);

View File

@@ -172,6 +172,8 @@ public:
FloatingContainerForceNativeTitleBar, FloatingContainerForceNativeTitleBar,
FloatingContainerForceQWidgetTitleBar, FloatingContainerForceQWidgetTitleBar,
MiddleMouseButtonClosesTab, MiddleMouseButtonClosesTab,
DisableTabTextEliding,
ShowTabTextOnlyForActiveTab,
DefaultDockAreaButtons, DefaultDockAreaButtons,
DefaultBaseConfig, DefaultBaseConfig,
DefaultOpaqueConfig, DefaultOpaqueConfig,
@@ -187,6 +189,9 @@ public:
AutoHideButtonCheckable, AutoHideButtonCheckable,
AutoHideSideBarsIconOnly, AutoHideSideBarsIconOnly,
AutoHideShowOnMouseOver, AutoHideShowOnMouseOver,
AutoHideCloseButtonCollapsesDock,
AutoHideHasCloseButton,
AutoHideHasMinimizeButton,
DefaultAutoHideConfig, DefaultAutoHideConfig,
}; };
typedef QFlags<ads::CDockManager::eAutoHideFlag> AutoHideFlags; typedef QFlags<ads::CDockManager::eAutoHideFlag> AutoHideFlags;
@@ -237,14 +242,22 @@ public:
QMenu* viewMenu() const; QMenu* viewMenu() const;
void setViewMenuInsertionOrder(ads::CDockManager::eViewMenuInsertionOrder Order); void setViewMenuInsertionOrder(ads::CDockManager::eViewMenuInsertionOrder Order);
bool isRestoringState() const; bool isRestoringState() const;
bool isLeavingMinimizedState() const;
static int startDragDistance(); static int startDragDistance();
ads::CDockWidget* focusedDockWidget() const; ads::CDockWidget* focusedDockWidget() const;
QList<int> splitterSizes(ads::CDockAreaWidget *ContainedArea) const; QList<int> splitterSizes(ads::CDockAreaWidget *ContainedArea) const;
void setSplitterSizes(ads::CDockAreaWidget *ContainedArea, const QList<int>& sizes); void setSplitterSizes(ads::CDockAreaWidget *ContainedArea, const QList<int>& sizes);
static void setFloatingContainersTitle(const QString& Title); static void setFloatingContainersTitle(const QString& Title);
static QString floatingContainersTitle(); static QString floatingContainersTitle();
void setDockWidgetToolBarStyle(Qt::ToolButtonStyle Style, ads::CDockWidget::eState State);
Qt::ToolButtonStyle dockWidgetToolBarStyle(ads::CDockWidget::eState State) const;
void setDockWidgetToolBarIconSize(const QSize& IconSize, ads::CDockWidget::eState State);
QSize dockWidgetToolBarIconSize(ads::CDockWidget::eState State) const;
ads::CDockWidget::DockWidgetFeatures globallyLockedDockWidgetFeatures() const;
void lockDockWidgetFeaturesGlobally(ads::CDockWidget::DockWidgetFeatures Features = ads::CDockWidget::GloballyLockableFeatures);
public slots: public slots:
void endLeavingMinimizedState();
void openPerspective(const QString& PerspectiveName); void openPerspective(const QString& PerspectiveName);
void setDockWidgetFocused(ads::CDockWidget* DockWidget); void setDockWidgetFocused(ads::CDockWidget* DockWidget);

View File

@@ -22,8 +22,10 @@ public:
CDockOverlay(QWidget* parent /TransferThis/, eMode Mode = ads::CDockOverlay::ModeDockAreaOverlay); CDockOverlay(QWidget* parent /TransferThis/, eMode Mode = ads::CDockOverlay::ModeDockAreaOverlay);
virtual ~CDockOverlay(); virtual ~CDockOverlay();
void setAllowedAreas(ads::DockWidgetAreas areas); void setAllowedAreas(ads::DockWidgetAreas areas);
void setAllowedArea(ads::DockWidgetArea area, bool Enable);
ads::DockWidgetAreas allowedAreas() const; ads::DockWidgetAreas allowedAreas() const;
ads::DockWidgetArea dropAreaUnderCursor() const; ads::DockWidgetArea dropAreaUnderCursor() const;
int tabIndexUnderCursor() const;
ads::DockWidgetArea visibleDropAreaUnderCursor() const; ads::DockWidgetArea visibleDropAreaUnderCursor() const;
ads::DockWidgetArea showOverlay(QWidget* target); ads::DockWidgetArea showOverlay(QWidget* target);
void hideOverlay(); void hideOverlay();

View File

@@ -39,6 +39,7 @@ public:
DefaultDockWidgetFeatures, DefaultDockWidgetFeatures,
AllDockWidgetFeatures, AllDockWidgetFeatures,
DockWidgetAlwaysCloseAndDelete, DockWidgetAlwaysCloseAndDelete,
GloballyLockableFeatures,
NoDockWidgetFeatures NoDockWidgetFeatures
}; };
typedef QFlags<ads::CDockWidget::DockWidgetFeature> DockWidgetFeatures; typedef QFlags<ads::CDockWidget::DockWidgetFeature> DockWidgetFeatures;
@@ -50,6 +51,12 @@ public:
StateFloating StateFloating
}; };
enum eToolBarStyleSource
{
ToolBarStyleFromDockManager,
ToolBarStyleFromDockWidget
};
enum eInsertMode enum eInsertMode
{ {
AutoScrollArea, AutoScrollArea,
@@ -60,7 +67,9 @@ public:
enum eMinimumSizeHintMode enum eMinimumSizeHintMode
{ {
MinimumSizeHintFromDockWidget, MinimumSizeHintFromDockWidget,
MinimumSizeHintFromContent MinimumSizeHintFromContent,
MinimumSizeHintFromDockWidgetMinimumSize,
MinimumSizeHintFromContentMinimumSize,
}; };
enum eToggleViewActionMode enum eToggleViewActionMode
@@ -70,7 +79,7 @@ public:
}; };
CDockWidget(const QString &title, QWidget* parent /TransferThis/ = 0); CDockWidget(const QString &title, QWidget* parent /TransferThis/ = Q_NULLPTR);
virtual ~CDockWidget(); virtual ~CDockWidget();
virtual QSize minimumSizeHint() const; virtual QSize minimumSizeHint() const;
void setWidget(QWidget* widget /Transfer/, ads::CDockWidget::eInsertMode InsertMode = AutoScrollArea); void setWidget(QWidget* widget /Transfer/, ads::CDockWidget::eInsertMode InsertMode = AutoScrollArea);
@@ -80,6 +89,7 @@ public:
void setFeatures(ads::CDockWidget::DockWidgetFeatures features); void setFeatures(ads::CDockWidget::DockWidgetFeatures features);
void setFeature(ads::CDockWidget::DockWidgetFeature flag, bool on); void setFeature(ads::CDockWidget::DockWidgetFeature flag, bool on);
ads::CDockWidget::DockWidgetFeatures features() const; ads::CDockWidget::DockWidgetFeatures features() const;
void notifyFeaturesChanged();
ads::CDockManager* dockManager() const; ads::CDockManager* dockManager() const;
ads::CDockContainerWidget* dockContainer() const; ads::CDockContainerWidget* dockContainer() const;
ads::CFloatingDockContainer* floatingDockContainer() const; ads::CFloatingDockContainer* floatingDockContainer() const;
@@ -88,18 +98,23 @@ public:
void setSideTabWidget(ads::CAutoHideTab* SideTab /Transfer/) const; void setSideTabWidget(ads::CAutoHideTab* SideTab /Transfer/) const;
bool isAutoHide() const; bool isAutoHide() const;
ads::CAutoHideDockContainer* autoHideDockContainer() const; ads::CAutoHideDockContainer* autoHideDockContainer() const;
ads::SideBarLocation autoHideLocation() const;
bool isFloating() const; bool isFloating() const;
bool isInFloatingContainer() const; bool isInFloatingContainer() const;
bool isClosed() const; bool isClosed() const;
QAction* toggleViewAction() const; QAction* toggleViewAction() const;
void setToggleViewAction(QAction* action);
void setToggleViewActionMode(ads::CDockWidget::eToggleViewActionMode Mode); void setToggleViewActionMode(ads::CDockWidget::eToggleViewActionMode Mode);
void setMinimumSizeHintMode(ads::CDockWidget::eMinimumSizeHintMode Mode); void setMinimumSizeHintMode(ads::CDockWidget::eMinimumSizeHintMode Mode);
ads::CDockWidget::eMinimumSizeHintMode minimumSizeHintMode() const;
bool isCentralWidget() const; bool isCentralWidget() const;
void setIcon(const QIcon& Icon); void setIcon(const QIcon& Icon);
QIcon icon() const; QIcon icon() const;
QToolBar* toolBar() const; QToolBar* toolBar() const;
QToolBar* createDefaultToolBar(); QToolBar* createDefaultToolBar();
void setToolBar(QToolBar* ToolBar /Transfer/ ); void setToolBar(QToolBar* ToolBar /Transfer/ );
void setToolBarStyleSource(ads::CDockWidget::eToolBarStyleSource Source);
ads::CDockWidget::eToolBarStyleSource toolBarStyleSource() const;
void setToolBarStyle(Qt::ToolButtonStyle Style, ads::CDockWidget::eState State); void setToolBarStyle(Qt::ToolButtonStyle Style, ads::CDockWidget::eState State);
Qt::ToolButtonStyle toolBarStyle(ads::CDockWidget::eState State) const; Qt::ToolButtonStyle toolBarStyle(ads::CDockWidget::eState State) const;
void setToolBarIconSize(const QSize& IconSize, ads::CDockWidget::eState State); void setToolBarIconSize(const QSize& IconSize, ads::CDockWidget::eState State);
@@ -122,9 +137,10 @@ public slots:
void setFloating(); void setFloating();
void deleteDockWidget(); void deleteDockWidget();
void closeDockWidget(); void closeDockWidget();
void requestCloseDockWidget();
void showFullScreen(); void showFullScreen();
void showNormal(); void showNormal();
void setAutoHide(bool Enable, ads::SideBarLocation Location = ads::SideBarNone); void setAutoHide(bool Enable, ads::SideBarLocation Location = ads::SideBarNone, int TabIndex = -1);
void toggleAutoHide(ads::SideBarLocation Location = ads::SideBarNone); void toggleAutoHide(ads::SideBarLocation Location = ads::SideBarNone);
signals: signals:

View File

@@ -17,8 +17,8 @@ protected:
virtual void mouseDoubleClickEvent( QMouseEvent *ev ); virtual void mouseDoubleClickEvent( QMouseEvent *ev );
public: public:
CElidingLabel(QWidget* parent /TransferThis/ = 0, Qt::WindowFlags f = 0); CElidingLabel(QWidget* parent /TransferThis/ = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags ());
CElidingLabel(const QString& text, QWidget* parent /TransferThis/ = 0, Qt::WindowFlags f = 0); CElidingLabel(const QString& text, QWidget* parent /TransferThis/ = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags ());
virtual ~CElidingLabel(); virtual ~CElidingLabel();
Qt::TextElideMode elideMode() const; Qt::TextElideMode elideMode() const;
void setElideMode(Qt::TextElideMode mode); void setElideMode(Qt::TextElideMode mode);

View File

@@ -44,6 +44,7 @@ protected:
void startDragging(const QPoint& DragStartMousePos, const QSize& Size, void startDragging(const QPoint& DragStartMousePos, const QSize& Size,
QWidget* MouseEventHandler); QWidget* MouseEventHandler);
virtual void finishDragging(); virtual void finishDragging();
void deleteContent();
void initFloatingGeometry(const QPoint& DragStartMousePos, const QSize& Size); void initFloatingGeometry(const QPoint& DragStartMousePos, const QSize& Size);
void moveFloating(); void moveFloating();
bool restoreState(ads::CDockingStateReader& Stream, bool Testing); bool restoreState(ads::CDockingStateReader& Stream, bool Testing);
@@ -82,6 +83,7 @@ public:
bool hasTopLevelDockWidget() const; bool hasTopLevelDockWidget() const;
ads::CDockWidget* topLevelDockWidget() const; ads::CDockWidget* topLevelDockWidget() const;
QList<ads::CDockWidget*> dockWidgets() const; QList<ads::CDockWidget*> dockWidgets() const;
void finishDropOperation();
%If (WS_X11) %If (WS_X11)
void onMaximizeRequest(); void onMaximizeRequest();

View File

@@ -29,7 +29,7 @@ public: // implements IFloatingWidget
ads::eDragState DragState, QWidget* MouseEventHandler); ads::eDragState DragState, QWidget* MouseEventHandler);
virtual void moveFloating(); virtual void moveFloating();
virtual void finishDragging(); virtual void finishDragging();
void cleanupAutoHideContainerWidget(); void cleanupAutoHideContainerWidget(ads::DockWidgetArea ContainerDropArea);
signals: signals:
void draggingCanceled(); void draggingCanceled();

View File

@@ -1,4 +1,6 @@
%Module(name=PyQtAds, 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)
%HideNamespace(name=ads)
%Import QtCore/QtCoremod.sip %Import QtCore/QtCoremod.sip
%DefaultSupertype sip.simplewrapper %DefaultSupertype sip.simplewrapper

View File

@@ -50,19 +50,31 @@ namespace ads
TopDockWidgetArea, TopDockWidgetArea,
BottomDockWidgetArea, BottomDockWidgetArea,
CenterDockWidgetArea, CenterDockWidgetArea,
LeftAutoHideArea,
RightAutoHideArea,
TopAutoHideArea,
BottomAutoHideArea,
InvalidDockWidgetArea, InvalidDockWidgetArea,
OuterDockAreas, OuterDockAreas,
AutoHideDockAreas,
AllDockAreas AllDockAreas
}; };
typedef QFlags<ads::DockWidgetArea> DockWidgetAreas; typedef QFlags<ads::DockWidgetArea> DockWidgetAreas;
enum eTabIndex
{
TabDefaultInsertIndex,
TabInvalidIndex
};
enum TitleBarButton enum TitleBarButton
{ {
TitleBarButtonTabsMenu, TitleBarButtonTabsMenu,
TitleBarButtonUndock, TitleBarButtonUndock,
TitleBarButtonClose, TitleBarButtonClose,
TitleBarButtonAutoHide TitleBarButtonAutoHide,
TitleBarButtonMinimize
}; };
enum eDragState enum eDragState
@@ -115,6 +127,9 @@ namespace ads
int insertOffset() const; int insertOffset() const;
}; };
ads::internal::CDockInsertParam dockAreaInsertParameters(ads::DockWidgetArea Area); ads::internal::CDockInsertParam dockAreaInsertParameters(ads::DockWidgetArea Area);
ads::SideBarLocation toSideBarLocation(ads::DockWidgetArea Area);
bool isHorizontalSideBarLocation(ads::SideBarLocation Location);
bool isSideBarArea(ads::DockWidgetArea Area);
SIP_PYOBJECT findParent(SIP_PYTYPE type, const QWidget *w) const /TypeHint="QObject"/; SIP_PYOBJECT findParent(SIP_PYTYPE type, const QWidget *w) const /TypeHint="QObject"/;
%MethodCode %MethodCode

View File

@@ -117,6 +117,7 @@ struct AutoHideDockContainerPrivate
CResizeHandle* ResizeHandle = nullptr; CResizeHandle* ResizeHandle = nullptr;
QSize Size; // creates invalid size QSize Size; // creates invalid size
QPointer<CAutoHideTab> SideTab; QPointer<CAutoHideTab> SideTab;
QSize SizeCache;
/** /**
* Private data constructor * Private data constructor
@@ -215,6 +216,7 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarL
bool OpaqueResize = CDockManager::testConfigFlag(CDockManager::OpaqueSplitterResize); bool OpaqueResize = CDockManager::testConfigFlag(CDockManager::OpaqueSplitterResize);
d->ResizeHandle->setOpaqueResize(OpaqueResize); d->ResizeHandle->setOpaqueResize(OpaqueResize);
d->Size = d->DockArea->size(); d->Size = d->DockArea->size();
d->SizeCache = DockWidget->size();
addDockWidget(DockWidget); addDockWidget(DockWidget);
parent->registerAutoHideWidget(this); parent->registerAutoHideWidget(this);
@@ -237,7 +239,6 @@ void CAutoHideDockContainer::updateSize()
} }
auto rect = dockContainerParent->contentRect(); auto rect = dockContainerParent->contentRect();
switch (sideBarLocation()) switch (sideBarLocation())
{ {
case SideBarLocation::SideBarTop: case SideBarLocation::SideBarTop:
@@ -271,6 +272,15 @@ void CAutoHideDockContainer::updateSize()
default: default:
break; break;
} }
if (orientation() == Qt::Horizontal)
{
d->SizeCache.setHeight(this->height());
}
else
{
d->SizeCache.setWidth(this->width());
}
} }
//============================================================================ //============================================================================
@@ -294,7 +304,7 @@ CAutoHideDockContainer::~CAutoHideDockContainer()
} }
//============================================================================ //============================================================================
CAutoHideSideBar* CAutoHideDockContainer::sideBar() const CAutoHideSideBar* CAutoHideDockContainer::autoHideSideBar() const
{ {
if (d->SideTab) if (d->SideTab)
{ {
@@ -303,7 +313,7 @@ CAutoHideSideBar* CAutoHideDockContainer::sideBar() const
else else
{ {
auto DockContainer = dockContainer(); auto DockContainer = dockContainer();
return DockContainer ? DockContainer->sideTabBar(d->SideTabBarArea) : nullptr; return DockContainer ? DockContainer->autoHideSideBar(d->SideTabBarArea) : nullptr;
} }
} }
@@ -344,6 +354,10 @@ void CAutoHideDockContainer::addDockWidget(CDockWidget* DockWidget)
} }
d->DockArea->addDockWidget(DockWidget); d->DockArea->addDockWidget(DockWidget);
updateSize(); updateSize();
// The dock area is not visible and will not update the size when updateSize()
// is called for this auto hide container. Therefore we explicitly resize
// it here. As soon as it will become visible, it will get the right size
d->DockArea->resize(size());
} }
@@ -643,5 +657,63 @@ bool CAutoHideDockContainer::event(QEvent* event)
return Super::event(event); return Super::event(event);
} }
//============================================================================
void CAutoHideDockContainer::dragLeaveEvent(QDragLeaveEvent*)
{
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover))
{
collapseView(true);
}
} }
//============================================================================
Qt::Orientation CAutoHideDockContainer::orientation() const
{
return ads::internal::isHorizontalSideBarLocation(d->SideTabBarArea)
? Qt::Horizontal : Qt::Vertical;
}
//============================================================================
void CAutoHideDockContainer::resetToInitialDockWidgetSize()
{
if (orientation() == Qt::Horizontal)
{
setSize(d->SizeCache.height());
}
else
{
setSize(d->SizeCache.width());
}
}
//============================================================================
void CAutoHideDockContainer::moveToNewSideBarLocation(SideBarLocation NewSideBarLocation,
int TabIndex)
{
if (NewSideBarLocation == sideBarLocation() && TabIndex == this->tabIndex())
{
return;
}
auto OldOrientation = orientation();
auto SideBar = dockContainer()->autoHideSideBar(NewSideBarLocation);
SideBar->addAutoHideWidget(this, TabIndex);
// If we move a horizontal auto hide container to a vertical position
// then we resize it to the original dock widget size, to avoid
// an extremely stretched dock widget after insertion
if (SideBar->orientation() != OldOrientation)
{
resetToInitialDockWidgetSize();
}
}
//============================================================================
int CAutoHideDockContainer::tabIndex() const
{
return d->SideTab->tabIndex();
}
}

View File

@@ -34,7 +34,7 @@
#include <QSplitter> #include <QSplitter>
#include "AutoHideTab.h" #include "AutoHideTab.h"
class QXmlStreamWriter; QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
namespace ads namespace ads
{ {
@@ -65,6 +65,7 @@ protected:
virtual void resizeEvent(QResizeEvent* event) override; virtual void resizeEvent(QResizeEvent* event) override;
virtual void leaveEvent(QEvent *event) override; virtual void leaveEvent(QEvent *event) override;
virtual bool event(QEvent* event) override; virtual bool event(QEvent* event) override;
virtual void dragLeaveEvent(QDragLeaveEvent* ev) override;
/** /**
* Updates the size considering the size limits and the resize margins * Updates the size considering the size limits and the resize margins
@@ -91,9 +92,9 @@ public:
virtual ~CAutoHideDockContainer(); virtual ~CAutoHideDockContainer();
/** /**
* Get's the side tab bar * Gets the side tab bar
*/ */
CAutoHideSideBar* sideBar() const; CAutoHideSideBar* autoHideSideBar() const;
/** /**
* Returns the side tab * Returns the side tab
@@ -101,10 +102,15 @@ public:
CAutoHideTab* autoHideTab() const; CAutoHideTab* autoHideTab() const;
/** /**
* Get's the dock widget in this dock container * Gets the dock widget in this dock container
*/ */
CDockWidget* dockWidget() const; CDockWidget* dockWidget() const;
/**
* Returns the index of this container in the sidebar
*/
int tabIndex() const;
/** /**
* Adds a dock widget and removes the previous dock widget * Adds a dock widget and removes the previous dock widget
*/ */
@@ -162,10 +168,34 @@ public:
/** /**
* Use this instead of resize. * Use this instead of resize.
* Depending on the sidebar location this will set the width or heigth * Depending on the sidebar location this will set the width or height
* of this auto hide container. * of this auto hide container.
*/ */
void setSize(int Size); void setSize(int Size);
/**
* Resets the width or height to the initial dock widget size dependinng on
* the orientation.
* If the orientation is Qt::Horizontal, then the height is reset to
* the initial size and if orientation is Qt::Vertical, then the width is
* reset to the initial size
*/
void resetToInitialDockWidgetSize();
/**
* Returns orientation of this container.
* Left and right containers have a Qt::Vertical orientation and top / bottom
* containers have a Qt::Horizontal orientation.
* The function returns the orientation of the corresponding auto hide
* side bar.
*/
Qt::Orientation orientation() const;
/**
* Removes the AutoHide container from the current side bar and adds
* it to the new side bar given in SideBarLocation
*/
void moveToNewSideBarLocation(SideBarLocation SideBarLocation, int TabIndex = -1);
}; };
} // namespace ads } // namespace ads

View File

@@ -196,6 +196,7 @@ void CAutoHideSideBar::insertTab(int Index, CAutoHideTab* SideTab)
{ {
SideTab->setSideBar(this); SideTab->setSideBar(this);
SideTab->installEventFilter(this); SideTab->installEventFilter(this);
// Default insertion is append
if (Index < 0) if (Index < 0)
{ {
d->TabsLayout->insertWidget(d->TabsLayout->count() - 1, SideTab); d->TabsLayout->insertWidget(d->TabsLayout->count() - 1, SideTab);
@@ -233,12 +234,25 @@ void CAutoHideSideBar::removeAutoHideWidget(CAutoHideDockContainer* AutoHideWidg
} }
//============================================================================ //============================================================================
void CAutoHideSideBar::addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget) void CAutoHideSideBar::addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget,
int TabIndex)
{ {
auto SideBar = AutoHideWidget->autoHideTab()->sideBar(); auto SideBar = AutoHideWidget->autoHideTab()->sideBar();
if (SideBar == this) if (SideBar == this)
{ {
return; // If we move to the same tab index or if we insert before the next
// tab index, then we will end at the same tab position and can leave
if (AutoHideWidget->tabIndex() == TabIndex || (AutoHideWidget->tabIndex() + 1) == TabIndex)
{
return;
}
// We remove this auto hide widget from the sidebar in the code below
// and therefore need to correct the TabIndex here
if (AutoHideWidget->tabIndex() < TabIndex)
{
--TabIndex;
}
} }
if (SideBar) if (SideBar)
@@ -248,7 +262,7 @@ void CAutoHideSideBar::addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget)
AutoHideWidget->setParent(d->ContainerWidget); AutoHideWidget->setParent(d->ContainerWidget);
AutoHideWidget->setSideBarLocation(d->SideTabArea); AutoHideWidget->setSideBarLocation(d->SideTabArea);
d->ContainerWidget->registerAutoHideWidget(AutoHideWidget); d->ContainerWidget->registerAutoHideWidget(AutoHideWidget);
insertTab(-1, AutoHideWidget->autoHideTab()); insertTab(TabIndex, AutoHideWidget->autoHideTab());
} }
@@ -302,14 +316,14 @@ Qt::Orientation CAutoHideSideBar::orientation() const
//============================================================================ //============================================================================
CAutoHideTab* CAutoHideSideBar::tabAt(int index) const CAutoHideTab* CAutoHideSideBar::tab(int index) const
{ {
return qobject_cast<CAutoHideTab*>(d->TabsLayout->itemAt(index)->widget()); return qobject_cast<CAutoHideTab*>(d->TabsLayout->itemAt(index)->widget());
} }
//============================================================================ //============================================================================
int CAutoHideSideBar::tabCount() const int CAutoHideSideBar::count() const
{ {
return d->TabsLayout->count() - 1; return d->TabsLayout->count() - 1;
} }
@@ -318,17 +332,17 @@ int CAutoHideSideBar::tabCount() const
//============================================================================ //============================================================================
int CAutoHideSideBar::visibleTabCount() const int CAutoHideSideBar::visibleTabCount() const
{ {
int count = 0; int VisibleTabCount = 0;
auto ParentWidget = parentWidget(); auto ParentWidget = parentWidget();
for (auto i = 0; i < tabCount(); i++) for (auto i = 0; i < count(); i++)
{ {
if (tabAt(i)->isVisibleTo(ParentWidget)) if (tab(i)->isVisibleTo(ParentWidget))
{ {
count++; VisibleTabCount++;
} }
} }
return count; return VisibleTabCount;
} }
@@ -336,9 +350,9 @@ int CAutoHideSideBar::visibleTabCount() const
bool CAutoHideSideBar::hasVisibleTabs() const bool CAutoHideSideBar::hasVisibleTabs() const
{ {
auto ParentWidget = parentWidget(); auto ParentWidget = parentWidget();
for (auto i = 0; i < tabCount(); i++) for (auto i = 0; i < count(); i++)
{ {
if (tabAt(i)->isVisibleTo(ParentWidget)) if (tab(i)->isVisibleTo(ParentWidget))
{ {
return true; return true;
} }
@@ -348,6 +362,21 @@ bool CAutoHideSideBar::hasVisibleTabs() const
} }
//============================================================================
int CAutoHideSideBar::indexOfTab(const CAutoHideTab& Tab) const
{
for (auto i = 0; i < count(); i++)
{
if (tab(i) == &Tab)
{
return i;
}
}
return -1;
}
//============================================================================ //============================================================================
SideBarLocation CAutoHideSideBar::sideBarLocation() const SideBarLocation CAutoHideSideBar::sideBarLocation() const
{ {
@@ -358,18 +387,18 @@ SideBarLocation CAutoHideSideBar::sideBarLocation() const
//============================================================================ //============================================================================
void CAutoHideSideBar::saveState(QXmlStreamWriter& s) const void CAutoHideSideBar::saveState(QXmlStreamWriter& s) const
{ {
if (!tabCount()) if (!count())
{ {
return; return;
} }
s.writeStartElement("SideBar"); s.writeStartElement("SideBar");
s.writeAttribute("Area", QString::number(sideBarLocation())); s.writeAttribute("Area", QString::number(sideBarLocation()));
s.writeAttribute("Tabs", QString::number(tabCount())); s.writeAttribute("Tabs", QString::number(count()));
for (auto i = 0; i < tabCount(); ++i) for (auto i = 0; i < count(); ++i)
{ {
auto Tab = tabAt(i); auto Tab = tab(i);
if (!Tab) if (!Tab)
{ {
continue; continue;
@@ -385,7 +414,14 @@ void CAutoHideSideBar::saveState(QXmlStreamWriter& s) const
QSize CAutoHideSideBar::minimumSizeHint() const QSize CAutoHideSideBar::minimumSizeHint() const
{ {
QSize Size = sizeHint(); QSize Size = sizeHint();
Size.setWidth(10); if (d->isHorizontal())
{
Size.setWidth(0);
}
else
{
Size.setHeight(0);
}
return Size; return Size;
} }
@@ -417,5 +453,56 @@ CDockContainerWidget* CAutoHideSideBar::dockContainer() const
return d->ContainerWidget; return d->ContainerWidget;
} }
//===========================================================================
int CAutoHideSideBar::tabAt(const QPoint& Pos) const
{
if (!isVisible())
{
return TabInvalidIndex;
}
if (orientation() == Qt::Horizontal)
{
if (Pos.x() < tab(0)->geometry().x())
{
return -1;
}
}
else
{
if (Pos.y() < tab(0)->geometry().y())
{
return -1;
}
}
for (int i = 0; i < count(); ++i)
{
if (tab(i)->geometry().contains(Pos))
{
return i;
}
}
return count();
}
//===========================================================================
int CAutoHideSideBar::tabInsertIndexAt(const QPoint& Pos) const
{
int Index = tabAt(Pos);
if (Index == TabInvalidIndex)
{
return TabDefaultInsertIndex;
}
else
{
return (Index < 0) ? 0 : Index;
}
}
} // namespace ads } // namespace ads

View File

@@ -33,7 +33,7 @@
#include "ads_globals.h" #include "ads_globals.h"
#include "AutoHideTab.h" #include "AutoHideTab.h"
class QXmlStreamWriter; QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
namespace ads namespace ads
{ {
@@ -117,7 +117,7 @@ public:
* If the AutoHideWidget is in another sidebar, then it will be removed * If the AutoHideWidget is in another sidebar, then it will be removed
* from this sidebar. * from this sidebar.
*/ */
void addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget); void addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget, int Index = TabDefaultInsertIndex);
/** /**
* Returns orientation of side tab. * Returns orientation of side tab.
@@ -125,14 +125,32 @@ public:
Qt::Orientation orientation() const; Qt::Orientation orientation() const;
/* /*
* get the side tab widget at position, returns nullptr if it's out of bounds * Get the side tab widget at position, returns nullptr if it's out of bounds
*/ */
CAutoHideTab* tabAt(int index) const; CAutoHideTab* tab(int index) const;
/**
* Returns the tab at the given position.
* Returns -1 if the position is left of the first tab and count() if the
* position is right of the last tab. Returns InvalidTabIndex (-2) to
* indicate an invalid value.
*/
int tabAt(const QPoint& Pos) const;
/**
* Returns the tab insertion index for the given mouse cursor position
*/
int tabInsertIndexAt(const QPoint& Pos) const;
/**
* Returns the index of the given tab
*/
int indexOfTab(const CAutoHideTab& Tab) const;
/* /*
* Gets the count of the tab widgets * Gets the count of the tab widgets
*/ */
int tabCount() const; int count() const;
/** /**
* Returns the number of visible tabs to its parent widget. * Returns the number of visible tabs to its parent widget.
@@ -155,7 +173,7 @@ public:
/** /**
* Overrides the minimumSizeHint() function of QScrollArea * Overrides the minimumSizeHint() function of QScrollArea
* The minimumSizeHint() is bigger than the sizeHint () for the scroll * The minimumSizeHint() is bigger than the sizeHint () for the scroll
* area because even if the scrollbars are invisible, the required speace * area because even if the scrollbars are invisible, the required space
* is reserved in the minimumSizeHint(). This override simply returns * is reserved in the minimumSizeHint(). This override simply returns
* sizeHint(); * sizeHint();
*/ */

View File

@@ -32,15 +32,22 @@
#include <QBoxLayout> #include <QBoxLayout>
#include <QApplication> #include <QApplication>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QMenu>
#include <QEvent>
#include <QTimer>
#include "AutoHideDockContainer.h" #include "AutoHideDockContainer.h"
#include "AutoHideSideBar.h" #include "AutoHideSideBar.h"
#include "DockAreaWidget.h" #include "DockAreaWidget.h"
#include "DockManager.h" #include "DockManager.h"
#include "DockWidget.h" #include "DockWidget.h"
#include "FloatingDragPreview.h"
#include "DockOverlay.h"
#include "ads_globals.h"
namespace ads namespace ads
{ {
/** /**
* Private data class of CDockWidgetTab class (pimpl) * Private data class of CDockWidgetTab class (pimpl)
*/ */
@@ -51,6 +58,13 @@ struct AutoHideTabPrivate
CAutoHideSideBar* SideBar = nullptr; CAutoHideSideBar* SideBar = nullptr;
Qt::Orientation Orientation{Qt::Vertical}; Qt::Orientation Orientation{Qt::Vertical};
QElapsedTimer TimeSinceHoverMousePress; QElapsedTimer TimeSinceHoverMousePress;
QTimer DragOverTimer;
bool MousePressed = false;
eDragState DragState = DraggingInactive;
QPoint GlobalDragStartMousePosition;
QPoint DragStartMousePosition;
IFloatingWidget* FloatingWidget = nullptr;
Qt::Orientation DragStartOrientation;
/** /**
* Private data constructor * Private data constructor
@@ -82,6 +96,55 @@ struct AutoHideTabPrivate
DockContainer->handleAutoHideWidgetEvent(event, _this); DockContainer->handleAutoHideWidgetEvent(event, _this);
} }
} }
/**
* 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(internal::LocationProperty, Location);
QObject::connect(Action, &QAction::triggered, _this, &CAutoHideTab::onAutoHideToActionClicked);
Action->setEnabled(Location != _this->sideBarLocation());
return Action;
}
/**
* Test function for current drag state
*/
bool isDraggingState(eDragState dragState) const
{
return this->DragState == dragState;
}
/**
* Saves the drag start position in global and local coordinates
*/
void saveDragStartMousePosition(const QPoint& GlobalPos)
{
GlobalDragStartMousePosition = GlobalPos;
DragStartMousePosition = _this->mapFromGlobal(GlobalPos);
}
/**
* Starts floating of the dock widget that belongs to this title bar
* Returns true, if floating has been started and false if floating
* is not possible for any reason
*/
bool startFloating(eDragState DraggingState = DraggingFloatingWidget);
template <typename T>
IFloatingWidget* createFloatingWidget(T* Widget)
{
auto w = new CFloatingDragPreview(Widget);
_this->connect(w, &CFloatingDragPreview::draggingCanceled, [=]()
{
DragState = DraggingInactive;
});
return w;
}
}; // struct DockWidgetTabPrivate }; // struct DockWidgetTabPrivate
@@ -110,6 +173,53 @@ void AutoHideTabPrivate::updateOrientation()
} }
//============================================================================
bool AutoHideTabPrivate::startFloating(eDragState DraggingState)
{
auto DockArea = DockWidget->dockAreaWidget();
ADS_PRINT("isFloating " << dockContainer()->isFloating());
ADS_PRINT("startFloating");
DragState = DraggingState;
IFloatingWidget* FloatingWidget = nullptr;
FloatingWidget = createFloatingWidget(DockArea);
auto Size = DockArea->size();
auto StartPos = DragStartMousePosition;
auto AutoHideContainer = DockWidget->autoHideDockContainer();
DragStartOrientation = AutoHideContainer->orientation();
switch (SideBar->sideBarLocation())
{
case SideBarLeft:
StartPos.rx() = AutoHideContainer->rect().left() + 10;
break;
case SideBarRight:
StartPos.rx() = AutoHideContainer->rect().right() - 10;
break;
case SideBarTop:
StartPos.ry() = AutoHideContainer->rect().top() + 10;
break;
case SideBarBottom:
StartPos.ry() = AutoHideContainer->rect().bottom() - 10;
break;
case SideBarNone:
return false;
}
FloatingWidget->startFloating(StartPos, Size, DraggingFloatingWidget, _this);
auto DockManager = DockWidget->dockManager();
auto Overlay = DockManager->containerOverlay();
Overlay->setAllowedAreas(OuterDockAreas);
this->FloatingWidget = FloatingWidget;
qApp->postEvent(DockWidget, new QEvent((QEvent::Type)internal::DockedWidgetDragStartEvent));
return true;
}
//============================================================================ //============================================================================
void CAutoHideTab::setSideBar(CAutoHideSideBar* SideTabBar) void CAutoHideTab::setSideBar(CAutoHideSideBar* SideTabBar)
{ {
@@ -146,6 +256,14 @@ CAutoHideTab::CAutoHideTab(QWidget* parent) :
{ {
setAttribute(Qt::WA_NoMousePropagation); setAttribute(Qt::WA_NoMousePropagation);
setFocusPolicy(Qt::NoFocus); setFocusPolicy(Qt::NoFocus);
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover)) {
setAcceptDrops(true);
}
d->DragOverTimer.setInterval(CDockManager::configParam(
CDockManager::AutoHideOpenOnDragHoverDelay_ms, 500).toInt());
d->DragOverTimer.setSingleShot(true);
connect(&d->DragOverTimer, &QTimer::timeout, this, &CAutoHideTab::onDragHoverDelayExpired);
} }
@@ -249,33 +367,254 @@ bool CAutoHideTab::event(QEvent* event)
case QEvent::Leave: case QEvent::Leave:
d->forwardEventToDockContainer(event); d->forwardEventToDockContainer(event);
break; 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: default:
break; break;
} }
return Super::event(event); return Super::event(event);
} }
//============================================================================ //============================================================================
bool CAutoHideTab::iconOnly() const bool CAutoHideTab::iconOnly() const
{ {
return CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideSideBarsIconOnly) && !icon().isNull(); return CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideSideBarsIconOnly) && !icon().isNull();
} }
//============================================================================
void CAutoHideTab::contextMenuEvent(QContextMenuEvent* ev)
{
ev->accept();
d->saveDragStartMousePosition(ev->globalPos());
const bool isFloatable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable);
QAction* Action;
QMenu Menu(this);
Action = Menu.addAction(tr("Detach"), this, SLOT(setDockWidgetFloating()));
Action->setEnabled(isFloatable);
auto IsPinnable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable);
Action->setEnabled(IsPinnable);
auto menu = Menu.addMenu(tr("Pin To..."));
menu->setEnabled(IsPinnable);
d->createAutoHideToAction(tr("Top"), SideBarTop, menu);
d->createAutoHideToAction(tr("Left"), SideBarLeft, menu);
d->createAutoHideToAction(tr("Right"), SideBarRight, menu);
d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu);
Action = Menu.addAction(tr("Unpin (Dock)"), this, SLOT(unpinDockWidget()));
Menu.addSeparator();
Action = Menu.addAction(tr("Close"), this, SLOT(requestCloseDockWidget()));
Action->setEnabled(d->DockWidget->features().testFlag(CDockWidget::DockWidgetClosable));
Menu.exec(ev->globalPos());
}
//============================================================================
void CAutoHideTab::setDockWidgetFloating()
{
d->DockWidget->setFloating();
}
//============================================================================
void CAutoHideTab::unpinDockWidget()
{
d->DockWidget->setAutoHide(false);
}
//===========================================================================
void CAutoHideTab::onAutoHideToActionClicked()
{
int Location = sender()->property(internal::LocationProperty).toInt();
d->DockWidget->setAutoHide(true, (SideBarLocation)Location);
}
//============================================================================
void CAutoHideTab::mousePressEvent(QMouseEvent* ev)
{
// 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 (!ev->spontaneous())
{
d->TimeSinceHoverMousePress.restart();
d->forwardEventToDockContainer(ev);
}
else if (d->TimeSinceHoverMousePress.hasExpired(500))
{
d->forwardEventToDockContainer(ev);
}
if (ev->button() == Qt::LeftButton)
{
ev->accept();
d->MousePressed = true;
d->saveDragStartMousePosition(internal::globalPositionOf(ev));
d->DragState = DraggingMousePressed;
}
Super::mousePressEvent(ev);
}
//============================================================================
void CAutoHideTab::mouseReleaseEvent(QMouseEvent* ev)
{
if (ev->button() == Qt::LeftButton)
{
d->MousePressed = false;
auto CurrentDragState = d->DragState;
d->GlobalDragStartMousePosition = QPoint();
d->DragStartMousePosition = QPoint();
d->DragState = DraggingInactive;
switch (CurrentDragState)
{
case DraggingTab:
// End of tab moving, emit signal
/*if (d->DockArea)
{
ev->accept();
Q_EMIT moved(internal::globalPositionOf(ev));
}*/
break;
case DraggingFloatingWidget:
ev->accept();
d->FloatingWidget->finishDragging();
if (d->DockWidget->autoHideDockContainer() && d->DragStartOrientation != orientation())
{
d->DockWidget->autoHideDockContainer()->resetToInitialDockWidgetSize();
}
break;
default:
break; // do nothing
}
}
Super::mouseReleaseEvent(ev);
}
//============================================================================
void CAutoHideTab::mouseMoveEvent(QMouseEvent *ev)
{
if (!(ev->buttons() & Qt::LeftButton)
|| d->isDraggingState(DraggingInactive))
{
d->DragState = DraggingInactive;
Super::mouseMoveEvent(ev);
return;
}
// move floating window
if (d->isDraggingState(DraggingFloatingWidget))
{
d->FloatingWidget->moveFloating();
Super::mouseMoveEvent(ev);
return;
}
// move tab
if (d->isDraggingState(DraggingTab))
{
// Moving the tab is always allowed because it does not mean moving the
// dock widget around
//d->moveTab(ev);
}
auto MappedPos = mapToParent(ev->pos());
bool MouseOutsideBar = (MappedPos.x() < 0)
|| (MappedPos.x() > parentWidget()->rect().right());
// Maybe a fixed drag distance is better here ?
int DragDistanceY = qAbs(
d->GlobalDragStartMousePosition.y()
- internal::globalPositionOf(ev).y());
if (DragDistanceY >= CDockManager::startDragDistance() || MouseOutsideBar)
{
// Floating is only allowed for widgets that are floatable
// We can create the drag preview if the widget is movable.
auto Features = d->DockWidget->features();
if (Features.testFlag(CDockWidget::DockWidgetFloatable)
|| (Features.testFlag(CDockWidget::DockWidgetMovable)))
{
d->startFloating();
}
return;
}
Super::mouseMoveEvent(ev);
}
//============================================================================
void CAutoHideTab::dragEnterEvent(QDragEnterEvent *ev)
{
Q_UNUSED(ev);
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover))
{
d->DragOverTimer.start();
ev->accept();
}
}
//============================================================================
void CAutoHideTab::dragLeaveEvent(QDragLeaveEvent *ev)
{
Q_UNUSED(ev);
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover))
{
d->DragOverTimer.stop();
}
}
//============================================================================
void CAutoHideTab::requestCloseDockWidget()
{
d->DockWidget->requestCloseDockWidget();
}
//============================================================================
int CAutoHideTab::tabIndex() const
{
if (!d->SideBar)
{
return -1;
}
return d->SideBar->indexOfTab(*this);
}
//============================================================================
void CAutoHideTab::onDragHoverDelayExpired()
{
static const char* const PropertyId = "ActiveDragOverAutoHideContainer";
// First we check if there is an active auto hide container that is visible
// In this case, we collapse it before we open the new one
auto v = d->DockWidget->dockManager()->property(PropertyId);
if (v.isValid())
{
auto ActiveAutoHideContainer = v.value<QPointer<CAutoHideDockContainer>>();
if (ActiveAutoHideContainer)
{
ActiveAutoHideContainer->collapseView(true);
}
}
auto AutoHideContainer = d->DockWidget->autoHideDockContainer();
AutoHideContainer->collapseView(false);
d->DockWidget->dockManager()->setProperty(PropertyId,
QVariant::fromValue(QPointer<CAutoHideDockContainer>(AutoHideContainer)));
}
} }

View File

@@ -65,11 +65,20 @@ private:
friend class CDockContainerWidget; friend class CDockContainerWidget;
friend DockContainerWidgetPrivate; friend DockContainerWidgetPrivate;
private Q_SLOTS:
void onAutoHideToActionClicked();
void onDragHoverDelayExpired();
protected: protected:
void setSideBar(CAutoHideSideBar *SideTabBar); void setSideBar(CAutoHideSideBar *SideTabBar);
void removeFromSideBar(); void removeFromSideBar();
virtual bool event(QEvent* event) override; virtual bool event(QEvent* event) override;
virtual void contextMenuEvent(QContextMenuEvent* ev) override;
virtual void mousePressEvent(QMouseEvent* ev) override;
virtual void mouseReleaseEvent(QMouseEvent* ev) override;
virtual void mouseMoveEvent(QMouseEvent* ev) override;
virtual void dragEnterEvent(QDragEnterEvent* ev) override;
virtual void dragLeaveEvent(QDragLeaveEvent* ev) override;
public: public:
using Super = CPushButton; using Super = CPushButton;
@@ -133,6 +142,27 @@ public:
* not in a side bar * not in a side bar
*/ */
CAutoHideSideBar* sideBar() const; CAutoHideSideBar* sideBar() const;
/**
* Returns the index of this tab in the sideBar
*/
int tabIndex() const;
public Q_SLOTS:
/**
* Set the dock widget floating, if it is floatable
*/
void setDockWidgetFloating();
/**
* Unpin and dock the auto hide widget
*/
void unpinDockWidget();
/**
* Calls the requestCloseDockWidget() function for the assigned dock widget
*/
void requestCloseDockWidget();
}; // class AutoHideTab }; // class AutoHideTab
} }
// namespace ads // namespace ads

View File

@@ -1,5 +1,6 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
project(QtAdvancedDockingSystem LANGUAGES CXX VERSION ${VERSION_SHORT}) project(QtAdvancedDockingSystem LANGUAGES CXX VERSION ${VERSION_SHORT})
include(GNUInstallDirs)
if (${QT_VERSION_MAJOR}) if (${QT_VERSION_MAJOR})
message(STATUS "Forced to use Qt version ${QT_VERSION_MAJOR}") message(STATUS "Forced to use Qt version ${QT_VERSION_MAJOR}")
find_package(QT NAMES Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) find_package(QT NAMES Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
@@ -36,7 +37,7 @@ set(ads_SRCS
AutoHideTab.cpp AutoHideTab.cpp
AutoHideDockContainer.cpp AutoHideDockContainer.cpp
PushButton.cpp PushButton.cpp
ResizeHandle.cpp ResizeHandle.cpp
ads.qrc ads.qrc
) )
set(ads_HEADERS set(ads_HEADERS
@@ -62,7 +63,7 @@ set(ads_HEADERS
AutoHideTab.h AutoHideTab.h
AutoHideDockContainer.h AutoHideDockContainer.h
PushButton.h PushButton.h
ResizeHandle.h ResizeHandle.h
) )
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>") add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
@@ -85,7 +86,12 @@ target_link_libraries(${library_name} PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets) Qt${QT_VERSION_MAJOR}::Widgets)
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
target_link_libraries(${library_name} PUBLIC xcb) if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
find_package(X11 REQUIRED)
target_link_libraries(${library_name} PUBLIC X11::xcb)
else()
target_link_libraries(${library_name} PUBLIC xcb)
endif()
endif() endif()
set_target_properties(${library_name} PROPERTIES set_target_properties(${library_name} PROPERTIES
AUTOMOC ON AUTOMOC ON
@@ -93,6 +99,7 @@ set_target_properties(${library_name} PROPERTIES
CXX_EXTENSIONS OFF CXX_EXTENSIONS OFF
VERSION ${VERSION_SHORT} VERSION ${VERSION_SHORT}
EXPORT_NAME ${library_name} EXPORT_NAME ${library_name}
DEBUG_POSTFIX "d"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib" ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
LIBRARY_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" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/bin"
@@ -114,7 +121,7 @@ write_basic_package_version_file(
COMPATIBILITY SameMajorVersion COMPATIBILITY SameMajorVersion
) )
install(FILES ${ads_HEADERS} install(FILES ${ads_HEADERS}
DESTINATION include/${library_name} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${library_name}
COMPONENT headers COMPONENT headers
) )
install(FILES install(FILES
@@ -125,25 +132,25 @@ install(FILES
) )
install(TARGETS ${library_name} install(TARGETS ${library_name}
EXPORT adsTargets EXPORT adsTargets
RUNTIME DESTINATION bin RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION lib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION lib ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION include/${library_name} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${library_name}
) )
install(EXPORT adsTargets install(EXPORT adsTargets
FILE adsTargets.cmake FILE adsTargets.cmake
NAMESPACE ads:: NAMESPACE ads::
DESTINATION lib/cmake/${library_name} DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${library_name}
) )
install(FILES qtadvanceddockingConfig.cmake RENAME ${library_name}Config.cmake install(FILES qtadvanceddockingConfig.cmake RENAME ${library_name}Config.cmake
DESTINATION lib/cmake/${library_name} DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${library_name}
) )
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${library_name}ConfigVersion.cmake" install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${library_name}ConfigVersion.cmake"
DESTINATION lib/cmake/${library_name} DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${library_name}
) )
target_include_directories(${library_name} PUBLIC target_include_directories(${library_name} PUBLIC
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
) )

View File

@@ -111,8 +111,9 @@ void DockAreaTabBarPrivate::updateTabs()
// Sometimes the synchronous calculation of the rectangular area fails // Sometimes the synchronous calculation of the rectangular area fails
// Therefore we use QTimer::singleShot here to execute the call // Therefore we use QTimer::singleShot here to execute the call
// within the event loop - see #520 // within the event loop - see #520
QTimer::singleShot(0, [&, TabWidget]{ QTimer::singleShot(0, _this, [&, TabWidget]
_this->ensureWidgetVisible(TabWidget); {
_this->ensureWidgetVisible(TabWidget);
}); });
} }
else else
@@ -160,15 +161,13 @@ CDockAreaTabBar::~CDockAreaTabBar()
void CDockAreaTabBar::wheelEvent(QWheelEvent* Event) void CDockAreaTabBar::wheelEvent(QWheelEvent* Event)
{ {
Event->accept(); Event->accept();
const int direction = Event->angleDelta().y(); int numPixels = Event->pixelDelta().y();
if (direction < 0) if (!numPixels)
{ {
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + 20); numPixels = Event->angleDelta().y() / 5;
} }
else
{ horizontalScrollBar()->setValue(horizontalScrollBar()->value() - numPixels);
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20);
}
} }
@@ -300,7 +299,7 @@ int CDockAreaTabBar::currentIndex() const
//=========================================================================== //===========================================================================
CDockWidgetTab* CDockAreaTabBar::currentTab() const CDockWidgetTab* CDockAreaTabBar::currentTab() const
{ {
if (d->CurrentIndex < 0) if (d->CurrentIndex < 0 || d->CurrentIndex >= d->TabsLayout->count())
{ {
return nullptr; return nullptr;
} }
@@ -389,15 +388,18 @@ void CDockAreaTabBar::onTabWidgetMoved(const QPoint& GlobalPos)
int fromIndex = d->TabsLayout->indexOf(MovingTab); int fromIndex = d->TabsLayout->indexOf(MovingTab);
auto MousePos = mapFromGlobal(GlobalPos); auto MousePos = mapFromGlobal(GlobalPos);
MousePos.rx() = qMax(d->firstTab()->geometry().left(), MousePos.x()); MousePos.rx() = qMax(0, MousePos.x());
MousePos.rx() = qMin(d->lastTab()->geometry().right(), MousePos.x()); MousePos.rx() = qMin(width(), MousePos.x());
int toIndex = -1; int toIndex = -1;
// Find tab under mouse // Find tab under mouse
for (int i = 0; i < count(); ++i) for (int i = 0; i < count(); ++i)
{ {
CDockWidgetTab* DropTab = tab(i); CDockWidgetTab* DropTab = tab(i);
auto TabGeometry = DropTab->geometry();
TabGeometry.setTopLeft(d->TabsContainerWidget->mapToParent(TabGeometry.topLeft()));
TabGeometry.setBottomRight(d->TabsContainerWidget->mapToParent(TabGeometry.bottomRight()));
if (DropTab == MovingTab || !DropTab->isVisibleTo(this) if (DropTab == MovingTab || !DropTab->isVisibleTo(this)
|| !DropTab->geometry().contains(MousePos)) || !TabGeometry.contains(MousePos))
{ {
continue; continue;
} }
@@ -469,6 +471,15 @@ bool CDockAreaTabBar::eventFilter(QObject *watched, QEvent *event)
updateGeometry(); updateGeometry();
break; break;
// Manage wheel event
case QEvent::Wheel:
// Ignore wheel events if tab is currently dragged
if (Tab->dragState() == DraggingInactive)
{
wheelEvent((QWheelEvent* )event);
}
break;
default: default:
break; break;
} }
@@ -504,6 +515,53 @@ QSize CDockAreaTabBar::sizeHint() const
return d->TabsContainerWidget->sizeHint(); return d->TabsContainerWidget->sizeHint();
} }
//===========================================================================
int CDockAreaTabBar::tabAt(const QPoint& Pos) const
{
if (!isVisible())
{
return TabInvalidIndex;
}
if (Pos.x() < tab(0)->geometry().x())
{
return -1;
}
for (int i = 0; i < count(); ++i)
{
if (tab(i)->geometry().contains(Pos))
{
return i;
}
}
return count();
}
//===========================================================================
int CDockAreaTabBar::tabInsertIndexAt(const QPoint& Pos) const
{
int Index = tabAt(Pos);
if (Index == TabInvalidIndex)
{
return TabDefaultInsertIndex;
}
else
{
return (Index < 0) ? 0 : Index;
}
}
//===========================================================================
bool CDockAreaTabBar::areTabsOverflowing() const
{
return d->TabsContainerWidget->width() > width();
}
} // namespace ads } // namespace ads

View File

@@ -113,6 +113,19 @@ public:
*/ */
CDockWidgetTab* tab(int Index) const; CDockWidgetTab* tab(int Index) const;
/**
* Returns the tab at the given position.
* Returns -1 if the position is left of the first tab and count() if the
* position is right of the last tab. Returns -2 to indicate an invalid
* value.
*/
int tabAt(const QPoint& Pos) const;
/**
* Returns the tab insertion index for the given mouse cursor position
*/
int tabInsertIndexAt(const QPoint& Pos) const;
/** /**
* Filters the tab widget events * Filters the tab widget events
*/ */
@@ -128,7 +141,7 @@ public:
/** /**
* Overrides the minimumSizeHint() function of QScrollArea * Overrides the minimumSizeHint() function of QScrollArea
* The minimumSizeHint() is bigger than the sizeHint () for the scroll * The minimumSizeHint() is bigger than the sizeHint () for the scroll
* area because even if the scrollbars are invisible, the required speace * area because even if the scrollbars are invisible, the required space
* is reserved in the minimumSizeHint(). This override simply returns * is reserved in the minimumSizeHint(). This override simply returns
* sizeHint(); * sizeHint();
*/ */
@@ -140,6 +153,12 @@ public:
*/ */
virtual QSize sizeHint() const override; virtual QSize sizeHint() const override;
/**
* This function returns true, if the tabs need more space than the size
* of the tab bar.
*/
bool areTabsOverflowing() const;
public Q_SLOTS: public Q_SLOTS:
/** /**
* This property sets the index of the tab bar's visible tab * This property sets the index of the tab bar's visible tab

View File

@@ -60,7 +60,6 @@
namespace ads namespace ads
{ {
static const char* const LocationProperty = "Location";
/** /**
* Private data class of CDockAreaTitleBar class (pimpl) * Private data class of CDockAreaTitleBar class (pimpl)
@@ -68,14 +67,15 @@ static const char* const LocationProperty = "Location";
struct DockAreaTitleBarPrivate struct DockAreaTitleBarPrivate
{ {
CDockAreaTitleBar* _this; CDockAreaTitleBar* _this;
QPointer<tTitleBarButton> TabsMenuButton; QPointer<CTitleBarButton> TabsMenuButton;
QPointer<tTitleBarButton> AutoHideButton; QPointer<CTitleBarButton> AutoHideButton;
QPointer<tTitleBarButton> UndockButton; QPointer<CTitleBarButton> UndockButton;
QPointer<tTitleBarButton> CloseButton; QPointer<CTitleBarButton> CloseButton;
QPointer<CTitleBarButton> MinimizeButton;
QBoxLayout* Layout; QBoxLayout* Layout;
CDockAreaWidget* DockArea; CDockAreaWidget* DockArea;
CDockAreaTabBar* TabBar; CDockAreaTabBar* TabBar;
CElidingLabel* AutoHideTitleLabel; CElidingLabel* AutoHideTitleLabel = nullptr;
bool MenuOutdated = true; bool MenuOutdated = true;
QMenu* TabsMenu; QMenu* TabsMenu;
QList<tTitleBarButton*> DockWidgetActionsButtons; QList<tTitleBarButton*> DockWidgetActionsButtons;
@@ -158,7 +158,7 @@ struct DockAreaTitleBarPrivate
QMenu* Menu) QMenu* Menu)
{ {
auto Action = Menu->addAction(Title); auto Action = Menu->addAction(Title);
Action->setProperty("Location", Location); Action->setProperty(internal::LocationProperty, Location);
QObject::connect(Action, &QAction::triggered, _this, &CDockAreaTitleBar::onAutoHideToActionClicked); QObject::connect(Action, &QAction::triggered, _this, &CDockAreaTitleBar::onAutoHideToActionClicked);
return Action; return Action;
} }
@@ -178,7 +178,8 @@ void DockAreaTitleBarPrivate::createButtons()
QSizePolicy ButtonSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); QSizePolicy ButtonSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
// Tabs menu button // Tabs menu button
TabsMenuButton = new CTitleBarButton(testConfigFlag(CDockManager::DockAreaHasTabsMenuButton)); TabsMenuButton = new CTitleBarButton(testConfigFlag(CDockManager::DockAreaHasTabsMenuButton),
false, TitleBarButtonTabsMenu);
TabsMenuButton->setObjectName("tabsMenuButton"); TabsMenuButton->setObjectName("tabsMenuButton");
TabsMenuButton->setAutoRaise(true); TabsMenuButton->setAutoRaise(true);
TabsMenuButton->setPopupMode(QToolButton::InstantPopup); TabsMenuButton->setPopupMode(QToolButton::InstantPopup);
@@ -196,7 +197,8 @@ void DockAreaTitleBarPrivate::createButtons()
SLOT(onTabsMenuActionTriggered(QAction*))); SLOT(onTabsMenuActionTriggered(QAction*)));
// Undock button // Undock button
UndockButton = new CTitleBarButton(testConfigFlag(CDockManager::DockAreaHasUndockButton)); UndockButton = new CTitleBarButton(testConfigFlag(CDockManager::DockAreaHasUndockButton),
true, TitleBarButtonUndock);
UndockButton->setObjectName("detachGroupButton"); UndockButton->setObjectName("detachGroupButton");
UndockButton->setAutoRaise(true); UndockButton->setAutoRaise(true);
internal::setToolTip(UndockButton, QObject::tr("Detach Group")); internal::setToolTip(UndockButton, QObject::tr("Detach Group"));
@@ -207,7 +209,8 @@ void DockAreaTitleBarPrivate::createButtons()
// AutoHide Button // AutoHide Button
const auto autoHideEnabled = testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled); const auto autoHideEnabled = testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled);
AutoHideButton = new CTitleBarButton(testAutoHideConfigFlag(CDockManager::DockAreaHasAutoHideButton) && autoHideEnabled); AutoHideButton = new CTitleBarButton(testAutoHideConfigFlag(CDockManager::DockAreaHasAutoHideButton) && autoHideEnabled,
true, TitleBarButtonAutoHide);
AutoHideButton->setObjectName("dockAreaAutoHideButton"); AutoHideButton->setObjectName("dockAreaAutoHideButton");
AutoHideButton->setAutoRaise(true); AutoHideButton->setAutoRaise(true);
internal::setToolTip(AutoHideButton, _this->titleBarButtonToolTip(TitleBarButtonAutoHide)); internal::setToolTip(AutoHideButton, _this->titleBarButtonToolTip(TitleBarButtonAutoHide));
@@ -218,8 +221,21 @@ void DockAreaTitleBarPrivate::createButtons()
Layout->addWidget(AutoHideButton, 0); Layout->addWidget(AutoHideButton, 0);
_this->connect(AutoHideButton, SIGNAL(clicked()), SLOT(onAutoHideButtonClicked())); _this->connect(AutoHideButton, SIGNAL(clicked()), SLOT(onAutoHideButtonClicked()));
// Minimize button
MinimizeButton = new CTitleBarButton(testAutoHideConfigFlag(CDockManager::AutoHideHasMinimizeButton),
false, TitleBarButtonMinimize);
MinimizeButton->setObjectName("dockAreaMinimizeButton");
MinimizeButton->setAutoRaise(true);
MinimizeButton->setVisible(false);
internal::setButtonIcon(MinimizeButton, QStyle::SP_TitleBarMinButton, ads::DockAreaMinimizeIcon);
internal::setToolTip(MinimizeButton, QObject::tr("Minimize"));
MinimizeButton->setSizePolicy(ButtonSizePolicy);
Layout->addWidget(MinimizeButton, 0);
_this->connect(MinimizeButton, SIGNAL(clicked()), SLOT(minimizeAutoHideContainer()));
// Close button // Close button
CloseButton = new CTitleBarButton(testConfigFlag(CDockManager::DockAreaHasCloseButton)); CloseButton = new CTitleBarButton(testConfigFlag(CDockManager::DockAreaHasCloseButton),
true, TitleBarButtonClose);
CloseButton->setObjectName("dockAreaCloseButton"); CloseButton->setObjectName("dockAreaCloseButton");
CloseButton->setAutoRaise(true); CloseButton->setAutoRaise(true);
internal::setButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton, ads::DockAreaCloseIcon); internal::setButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton, ads::DockAreaCloseIcon);
@@ -236,7 +252,10 @@ void DockAreaTitleBarPrivate::createAutoHideTitleLabel()
{ {
AutoHideTitleLabel = new CElidingLabel(""); AutoHideTitleLabel = new CElidingLabel("");
AutoHideTitleLabel->setObjectName("autoHideTitleLabel"); AutoHideTitleLabel->setObjectName("autoHideTitleLabel");
Layout->addWidget(AutoHideTitleLabel); // At position 0 is the tab bar - insert behind tab bar
Layout->insertWidget(1, AutoHideTitleLabel);
AutoHideTitleLabel->setVisible(false); // Default hidden
Layout->insertWidget(2 ,new CSpacerWidget(_this));
} }
@@ -324,10 +343,8 @@ CDockAreaTitleBar::CDockAreaTitleBar(CDockAreaWidget* parent) :
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
d->createTabBar(); d->createTabBar();
d->createAutoHideTitleLabel();
d->AutoHideTitleLabel->setVisible(false); // Default hidden
d->Layout->addWidget(new CSpacerWidget(this));
d->createButtons(); d->createButtons();
d->createAutoHideTitleLabel();
setFocusPolicy(Qt::NoFocus); setFocusPolicy(Qt::NoFocus);
} }
@@ -360,27 +377,48 @@ CDockAreaTabBar* CDockAreaTitleBar::tabBar() const
return d->TabBar; return d->TabBar;
} }
//============================================================================
void CDockAreaTitleBar::resizeEvent(QResizeEvent *event)
{
Super::resizeEvent(event);
if (CDockManager::testConfigFlag(CDockManager::DockAreaDynamicTabsMenuButtonVisibility)
&& CDockManager::testConfigFlag(CDockManager::DisableTabTextEliding))
{
markTabsMenuOutdated();
}
}
//============================================================================ //============================================================================
void CDockAreaTitleBar::markTabsMenuOutdated() void CDockAreaTitleBar::markTabsMenuOutdated()
{ {
if(DockAreaTitleBarPrivate::testConfigFlag(CDockManager::DockAreaDynamicTabsMenuButtonVisibility)) if (CDockManager::testConfigFlag(CDockManager::DockAreaDynamicTabsMenuButtonVisibility))
{ {
bool hasElidedTabTitle = false; bool TabsMenuButtonVisible = false;
for (int i = 0; i < d->TabBar->count(); ++i) if (CDockManager::testConfigFlag(CDockManager::DisableTabTextEliding))
{ {
if (!d->TabBar->isTabOpen(i)) TabsMenuButtonVisible = d->TabBar->areTabsOverflowing();
{
continue;
}
CDockWidgetTab* Tab = d->TabBar->tab(i);
if(Tab->isTitleElided())
{
hasElidedTabTitle = true;
break;
}
} }
bool visible = (hasElidedTabTitle && (d->TabBar->count() > 1)); else
QMetaObject::invokeMethod(d->TabsMenuButton, "setVisible", Qt::QueuedConnection, Q_ARG(bool, visible)); {
bool hasElidedTabTitle = false;
for (int i = 0; i < d->TabBar->count(); ++i)
{
if (!d->TabBar->isTabOpen(i))
{
continue;
}
CDockWidgetTab* Tab = d->TabBar->tab(i);
if(Tab->isTitleElided())
{
hasElidedTabTitle = true;
break;
}
}
TabsMenuButtonVisible = (hasElidedTabTitle && (d->TabBar->count() > 1));
}
QMetaObject::invokeMethod(d->TabsMenuButton, "setVisible", Qt::QueuedConnection, Q_ARG(bool, TabsMenuButtonVisible));
} }
d->MenuOutdated = true; d->MenuOutdated = true;
} }
@@ -431,6 +469,24 @@ void CDockAreaTitleBar::onCloseButtonClicked()
} }
//============================================================================
void CDockAreaTitleBar::onAutoHideCloseActionTriggered()
{
d->DockArea->closeArea();
}
//============================================================================
void CDockAreaTitleBar::minimizeAutoHideContainer()
{
auto AutoHideContainer = d->DockArea->autoHideDockContainer();
if (AutoHideContainer)
{
AutoHideContainer->collapseView(true);
}
}
//============================================================================ //============================================================================
void CDockAreaTitleBar::onUndockButtonClicked() void CDockAreaTitleBar::onUndockButtonClicked()
{ {
@@ -479,7 +535,7 @@ void CDockAreaTitleBar::updateDockWidgetActionsButtons()
int InsertIndex = indexOf(d->TabsMenuButton); int InsertIndex = indexOf(d->TabsMenuButton);
for (auto Action : Actions) for (auto Action : Actions)
{ {
auto Button = new CTitleBarButton(true, this); auto Button = new CTitleBarButton(true, false, TitleBarButtonTabsMenu, this);
Button->setDefaultAction(Action); Button->setDefaultAction(Action);
Button->setAutoRaise(true); Button->setAutoRaise(true);
Button->setPopupMode(QToolButton::InstantPopup); Button->setPopupMode(QToolButton::InstantPopup);
@@ -533,13 +589,13 @@ void CDockAreaTitleBar::onAutoHideDockAreaActionClicked()
//============================================================================ //============================================================================
void CDockAreaTitleBar::onAutoHideToActionClicked() void CDockAreaTitleBar::onAutoHideToActionClicked()
{ {
int Location = sender()->property(LocationProperty).toInt(); int Location = sender()->property(internal::LocationProperty).toInt();
d->DockArea->toggleAutoHide((SideBarLocation)Location); d->DockArea->toggleAutoHide((SideBarLocation)Location);
} }
//============================================================================ //============================================================================
QAbstractButton* CDockAreaTitleBar::button(TitleBarButton which) const CTitleBarButton* CDockAreaTitleBar::button(TitleBarButton which) const
{ {
switch (which) switch (which)
{ {
@@ -547,6 +603,7 @@ QAbstractButton* CDockAreaTitleBar::button(TitleBarButton which) const
case TitleBarButtonUndock: return d->UndockButton; case TitleBarButtonUndock: return d->UndockButton;
case TitleBarButtonClose: return d->CloseButton; case TitleBarButtonClose: return d->CloseButton;
case TitleBarButtonAutoHide: return d->AutoHideButton; case TitleBarButtonAutoHide: return d->AutoHideButton;
case TitleBarButtonMinimize: return d->MinimizeButton;
default: default:
return nullptr; return nullptr;
} }
@@ -677,6 +734,28 @@ void CDockAreaTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
} }
//============================================================================
void CDockAreaTitleBar::setAreaFloating()
{
// If this is the last dock area in a dock container it does not make
// sense to move it to a new floating widget and leave this one
// empty.
auto DockContainer = d->DockArea->dockContainer();
if (DockContainer->isFloating() && DockContainer->dockAreaCount() == 1
&& !d->DockArea->isAutoHide())
{
return;
}
if (!d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
{
return;
}
d->makeAreaFloating(mapFromGlobal(QCursor::pos()), DraggingInactive);
}
//============================================================================ //============================================================================
void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev) void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev)
{ {
@@ -686,24 +765,35 @@ void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev)
return; return;
} }
const bool isAutoHide = d->DockArea->isAutoHide(); auto Menu = buildContextMenu(nullptr);
Menu->exec(ev->globalPos());
delete Menu;
}
QMenu* CDockAreaTitleBar::buildContextMenu(QMenu *Menu)
{
const bool isAutoHide = d->DockArea->isAutoHide();
const bool isTopLevelArea = d->DockArea->isTopLevelArea(); const bool isTopLevelArea = d->DockArea->isTopLevelArea();
QAction* Action; QAction* Action;
QMenu Menu(this); if (Menu == nullptr)
if (!isTopLevelArea) {
Menu = new QMenu(this);
}
if (!isTopLevelArea)
{ {
Action = Menu.addAction(isAutoHide ? tr("Detach") : tr("Detach Group"), Action = Menu->addAction(isAutoHide ? tr("Detach") : tr("Detach Group"),
this, SLOT(onUndockButtonClicked())); this, SLOT(onUndockButtonClicked()));
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable)); Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable));
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled)) if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
{ {
Action = Menu.addAction(isAutoHide ? tr("Unpin (Dock)") : tr("Pin Group"), this, SLOT(onAutoHideDockAreaActionClicked())); Action = Menu->addAction(isAutoHide ? tr("Unpin (Dock)") : tr("Pin Group"), this, SLOT(onAutoHideDockAreaActionClicked()));
auto AreaIsPinnable = d->DockArea->features().testFlag(CDockWidget::DockWidgetPinnable); auto AreaIsPinnable = d->DockArea->features().testFlag(CDockWidget::DockWidgetPinnable);
Action->setEnabled(AreaIsPinnable); Action->setEnabled(AreaIsPinnable);
if (!isAutoHide) if (!isAutoHide)
{ {
auto menu = Menu.addMenu(tr("Pin Group To...")); auto menu = Menu->addMenu(tr("Pin Group To..."));
menu->setEnabled(AreaIsPinnable); menu->setEnabled(AreaIsPinnable);
d->createAutoHideToAction(tr("Top"), SideBarTop, menu); d->createAutoHideToAction(tr("Top"), SideBarTop, menu);
d->createAutoHideToAction(tr("Left"), SideBarLeft, menu); d->createAutoHideToAction(tr("Left"), SideBarLeft, menu);
@@ -711,18 +801,27 @@ void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev)
d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu); d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu);
} }
} }
Menu.addSeparator(); Menu->addSeparator();
} }
Action = Menu.addAction(isAutoHide ? tr("Close") : tr("Close Group"), this, SLOT(onCloseButtonClicked()));
if (isAutoHide)
{
Action = Menu->addAction(tr("Minimize"), this, SLOT(minimizeAutoHideContainer()));
Action = Menu->addAction(tr("Close"), this, SLOT(onAutoHideCloseActionTriggered()));
}
else
{
Action = Menu->addAction(isAutoHide ? tr("Close") : tr("Close Group"), this, SLOT(onCloseButtonClicked()));
}
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable)); Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable));
if (!isAutoHide && !isTopLevelArea) if (!isAutoHide && !isTopLevelArea)
{ {
Action = Menu.addAction(tr("Close Other Groups"), d->DockArea, SLOT(closeOtherAreas())); Action = Menu->addAction(tr("Close Other Groups"), d->DockArea, SLOT(closeOtherAreas()));
} }
Menu.exec(ev->globalPos()); return Menu;
} }
//============================================================================ //============================================================================
void CDockAreaTitleBar::insertWidget(int index, QWidget *widget) void CDockAreaTitleBar::insertWidget(int index, QWidget *widget)
{ {
@@ -760,7 +859,8 @@ QString CDockAreaTitleBar::titleBarButtonToolTip(TitleBarButton Button) const
case TitleBarButtonClose: case TitleBarButtonClose:
if (d->DockArea->isAutoHide()) if (d->DockArea->isAutoHide())
{ {
return tr("Close"); bool Minimize = CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideCloseButtonCollapsesDock);
return Minimize ? tr("Minimize") : tr("Close");
} }
if (CDockManager::testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab)) if (CDockManager::testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
@@ -780,11 +880,36 @@ QString CDockAreaTitleBar::titleBarButtonToolTip(TitleBarButton Button) const
return QString(); return QString();
} }
//============================================================================ //============================================================================
CTitleBarButton::CTitleBarButton(bool visible, QWidget* parent) void CDockAreaTitleBar::showAutoHideControls(bool Show)
{
d->TabBar->setVisible(!Show); // Auto hide toolbar never has tabs
d->MinimizeButton->setVisible(Show);
d->AutoHideTitleLabel->setVisible(Show);
}
//============================================================================
bool CDockAreaTitleBar::isAutoHide() const
{
return d->DockArea && d->DockArea->isAutoHide();
}
//============================================================================
CDockAreaWidget* CDockAreaTitleBar::dockAreaWidget() const
{
return d->DockArea;
}
//============================================================================
CTitleBarButton::CTitleBarButton(bool showInTitleBar, bool hideWhenDisabled, TitleBarButton ButtonId, QWidget* parent)
: tTitleBarButton(parent), : tTitleBarButton(parent),
Visible(visible), ShowInTitleBar(showInTitleBar),
HideWhenDisabled(CDockManager::testConfigFlag(CDockManager::DockAreaHideDisabledButtons)) HideWhenDisabled(CDockManager::testConfigFlag(CDockManager::DockAreaHideDisabledButtons) && hideWhenDisabled),
TitleBarButtonId(ButtonId)
{ {
setFocusPolicy(Qt::NoFocus); setFocusPolicy(Qt::NoFocus);
} }
@@ -792,8 +917,8 @@ CTitleBarButton::CTitleBarButton(bool visible, QWidget* parent)
//============================================================================ //============================================================================
void CTitleBarButton::setVisible(bool visible) void CTitleBarButton::setVisible(bool visible)
{ {
// 'visible' can stay 'true' if and only if this button is configured to generaly visible: // 'visible' can stay 'true' if and only if this button is configured to generally visible:
visible = visible && this->Visible; visible = visible && this->ShowInTitleBar;
// 'visible' can stay 'true' unless: this button is configured to be invisible when it is disabled and it is currently disabled: // 'visible' can stay 'true' unless: this button is configured to be invisible when it is disabled and it is currently disabled:
if (visible && HideWhenDisabled) if (visible && HideWhenDisabled)
@@ -804,19 +929,62 @@ void CTitleBarButton::setVisible(bool visible)
Super::setVisible(visible); Super::setVisible(visible);
} }
//============================================================================
void CTitleBarButton::setShowInTitleBar(bool Show)
{
this->ShowInTitleBar = Show;
if (!Show)
{
setVisible(false);
}
}
//============================================================================ //============================================================================
bool CTitleBarButton::event(QEvent *ev) bool CTitleBarButton::event(QEvent *ev)
{ {
if (QEvent::EnabledChange == ev->type() && HideWhenDisabled) if (QEvent::EnabledChange != ev->type() || !HideWhenDisabled || !ShowInTitleBar)
{ {
// force setVisible() call return Super::event(ev);
// Calling setVisible() directly here doesn't work well when button is expected to be shown first time
QMetaObject::invokeMethod(this, "setVisible", Qt::QueuedConnection, Q_ARG(bool, isEnabled()));
} }
bool Show = true;
if (isInAutoHideArea())
{
switch (TitleBarButtonId)
{
case TitleBarButtonClose: Show = CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideHasCloseButton); break;
case TitleBarButtonUndock: Show = false; break;
default:
break;
}
}
// force setVisible() call - Calling setVisible() directly here doesn't
// work well when button is expected to be shown first time
QMetaObject::invokeMethod(this, "setVisible", Qt::QueuedConnection,
Q_ARG(bool, isEnabledTo(this->parentWidget()) & Show));
return Super::event(ev); return Super::event(ev);
} }
//============================================================================
CDockAreaTitleBar* CTitleBarButton::titleBar() const
{
return qobject_cast<CDockAreaTitleBar*>(parentWidget());
}
//============================================================================
bool CTitleBarButton::isInAutoHideArea() const
{
auto TitleBar = titleBar();
return TitleBar && TitleBar->isAutoHide();
}
//============================================================================ //============================================================================
CSpacerWidget::CSpacerWidget(QWidget* Parent /*= 0*/) : Super(Parent) CSpacerWidget::CSpacerWidget(QWidget* Parent /*= 0*/) : Super(Parent)
{ {
@@ -824,6 +992,7 @@ CSpacerWidget::CSpacerWidget(QWidget* Parent /*= 0*/) : Super(Parent)
setStyleSheet("border: none; background: none;"); setStyleSheet("border: none; background: none;");
} }
} // namespace ads } // namespace ads
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -30,6 +30,7 @@
//============================================================================ //============================================================================
// INCLUDES // INCLUDES
//============================================================================ //============================================================================
#include <QToolButton>
#include <QFrame> #include <QFrame>
#include "ads_globals.h" #include "ads_globals.h"
@@ -42,6 +43,63 @@ class CDockAreaTabBar;
class CDockAreaWidget; class CDockAreaWidget;
struct DockAreaTitleBarPrivate; struct DockAreaTitleBarPrivate;
class CElidingLabel; class CElidingLabel;
class CDockAreaTitleBar;
using tTitleBarButton = QToolButton;
/**
* Title bar button of a dock area that customizes tTitleBarButton appearance/behaviour
* according to various config flags such as:
* CDockManager::DockAreaHas_xxx_Button - if set to 'false' keeps the button always invisible
* CDockManager::DockAreaHideDisabledButtons - if set to 'true' hides button when it is disabled
*/
class CTitleBarButton : public tTitleBarButton
{
Q_OBJECT
private:
bool ShowInTitleBar = true;
bool HideWhenDisabled = false;
TitleBarButton TitleBarButtonId;
public:
using Super = tTitleBarButton;
CTitleBarButton(bool ShowInTitleBar, bool HideWhenDisabled, TitleBarButton ButtonId,
QWidget* parent = nullptr);
/**
* Adjust this visibility change request with our internal settings:
*/
virtual void setVisible(bool visible) override;
/**
* Configures, if the title bar button should be shown in title bar
*/
void setShowInTitleBar(bool Show);
/**
* Identifier for the title bar button
*/
TitleBarButton buttonId() const {return TitleBarButtonId;}
/**
* Return the title bar that contains this button
*/
CDockAreaTitleBar* titleBar() const;
/**
* Returns true, if the button is in a title bar in an auto hide area
*/
bool isInAutoHideArea() const;
protected:
/**
* Handle EnabledChanged signal to set button invisible if the configured
*/
bool event(QEvent *ev) override;
};
/** /**
* Title bar of a dock area. * Title bar of a dock area.
@@ -58,6 +116,8 @@ private:
private Q_SLOTS: private Q_SLOTS:
void onTabsMenuAboutToShow(); void onTabsMenuAboutToShow();
void onCloseButtonClicked(); void onCloseButtonClicked();
void onAutoHideCloseActionTriggered();
void minimizeAutoHideContainer();
void onUndockButtonClicked(); void onUndockButtonClicked();
void onTabsMenuActionTriggered(QAction* Action); void onTabsMenuActionTriggered(QAction* Action);
void onCurrentTabChanged(int Index); void onCurrentTabChanged(int Index);
@@ -92,6 +152,11 @@ protected:
*/ */
virtual void contextMenuEvent(QContextMenuEvent *event) override; virtual void contextMenuEvent(QContextMenuEvent *event) override;
/**
* Handle resize events
*/
virtual void resizeEvent(QResizeEvent *event) override;
public Q_SLOTS: public Q_SLOTS:
/** /**
* Call this slot to tell the title bar that it should update the tabs menu * Call this slot to tell the title bar that it should update the tabs menu
@@ -121,13 +186,18 @@ public:
/** /**
* Returns the button corresponding to the given title bar button identifier * Returns the button corresponding to the given title bar button identifier
*/ */
QAbstractButton* button(TitleBarButton which) const; CTitleBarButton* button(TitleBarButton which) const;
/** /**
* Returns the auto hide title label, used when the dock area is expanded and auto hidden * Returns the auto hide title label, used when the dock area is expanded and auto hidden
*/ */
CElidingLabel* autoHideTitleLabel() const; CElidingLabel* autoHideTitleLabel() const;
/**
* Returns the dock area widget that contains this title bar
*/
CDockAreaWidget* dockAreaWidget() const;
/** /**
* Updates the visibility of the dock widget actions in the title bar * Updates the visibility of the dock widget actions in the title bar
*/ */
@@ -163,6 +233,36 @@ public:
*/ */
QString titleBarButtonToolTip(TitleBarButton Button) const; QString titleBarButtonToolTip(TitleBarButton Button) const;
/**
* Moves the dock area into its own floating widget if the area
* DockWidgetFloatable flag is true
*/
void setAreaFloating();
/**
* Call this function, to create all the required auto hide controls
*/
void showAutoHideControls(bool Show);
/**
* Returns true, if the auto hide controls are visible
*/
bool isAutoHide() const;
/**
* Fills the provided menu with standard entries. If a nullptr is passed, a
* new menu is created and filled with standard entries.
* This function is called from the actual version of contextMenuEvent, but
* can be called from any code. Caller is responsible of deleting the created
* object.
*
* @param menu The QMenu to fill with standard entries. If nullptr, a new
* QMenu will be created.
* @return The filled QMenu, either the provided one or a newly created one if
* nullptr was passed.
*/
virtual QMenu *buildContextMenu(QMenu *);
Q_SIGNALS: Q_SIGNALS:
/** /**
* This signal is emitted if a tab in the tab bar is clicked by the user * This signal is emitted if a tab in the tab bar is clicked by the user

View File

@@ -31,43 +31,12 @@
// INCLUDES // INCLUDES
//============================================================================ //============================================================================
#include <QFrame> #include <QFrame>
#include <QToolButton>
#include "ads_globals.h" #include "ads_globals.h"
namespace ads namespace ads
{ {
using tTitleBarButton = QToolButton;
/**
* Title bar button of a dock area that customizes tTitleBarButton appearance/behaviour
* according to various config flags such as:
* CDockManager::DockAreaHas_xxx_Button - if set to 'false' keeps the button always invisible
* CDockManager::DockAreaHideDisabledButtons - if set to 'true' hides button when it is disabled
*/
class CTitleBarButton : public tTitleBarButton
{
Q_OBJECT
private:
bool Visible = true;
bool HideWhenDisabled = false;
public:
using Super = tTitleBarButton;
CTitleBarButton(bool visible = true, QWidget* parent = nullptr);
/**
* Adjust this visibility change request with our internal settings:
*/
virtual void setVisible(bool visible) override;
protected:
/**
* Handle EnabledChanged signal to set button invisible if the configured
*/
bool event(QEvent *ev) override;
};
/** /**
@@ -83,7 +52,7 @@ class CSpacerWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
using Super = QWidget; using Super = QWidget;
CSpacerWidget(QWidget* Parent = 0); CSpacerWidget(QWidget* Parent = nullptr);
virtual QSize sizeHint() const override {return QSize(0, 0);} virtual QSize sizeHint() const override {return QSize(0, 0);}
virtual QSize minimumSizeHint() const override {return QSize(0, 0);} virtual QSize minimumSizeHint() const override {return QSize(0, 0);}
}; };

View File

@@ -34,7 +34,6 @@
#include <QStackedLayout> #include <QStackedLayout>
#include <QScrollBar> #include <QScrollBar>
#include <QWheelEvent>
#include <QStyle> #include <QStyle>
#include <QPushButton> #include <QPushButton>
#include <QDebug> #include <QDebug>
@@ -81,7 +80,7 @@ class CDockAreaLayout
{ {
private: private:
QBoxLayout* m_ParentLayout; QBoxLayout* m_ParentLayout;
QList<QWidget*> m_Widgets; QList<QPointer<QWidget>> m_Widgets;
int m_CurrentIndex = -1; int m_CurrentIndex = -1;
QWidget* m_CurrentWidget = nullptr; QWidget* m_CurrentWidget = nullptr;
@@ -317,12 +316,12 @@ struct DockAreaWidgetPrivate
} }
/** /**
* Udpates the enable state of the close and detach button * Updates the enable state of the close and detach button
*/ */
void updateTitleBarButtonStates(); void updateTitleBarButtonStates();
/** /**
* Udpates the enable state of the close and detach button * Updates the enable state of the close and detach button
*/ */
void updateTitleBarButtonVisibility(bool isTopLevel); void updateTitleBarButtonVisibility(bool isTopLevel);
@@ -370,10 +369,21 @@ void DockAreaWidgetPrivate::updateTitleBarButtonStates()
return; return;
} }
TitleBar->button(TitleBarButtonClose)->setEnabled( if (_this->isAutoHide())
_this->features().testFlag(CDockWidget::DockWidgetClosable)); {
TitleBar->button(TitleBarButtonUndock)->setEnabled( if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideHasCloseButton))
_this->features().testFlag(CDockWidget::DockWidgetFloatable)); {
TitleBar->button(TitleBarButtonClose)->setEnabled(
_this->features().testFlag(CDockWidget::DockWidgetClosable));
}
}
else
{
TitleBar->button(TitleBarButtonUndock)->setEnabled(
_this->features().testFlag(CDockWidget::DockWidgetFloatable));
TitleBar->button(TitleBarButtonClose)->setEnabled(
_this->features().testFlag(CDockWidget::DockWidgetClosable));
}
TitleBar->button(TitleBarButtonAutoHide)->setEnabled( TitleBar->button(TitleBarButtonAutoHide)->setEnabled(
_this->features().testFlag(CDockWidget::DockWidgetPinnable)); _this->features().testFlag(CDockWidget::DockWidgetPinnable));
TitleBar->updateDockWidgetActionsButtons(); TitleBar->updateDockWidgetActionsButtons();
@@ -390,20 +400,30 @@ void DockAreaWidgetPrivate::updateTitleBarButtonVisibility(bool IsTopLevel)
return; return;
} }
if (IsTopLevel) bool IsAutoHide = _this->isAutoHide();
if (IsAutoHide)
{
bool ShowCloseButton = CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideHasCloseButton);
TitleBar->button(TitleBarButtonClose)->setVisible(ShowCloseButton);
TitleBar->button(TitleBarButtonAutoHide)->setVisible(true);
TitleBar->button(TitleBarButtonUndock)->setVisible(false);
TitleBar->button(TitleBarButtonTabsMenu)->setVisible(false);
}
else if (IsTopLevel)
{ {
TitleBar->button(TitleBarButtonClose)->setVisible(!container->isFloating()); TitleBar->button(TitleBarButtonClose)->setVisible(!container->isFloating());
TitleBar->button(TitleBarButtonAutoHide)->setVisible(!container->isFloating()); TitleBar->button(TitleBarButtonAutoHide)->setVisible(!container->isFloating());
// Undock and tabs should never show when auto hidden // Undock and tabs should never show when auto hidden
TitleBar->button(TitleBarButtonUndock)->setVisible(!container->isFloating() && !_this->isAutoHide()); TitleBar->button(TitleBarButtonUndock)->setVisible(!container->isFloating());
TitleBar->button(TitleBarButtonTabsMenu)->setVisible(!_this->isAutoHide()); TitleBar->button(TitleBarButtonTabsMenu)->setVisible(true);
} }
else else
{ {
TitleBar->button(TitleBarButtonClose)->setVisible(true); TitleBar->button(TitleBarButtonClose)->setVisible(true);
TitleBar->button(TitleBarButtonAutoHide)->setVisible(true); bool ShowAutoHideButton = CDockManager::testAutoHideConfigFlag(CDockManager::DockAreaHasAutoHideButton);
TitleBar->button(TitleBarButtonUndock)->setVisible(!_this->isAutoHide()); TitleBar->button(TitleBarButtonAutoHide)->setVisible(ShowAutoHideButton);
TitleBar->button(TitleBarButtonTabsMenu)->setVisible(!_this->isAutoHide()); TitleBar->button(TitleBarButtonUndock)->setVisible(true);
TitleBar->button(TitleBarButtonTabsMenu)->setVisible(true);
} }
} }
@@ -455,6 +475,13 @@ CAutoHideDockContainer* CDockAreaWidget::autoHideDockContainer() const
return d->AutoHideDockContainer; return d->AutoHideDockContainer;
} }
//============================================================================
CDockSplitter* CDockAreaWidget::parentSplitter() const
{
return internal::findParent<CDockSplitter*>(this);
}
//============================================================================ //============================================================================
bool CDockAreaWidget::isAutoHide() const bool CDockAreaWidget::isAutoHide() const
{ {
@@ -467,6 +494,7 @@ void CDockAreaWidget::setAutoHideDockContainer(CAutoHideDockContainer* AutoHideD
d->AutoHideDockContainer = AutoHideDockContainer; d->AutoHideDockContainer = AutoHideDockContainer;
updateAutoHideButtonCheckState(); updateAutoHideButtonCheckState();
updateTitleBarButtonsToolTips(); updateTitleBarButtonsToolTips();
d->TitleBar->button(TitleBarButtonAutoHide)->setShowInTitleBar(true);
} }
@@ -590,7 +618,7 @@ void CDockAreaWidget::hideAreaWithNoVisibleContent()
this->toggleView(false); this->toggleView(false);
// Hide empty parent splitters // Hide empty parent splitters
auto Splitter = internal::findParent<CDockSplitter*>(this); auto Splitter = parentSplitter();
internal::hideEmptyParentSplitters(Splitter); internal::hideEmptyParentSplitters(Splitter);
//Hide empty floating widget //Hide empty floating widget
@@ -626,15 +654,7 @@ void CDockAreaWidget::hideAreaWithNoVisibleContent()
void CDockAreaWidget::onTabCloseRequested(int Index) void CDockAreaWidget::onTabCloseRequested(int Index)
{ {
ADS_PRINT("CDockAreaWidget::onTabCloseRequested " << Index); ADS_PRINT("CDockAreaWidget::onTabCloseRequested " << Index);
auto* DockWidget = dockWidget(Index); dockWidget(Index)->requestCloseDockWidget();
if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) || DockWidget->features().testFlag(CDockWidget::CustomCloseHandling))
{
DockWidget->closeDockWidgetInternal();
}
else
{
DockWidget->toggleView(false);
}
} }
@@ -747,7 +767,7 @@ int CDockAreaWidget::openDockWidgetsCount() const
int Count = 0; int Count = 0;
for (int i = 0; i < d->ContentsLayout->count(); ++i) for (int i = 0; i < d->ContentsLayout->count(); ++i)
{ {
if (!dockWidget(i)->isClosed()) if (dockWidget(i) && !dockWidget(i)->isClosed())
{ {
++Count; ++Count;
} }
@@ -763,7 +783,7 @@ QList<CDockWidget*> CDockAreaWidget::openedDockWidgets() const
for (int i = 0; i < d->ContentsLayout->count(); ++i) for (int i = 0; i < d->ContentsLayout->count(); ++i)
{ {
CDockWidget* DockWidget = dockWidget(i); CDockWidget* DockWidget = dockWidget(i);
if (!DockWidget->isClosed()) if (DockWidget && !DockWidget->isClosed())
{ {
DockWidgetList.append(dockWidget(i)); DockWidgetList.append(dockWidget(i));
} }
@@ -777,7 +797,7 @@ int CDockAreaWidget::indexOfFirstOpenDockWidget() const
{ {
for (int i = 0; i < d->ContentsLayout->count(); ++i) for (int i = 0; i < d->ContentsLayout->count(); ++i)
{ {
if (!dockWidget(i)->isClosed()) if (dockWidget(i) && !dockWidget(i)->isClosed())
{ {
return i; return i;
} }
@@ -800,7 +820,6 @@ CDockWidget* CDockAreaWidget::dockWidget(int Index) const
return qobject_cast<CDockWidget*>(d->ContentsLayout->widget(Index)); return qobject_cast<CDockWidget*>(d->ContentsLayout->widget(Index));
} }
//============================================================================ //============================================================================
void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex) void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex)
{ {
@@ -854,9 +873,7 @@ void CDockAreaWidget::updateTitleBarVisibility()
if (isAutoHideFeatureEnabled()) if (isAutoHideFeatureEnabled())
{ {
auto tabBar = d->TitleBar->tabBar(); d->TitleBar->showAutoHideControls(IsAutoHide);
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); updateTitleBarButtonVisibility(Container->topLevelDockArea() == this);
} }
} }
@@ -1290,17 +1307,17 @@ SideBarLocation CDockAreaWidget::calculateSideTabBarArea() const
case BorderHorizontalLeft: SideTab = SideBarLocation::SideBarLeft; break; case BorderHorizontalLeft: SideTab = SideBarLocation::SideBarLeft; break;
case BorderHorizontalRight: SideTab = SideBarLocation::SideBarRight; break; case BorderHorizontalRight: SideTab = SideBarLocation::SideBarRight; break;
// 3. Its touching horizontal or vertical borders // 3. It's touching horizontal or vertical borders
case BorderVertical : SideTab = SideBarLocation::SideBarBottom; break; case BorderVertical : SideTab = SideBarLocation::SideBarBottom; break;
case BorderHorizontal: SideTab = SideBarLocation::SideBarRight; break; case BorderHorizontal: SideTab = SideBarLocation::SideBarRight; break;
// 4. Its in a corner // 4. It's in a corner
case BorderTopLeft : SideTab = HorizontalOrientation ? SideBarLocation::SideBarTop : SideBarLocation::SideBarLeft; break; case BorderTopLeft : SideTab = HorizontalOrientation ? SideBarLocation::SideBarTop : SideBarLocation::SideBarLeft; break;
case BorderTopRight : SideTab = HorizontalOrientation ? SideBarLocation::SideBarTop : SideBarLocation::SideBarRight; break; case BorderTopRight : SideTab = HorizontalOrientation ? SideBarLocation::SideBarTop : SideBarLocation::SideBarRight; break;
case BorderBottomLeft : SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarLeft; break; case BorderBottomLeft : SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarLeft; break;
case BorderBottomRight : SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarRight; break; case BorderBottomRight : SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarRight; break;
// 5 Ists touching only one border // 5. It's touching only one border
case BorderLeft: SideTab = SideBarLocation::SideBarLeft; break; case BorderLeft: SideTab = SideBarLocation::SideBarLeft; break;
case BorderRight: SideTab = SideBarLocation::SideBarRight; break; case BorderRight: SideTab = SideBarLocation::SideBarRight; break;
case BorderTop: SideTab = SideBarLocation::SideBarTop; break; case BorderTop: SideTab = SideBarLocation::SideBarTop; break;
@@ -1312,7 +1329,7 @@ SideBarLocation CDockAreaWidget::calculateSideTabBarArea() const
//============================================================================ //============================================================================
void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location) void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location, int TabIndex)
{ {
if (!isAutoHideFeatureEnabled()) if (!isAutoHideFeatureEnabled())
{ {
@@ -1323,11 +1340,18 @@ void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location)
{ {
if (isAutoHide()) if (isAutoHide())
{ {
autoHideDockContainer()->moveContentsToParent(); d->AutoHideDockContainer->moveContentsToParent();
} }
return; return;
} }
// If this is already an auto hide container, then move it to new location
if (isAutoHide())
{
d->AutoHideDockContainer->moveToNewSideBarLocation(Location, TabIndex);
return;
}
auto area = (SideBarNone == Location) ? calculateSideTabBarArea() : Location; auto area = (SideBarNone == Location) ? calculateSideTabBarArea() : Location;
for (const auto DockWidget : openedDockWidgets()) for (const auto DockWidget : openedDockWidgets())
{ {
@@ -1341,7 +1365,7 @@ void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location)
continue; continue;
} }
dockContainer()->createAndSetupAutoHideContainer(area, DockWidget); dockContainer()->createAndSetupAutoHideContainer(area, DockWidget, TabIndex++);
} }
} }
@@ -1442,6 +1466,13 @@ bool CDockAreaWidget::isTopLevelArea() const
} }
//============================================================================
void CDockAreaWidget::setFloating()
{
d->TitleBar->setAreaFloating();
}
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
//============================================================================ //============================================================================
bool CDockAreaWidget::event(QEvent *e) bool CDockAreaWidget::event(QEvent *e)

View File

@@ -38,6 +38,7 @@
QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter) QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
QT_FORWARD_DECLARE_CLASS(QAbstractButton) QT_FORWARD_DECLARE_CLASS(QAbstractButton)
QT_FORWARD_DECLARE_CLASS(QMenu)
namespace ads namespace ads
{ {
@@ -47,6 +48,7 @@ class CDockContainerWidget;
class DockContainerWidgetPrivate; class DockContainerWidgetPrivate;
class CDockAreaTitleBar; class CDockAreaTitleBar;
class CDockingStateReader; class CDockingStateReader;
class CDockSplitter;
/** /**
@@ -216,12 +218,16 @@ public:
*/ */
CAutoHideDockContainer* autoHideDockContainer() const; CAutoHideDockContainer* autoHideDockContainer() const;
/**
* Returns the parent splitter that contains this dock area
*/
CDockSplitter* parentSplitter() const;
/** /**
* Returns true if the dock area is in an auto hide container * Returns true if the dock area is in an auto hide container
*/ */
bool isAutoHide() const; bool isAutoHide() const;
/** /**
* Sets the current auto hide dock container * Sets the current auto hide dock container
*/ */
@@ -401,7 +407,7 @@ public Q_SLOTS:
* If the dock area is switched to auto hide mode, then all dock widgets * If the dock area is switched to auto hide mode, then all dock widgets
* that are pinable will be added to the sidebar * that are pinable will be added to the sidebar
*/ */
void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone); void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone, int TabIndex = -1);
/** /**
* Switches the dock area to auto hide mode or vice versa depending on its * Switches the dock area to auto hide mode or vice versa depending on its
@@ -414,6 +420,12 @@ public Q_SLOTS:
*/ */
void closeOtherAreas(); void closeOtherAreas();
/**
* Moves the dock area into its own floating widget if the area
* DockWidgetFloatable flag is true
*/
void setFloating();
Q_SIGNALS: Q_SIGNALS:
/** /**
* This signal is emitted when user clicks on a tab at an index. * This signal is emitted when user clicks on a tab at an index.

View File

@@ -141,11 +141,11 @@ public:
CDockContainerWidget* _this; CDockContainerWidget* _this;
QPointer<CDockManager> DockManager; QPointer<CDockManager> DockManager;
unsigned int zOrderIndex = 0; unsigned int zOrderIndex = 0;
QList<CDockAreaWidget*> DockAreas; QList<QPointer<CDockAreaWidget>> DockAreas;
QList<CAutoHideDockContainer*> AutoHideWidgets; QList<CAutoHideDockContainer*> AutoHideWidgets;
QMap<SideBarLocation, CAutoHideSideBar*> SideTabBarWidgets; QMap<SideBarLocation, CAutoHideSideBar*> SideTabBarWidgets;
QGridLayout* Layout = nullptr; QGridLayout* Layout = nullptr;
QSplitter* RootSplitter = nullptr; CDockSplitter* RootSplitter = nullptr;
bool isFloating = false; bool isFloating = false;
CDockAreaWidget* LastAddedAreaCache[5]; CDockAreaWidget* LastAddedAreaCache[5];
int VisibleDockAreaCount = -1; int VisibleDockAreaCount = -1;
@@ -181,17 +181,29 @@ public:
*/ */
void dropIntoContainer(CFloatingDockContainer* FloatingWidget, DockWidgetArea area); void dropIntoContainer(CFloatingDockContainer* FloatingWidget, DockWidgetArea area);
/**
* Drop floating widget into auto hide side bar
*/
void dropIntoAutoHideSideBar(CFloatingDockContainer* FloatingWidget, DockWidgetArea area);
/**
* Creates a new tab for a widget dropped into the center of a section
*/
void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget,
CDockAreaWidget* TargetArea, int TabIndex = 0);
/** /**
* Drop floating widget into dock area * Drop floating widget into dock area
*/ */
void dropIntoSection(CFloatingDockContainer* FloatingWidget, void dropIntoSection(CFloatingDockContainer* FloatingWidget,
CDockAreaWidget* TargetArea, DockWidgetArea area); CDockAreaWidget* TargetArea, DockWidgetArea area, int TabIndex = 0);
/** /**
* Moves the dock widget or dock area given in Widget parameter to a * Moves the dock widget or dock area given in Widget parameter to a
* new dock widget area * new dock widget area
*/ */
void moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area); void moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area,
int TabIndex = 0);
/** /**
* Moves the dock widget or dock area given in Widget parameter to a * Moves the dock widget or dock area given in Widget parameter to a
@@ -202,13 +214,13 @@ public:
/** /**
* Creates a new tab for a widget dropped into the center of a section * Creates a new tab for a widget dropped into the center of a section
*/ */
void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget, void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea, int TabIndex = 0);
CDockAreaWidget* TargetArea);
/** /**
* Creates a new tab for a widget dropped into the center of a section * Moves the dock widget or dock area given in Widget parameter to
* a auto hide sidebar area
*/ */
void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea); void moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area, int TabIndex = TabDefaultInsertIndex);
/** /**
@@ -238,7 +250,7 @@ public:
* \param[out] CreatedWidget The widget created from parsed data or 0 if * \param[out] CreatedWidget The widget created from parsed data or 0 if
* the parsed widget was an empty splitter * the parsed widget was an empty splitter
* \param[in] Testing If Testing is true, only the stream data is * \param[in] Testing If Testing is true, only the stream data is
* parsed without modifiying anything. * parsed without modifying anything.
*/ */
bool restoreChildNodes(CDockingStateReader& Stream, QWidget*& CreatedWidget, bool restoreChildNodes(CDockingStateReader& Stream, QWidget*& CreatedWidget,
bool Testing); bool Testing);
@@ -287,7 +299,11 @@ public:
VisibleDockAreaCount = 0; VisibleDockAreaCount = 0;
for (auto DockArea : DockAreas) for (auto DockArea : DockAreas)
{ {
VisibleDockAreaCount += DockArea->isHidden() ? 0 : 1; if (!DockArea)
{
continue;
}
VisibleDockAreaCount += (DockArea->isHidden() ? 0 : 1);
} }
} }
@@ -454,7 +470,7 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
CDockContainerWidget* FloatingDockContainer = FloatingWidget->dockContainer(); CDockContainerWidget* FloatingDockContainer = FloatingWidget->dockContainer();
auto NewDockAreas = FloatingDockContainer->findChildren<CDockAreaWidget*>( auto NewDockAreas = FloatingDockContainer->findChildren<CDockAreaWidget*>(
QString(), Qt::FindChildrenRecursively); QString(), Qt::FindChildrenRecursively);
QSplitter* Splitter = RootSplitter; auto Splitter = RootSplitter;
if (DockAreas.count() <= 1) if (DockAreas.count() <= 1)
{ {
@@ -462,7 +478,7 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
} }
else if (Splitter->orientation() != InsertParam.orientation()) else if (Splitter->orientation() != InsertParam.orientation())
{ {
QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); auto NewSplitter = newSplitter(InsertParam.orientation());
QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter); QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
NewSplitter->addWidget(Splitter); NewSplitter->addWidget(Splitter);
updateSplitterHandles(NewSplitter); updateSplitterHandles(NewSplitter);
@@ -505,14 +521,33 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
} }
//============================================================================
void DockContainerWidgetPrivate::dropIntoAutoHideSideBar(CFloatingDockContainer* FloatingWidget, DockWidgetArea area)
{
auto SideBarLocation = internal::toSideBarLocation(area);
auto NewDockAreas = FloatingWidget->findChildren<CDockAreaWidget*>(
QString(), Qt::FindChildrenRecursively);
int TabIndex = DockManager->containerOverlay()->tabIndexUnderCursor();
for (auto DockArea : NewDockAreas)
{
auto DockWidgets = DockArea->dockWidgets();
for (auto DockWidget : DockWidgets)
{
_this->createAndSetupAutoHideContainer(SideBarLocation, DockWidget, TabIndex++);
}
}
}
//============================================================================ //============================================================================
void DockContainerWidgetPrivate::dropIntoCenterOfSection( void DockContainerWidgetPrivate::dropIntoCenterOfSection(
CFloatingDockContainer* FloatingWidget, CDockAreaWidget* TargetArea) CFloatingDockContainer* FloatingWidget, CDockAreaWidget* TargetArea, int TabIndex)
{ {
CDockContainerWidget* FloatingContainer = FloatingWidget->dockContainer(); CDockContainerWidget* FloatingContainer = FloatingWidget->dockContainer();
auto NewDockWidgets = FloatingContainer->dockWidgets(); auto NewDockWidgets = FloatingContainer->dockWidgets();
auto TopLevelDockArea = FloatingContainer->topLevelDockArea(); auto TopLevelDockArea = FloatingContainer->topLevelDockArea();
int NewCurrentIndex = -1; int NewCurrentIndex = -1;
TabIndex = qMax(0, TabIndex);
// If the floating widget contains only one single dock are, then the // If the floating widget contains only one single dock are, then the
// current dock widget of the dock area will also be the future current // current dock widget of the dock area will also be the future current
@@ -525,7 +560,7 @@ void DockContainerWidgetPrivate::dropIntoCenterOfSection(
for (int i = 0; i < NewDockWidgets.count(); ++i) for (int i = 0; i < NewDockWidgets.count(); ++i)
{ {
CDockWidget* DockWidget = NewDockWidgets[i]; CDockWidget* DockWidget = NewDockWidgets[i];
TargetArea->insertDockWidget(i, DockWidget, false); TargetArea->insertDockWidget(TabIndex + i, DockWidget, false);
// If the floating widget contains multiple visible dock areas, then we // If the floating widget contains multiple visible dock areas, then we
// simply pick the first visible open dock widget and make it // simply pick the first visible open dock widget and make it
// the current one. // the current one.
@@ -534,7 +569,7 @@ void DockContainerWidgetPrivate::dropIntoCenterOfSection(
NewCurrentIndex = i; NewCurrentIndex = i;
} }
} }
TargetArea->setCurrentIndex(NewCurrentIndex); TargetArea->setCurrentIndex(NewCurrentIndex + TabIndex);
TargetArea->updateTitleBarVisibility(); TargetArea->updateTitleBarVisibility();
return; return;
} }
@@ -542,13 +577,13 @@ void DockContainerWidgetPrivate::dropIntoCenterOfSection(
//============================================================================ //============================================================================
void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* FloatingWidget, void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* FloatingWidget,
CDockAreaWidget* TargetArea, DockWidgetArea area) CDockAreaWidget* TargetArea, DockWidgetArea area, int TabIndex)
{ {
// Dropping into center means all dock widgets in the dropped floating // Dropping into center means all dock widgets in the dropped floating
// widget will become tabs of the drop area // widget will become tabs of the drop area
if (CenterDockWidgetArea == area) if (CenterDockWidgetArea == area)
{ {
dropIntoCenterOfSection(FloatingWidget, TargetArea); dropIntoCenterOfSection(FloatingWidget, TargetArea, TabIndex);
return; return;
} }
@@ -556,16 +591,7 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
auto InsertParam = internal::dockAreaInsertParameters(area); auto InsertParam = internal::dockAreaInsertParameters(area);
auto NewDockAreas = FloatingContainer->findChildren<CDockAreaWidget*>( auto NewDockAreas = FloatingContainer->findChildren<CDockAreaWidget*>(
QString(), Qt::FindChildrenRecursively); QString(), Qt::FindChildrenRecursively);
QSplitter* TargetAreaSplitter = internal::findParent<QSplitter*>(TargetArea); auto TargetAreaSplitter = TargetArea->parentSplitter();
if (!TargetAreaSplitter)
{
QSplitter* Splitter = newSplitter(InsertParam.orientation());
Layout->replaceWidget(TargetArea, Splitter);
Splitter->addWidget(TargetArea);
updateSplitterHandles(Splitter);
TargetAreaSplitter = Splitter;
}
int AreaIndex = TargetAreaSplitter->indexOf(TargetArea); int AreaIndex = TargetAreaSplitter->indexOf(TargetArea);
auto FloatingSplitter = FloatingContainer->rootSplitter(); auto FloatingSplitter = FloatingContainer->rootSplitter();
if (TargetAreaSplitter->orientation() == InsertParam.orientation()) if (TargetAreaSplitter->orientation() == InsertParam.orientation())
@@ -638,11 +664,13 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
//============================================================================ //============================================================================
void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea) void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea,
int TabIndex)
{ {
auto DroppedDockWidget = qobject_cast<CDockWidget*>(Widget); auto DroppedDockWidget = qobject_cast<CDockWidget*>(Widget);
auto DroppedArea = qobject_cast<CDockAreaWidget*>(Widget); auto DroppedArea = qobject_cast<CDockAreaWidget*>(Widget);
TabIndex = qMax(0, TabIndex);
if (DroppedDockWidget) if (DroppedDockWidget)
{ {
CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget(); CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget();
@@ -655,7 +683,7 @@ void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockA
{ {
OldDockArea->removeDockWidget(DroppedDockWidget); OldDockArea->removeDockWidget(DroppedDockWidget);
} }
TargetArea->insertDockWidget(0, DroppedDockWidget, true); TargetArea->insertDockWidget(TabIndex, DroppedDockWidget, true);
} }
else else
{ {
@@ -664,9 +692,9 @@ void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockA
for (int i = 0; i < NewDockWidgets.count(); ++i) for (int i = 0; i < NewDockWidgets.count(); ++i)
{ {
CDockWidget* DockWidget = NewDockWidgets[i]; CDockWidget* DockWidget = NewDockWidgets[i];
TargetArea->insertDockWidget(i, DockWidget, false); TargetArea->insertDockWidget(TabIndex + i, DockWidget, false);
} }
TargetArea->setCurrentIndex(NewCurrentIndex); TargetArea->setCurrentIndex(TabIndex + NewCurrentIndex);
DroppedArea->dockContainer()->removeDockArea(DroppedArea); DroppedArea->dockContainer()->removeDockArea(DroppedArea);
DroppedArea->deleteLater(); DroppedArea->deleteLater();
} }
@@ -677,13 +705,14 @@ void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockA
//============================================================================ //============================================================================
void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area) void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area,
int TabIndex)
{ {
// Dropping into center means all dock widgets in the dropped floating // Dropping into center means all dock widgets in the dropped floating
// widget will become tabs of the drop area // widget will become tabs of the drop area
if (CenterDockWidgetArea == area) if (CenterDockWidgetArea == area)
{ {
moveIntoCenterOfSection(Widget, TargetArea); moveIntoCenterOfSection(Widget, TargetArea, TabIndex);
return; return;
} }
@@ -708,7 +737,7 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg
} }
auto InsertParam = internal::dockAreaInsertParameters(area); auto InsertParam = internal::dockAreaInsertParameters(area);
QSplitter* TargetAreaSplitter = internal::findParent<QSplitter*>(TargetArea); auto TargetAreaSplitter = TargetArea->parentSplitter();
int AreaIndex = TargetAreaSplitter->indexOf(TargetArea); int AreaIndex = TargetAreaSplitter->indexOf(TargetArea);
auto Sizes = TargetAreaSplitter->sizes(); auto Sizes = TargetAreaSplitter->sizes();
if (TargetAreaSplitter->orientation() == InsertParam.orientation()) if (TargetAreaSplitter->orientation() == InsertParam.orientation())
@@ -738,6 +767,48 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg
} }
//============================================================================
void DockContainerWidgetPrivate::moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area, int TabIndex)
{
CDockWidget* DroppedDockWidget = qobject_cast<CDockWidget*>(Widget);
CDockAreaWidget* DroppedDockArea = qobject_cast<CDockAreaWidget*>(Widget);
auto SideBarLocation = internal::toSideBarLocation(area);
if (DroppedDockWidget)
{
if (_this == DroppedDockWidget->dockContainer())
{
DroppedDockWidget->setAutoHide(true, SideBarLocation, TabIndex);
}
else
{
_this->createAndSetupAutoHideContainer(SideBarLocation, DroppedDockWidget, TabIndex);
}
}
else
{
if (_this == DroppedDockArea->dockContainer())
{
DroppedDockArea->setAutoHide(true, SideBarLocation, TabIndex);
}
else
{
for (const auto DockWidget : DroppedDockArea->openedDockWidgets())
{
if (!DockWidget->features().testFlag(
CDockWidget::DockWidgetPinnable))
{
continue;
}
_this->createAndSetupAutoHideContainer(SideBarLocation,
DockWidget, TabIndex++);
}
}
}
}
//============================================================================ //============================================================================
void DockContainerWidgetPrivate::updateSplitterHandles( QSplitter* splitter ) void DockContainerWidgetPrivate::updateSplitterHandles( QSplitter* splitter )
{ {
@@ -801,7 +872,7 @@ void DockContainerWidgetPrivate::moveToContainer(QWidget* Widget, DockWidgetArea
// it already has and do nothing, if it is the same place. It would // it already has and do nothing, if it is the same place. It would
// also work without this check, but it looks nicer with the check // also work without this check, but it looks nicer with the check
// because there will be no layout updates // because there will be no layout updates
auto Splitter = internal::findParent<CDockSplitter*>(DroppedDockArea); auto Splitter = DroppedDockArea->parentSplitter();
auto InsertParam = internal::dockAreaInsertParameters(area); auto InsertParam = internal::dockAreaInsertParameters(area);
if (Splitter == RootSplitter && InsertParam.orientation() == Splitter->orientation()) if (Splitter == RootSplitter && InsertParam.orientation() == Splitter->orientation())
{ {
@@ -857,7 +928,10 @@ void DockContainerWidgetPrivate::addDockAreasToList(const QList<CDockAreaWidget*
//============================================================================ //============================================================================
void DockContainerWidgetPrivate::appendDockAreas(const QList<CDockAreaWidget*> NewDockAreas) void DockContainerWidgetPrivate::appendDockAreas(const QList<CDockAreaWidget*> NewDockAreas)
{ {
DockAreas.append(NewDockAreas); for (auto *newDockArea : NewDockAreas)
{
DockAreas.append(newDockArea);
}
for (auto DockArea : NewDockAreas) for (auto DockArea : NewDockAreas)
{ {
QObject::connect(DockArea, QObject::connect(DockArea,
@@ -908,7 +982,7 @@ void DockContainerWidgetPrivate::saveAutoHideWidgetsState(QXmlStreamWriter& s)
{ {
for (const auto sideTabBar : SideTabBarWidgets.values()) for (const auto sideTabBar : SideTabBarWidgets.values())
{ {
if (!sideTabBar->tabCount()) if (!sideTabBar->count())
{ {
continue; continue;
} }
@@ -1101,12 +1175,12 @@ bool DockContainerWidgetPrivate::restoreSideBar(CDockingStateReader& s,
continue; continue;
} }
auto SideBar = _this->sideTabBar(Area); auto SideBar = _this->autoHideSideBar(Area);
CAutoHideDockContainer* AutoHideContainer; CAutoHideDockContainer* AutoHideContainer;
if (DockWidget->isAutoHide()) if (DockWidget->isAutoHide())
{ {
AutoHideContainer = DockWidget->autoHideDockContainer(); AutoHideContainer = DockWidget->autoHideDockContainer();
if (AutoHideContainer->sideBar() != SideBar) if (AutoHideContainer->autoHideSideBar() != SideBar)
{ {
SideBar->addAutoHideWidget(AutoHideContainer); SideBar->addAutoHideWidget(AutoHideContainer);
} }
@@ -1193,7 +1267,7 @@ void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockW
} }
else else
{ {
QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); auto NewSplitter = newSplitter(InsertParam.orientation());
if (InsertParam.append()) if (InsertParam.append())
{ {
QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter); QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
@@ -1288,7 +1362,7 @@ CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetA
NewDockArea->addDockWidget(Dockwidget); NewDockArea->addDockWidget(Dockwidget);
auto InsertParam = internal::dockAreaInsertParameters(area); auto InsertParam = internal::dockAreaInsertParameters(area);
QSplitter* TargetAreaSplitter = internal::findParent<QSplitter*>(TargetDockArea); auto TargetAreaSplitter = TargetDockArea->parentSplitter();
int index = TargetAreaSplitter ->indexOf(TargetDockArea); int index = TargetAreaSplitter ->indexOf(TargetDockArea);
if (TargetAreaSplitter->orientation() == InsertParam.orientation()) if (TargetAreaSplitter->orientation() == InsertParam.orientation())
{ {
@@ -1305,7 +1379,7 @@ CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetA
{ {
ADS_PRINT("TargetAreaSplitter->orientation() != InsertParam.orientation()"); ADS_PRINT("TargetAreaSplitter->orientation() != InsertParam.orientation()");
auto TargetAreaSizes = TargetAreaSplitter->sizes(); auto TargetAreaSizes = TargetAreaSplitter->sizes();
QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); auto NewSplitter = newSplitter(InsertParam.orientation());
NewSplitter->addWidget(TargetDockArea); NewSplitter->addWidget(TargetDockArea);
insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append()); insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append());
@@ -1404,7 +1478,7 @@ CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockW
//============================================================================ //============================================================================
CAutoHideDockContainer* CDockContainerWidget::createAndSetupAutoHideContainer( CAutoHideDockContainer* CDockContainerWidget::createAndSetupAutoHideContainer(
SideBarLocation area, CDockWidget* DockWidget) SideBarLocation area, CDockWidget* DockWidget, int TabIndex)
{ {
if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled)) if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
{ {
@@ -1417,7 +1491,7 @@ CAutoHideDockContainer* CDockContainerWidget::createAndSetupAutoHideContainer(
DockWidget->setDockManager(d->DockManager); // Auto hide Dock Container needs a valid dock manager DockWidget->setDockManager(d->DockManager); // Auto hide Dock Container needs a valid dock manager
} }
return sideTabBar(area)->insertDockWidget(-1, DockWidget); return autoHideSideBar(area)->insertDockWidget(TabIndex, DockWidget);
} }
@@ -1496,7 +1570,7 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
area->disconnect(this); area->disconnect(this);
d->DockAreas.removeAll(area); d->DockAreas.removeAll(area);
CDockSplitter* Splitter = internal::findParent<CDockSplitter*>(area); auto Splitter = area->parentSplitter();
// Remove are from parent splitter and recursively hide tree of parent // Remove are from parent splitter and recursively hide tree of parent
// splitters if it has no visible content // splitters if it has no visible content
@@ -1528,7 +1602,7 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
} }
QWidget* widget = Splitter->widget(0); QWidget* widget = Splitter->widget(0);
QSplitter* ChildSplitter = qobject_cast<QSplitter*>(widget); auto ChildSplitter = qobject_cast<CDockSplitter*>(widget);
// If the one and only content widget of the splitter is not a splitter // If the one and only content widget of the splitter is not a splitter
// then we are finished // then we are finished
if (!ChildSplitter) if (!ChildSplitter)
@@ -1569,12 +1643,21 @@ emitAndExit:
} }
//============================================================================
QList<QPointer<CDockAreaWidget>> CDockContainerWidget::removeAllDockAreas()
{
auto Result = d->DockAreas;
d->DockAreas.clear();
return Result;
}
//============================================================================ //============================================================================
CDockAreaWidget* CDockContainerWidget::dockAreaAt(const QPoint& GlobalPos) const CDockAreaWidget* CDockContainerWidget::dockAreaAt(const QPoint& GlobalPos) const
{ {
for (const auto& DockArea : d->DockAreas) for (const auto& DockArea : d->DockAreas)
{ {
if (DockArea->isVisible() && DockArea->rect().contains(DockArea->mapFromGlobal(GlobalPos))) if (DockArea && DockArea->isVisible() && DockArea->rect().contains(DockArea->mapFromGlobal(GlobalPos)))
{ {
return DockArea; return DockArea;
} }
@@ -1611,7 +1694,7 @@ int CDockContainerWidget::visibleDockAreaCount() const
int Result = 0; int Result = 0;
for (auto DockArea : d->DockAreas) for (auto DockArea : d->DockAreas)
{ {
Result += DockArea->isHidden() ? 0 : 1; Result += (!DockArea || DockArea->isHidden()) ? 0 : 1;
} }
return Result; return Result;
@@ -1629,11 +1712,12 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
ADS_PRINT("CDockContainerWidget::dropFloatingWidget"); ADS_PRINT("CDockContainerWidget::dropFloatingWidget");
CDockWidget* SingleDroppedDockWidget = FloatingWidget->topLevelDockWidget(); CDockWidget* SingleDroppedDockWidget = FloatingWidget->topLevelDockWidget();
CDockWidget* SingleDockWidget = topLevelDockWidget(); CDockWidget* SingleDockWidget = topLevelDockWidget();
CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
auto dropArea = InvalidDockWidgetArea; auto dropArea = InvalidDockWidgetArea;
auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
bool Dropped = false; bool Dropped = false;
CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
// mouse is over dock area
if (DockArea) if (DockArea)
{ {
auto dropOverlay = d->DockManager->dockAreaOverlay(); auto dropOverlay = d->DockManager->dockAreaOverlay();
@@ -1648,35 +1732,40 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
if (dropArea != InvalidDockWidgetArea) if (dropArea != InvalidDockWidgetArea)
{ {
ADS_PRINT("Dock Area Drop Content: " << dropArea); ADS_PRINT("Dock Area Drop Content: " << dropArea);
d->dropIntoSection(FloatingWidget, DockArea, dropArea); int TabIndex = d->DockManager->dockAreaOverlay()->tabIndexUnderCursor();
d->dropIntoSection(FloatingWidget, DockArea, dropArea, TabIndex);
Dropped = true; Dropped = true;
} }
} }
// mouse is over container // mouse is over container or auto hide side bar
if (InvalidDockWidgetArea == dropArea) if (InvalidDockWidgetArea == dropArea && InvalidDockWidgetArea != ContainerDropArea)
{ {
dropArea = ContainerDropArea; if (internal::isSideBarArea(ContainerDropArea))
ADS_PRINT("Container Drop Content: " << dropArea); {
if (dropArea != InvalidDockWidgetArea) ADS_PRINT("Container Drop Content: " << ContainerDropArea);
{ d->dropIntoAutoHideSideBar(FloatingWidget, ContainerDropArea);
d->dropIntoContainer(FloatingWidget, dropArea); }
Dropped = true; else
} {
ADS_PRINT("Container Drop Content: " << ContainerDropArea);
d->dropIntoContainer(FloatingWidget, ContainerDropArea);
}
Dropped = true;
} }
// Remove the auto hide widgets from the FloatingWidget and insert // Remove the auto hide widgets from the FloatingWidget and insert
// them into this widget // them into this widget
for (auto AutohideWidget : FloatingWidget->dockContainer()->autoHideWidgets()) for (auto AutohideWidget : FloatingWidget->dockContainer()->autoHideWidgets())
{ {
auto SideBar = sideTabBar(AutohideWidget->sideBarLocation()); auto SideBar = autoHideSideBar(AutohideWidget->sideBarLocation());
SideBar->addAutoHideWidget(AutohideWidget); SideBar->addAutoHideWidget(AutohideWidget);
} }
if (Dropped) if (Dropped)
{ {
// Fix https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/351 // Fix https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/351
FloatingWidget->hideAndDeleteLater(); FloatingWidget->finishDropOperation();
// If we dropped a floating widget with only one single dock widget, then we // If we dropped a floating widget with only one single dock widget, then we
// drop a top level widget that changes from floating to docked now // drop a top level widget that changes from floating to docked now
@@ -1697,12 +1786,17 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
//============================================================================ //============================================================================
void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget) void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget,
int TabIndex)
{ {
CDockWidget* SingleDockWidget = topLevelDockWidget(); CDockWidget* SingleDockWidget = topLevelDockWidget();
if (TargetAreaWidget) if (TargetAreaWidget)
{ {
d->moveToNewSection(Widget, TargetAreaWidget, DropArea); d->moveToNewSection(Widget, TargetAreaWidget, DropArea, TabIndex);
}
else if (internal::isSideBarArea(DropArea))
{
d->moveToAutoHideSideBar(Widget, DropArea, TabIndex);
} }
else else
{ {
@@ -1724,7 +1818,7 @@ QList<CDockAreaWidget*> CDockContainerWidget::openedDockAreas() const
QList<CDockAreaWidget*> Result; QList<CDockAreaWidget*> Result;
for (auto DockArea : d->DockAreas) for (auto DockArea : d->DockAreas)
{ {
if (!DockArea->isHidden()) if (DockArea && !DockArea->isHidden())
{ {
Result.append(DockArea); Result.append(DockArea);
} }
@@ -1740,7 +1834,7 @@ QList<CDockWidget*> CDockContainerWidget::openedDockWidgets() const
QList<CDockWidget*> DockWidgetList; QList<CDockWidget*> DockWidgetList;
for (auto DockArea : d->DockAreas) for (auto DockArea : d->DockAreas)
{ {
if (!DockArea->isHidden()) if (DockArea && !DockArea->isHidden())
{ {
DockWidgetList.append(DockArea->openedDockWidgets()); DockWidgetList.append(DockArea->openedDockWidgets());
} }
@@ -1755,7 +1849,7 @@ bool CDockContainerWidget::hasOpenDockAreas() const
{ {
for (auto DockArea : d->DockAreas) for (auto DockArea : d->DockAreas)
{ {
if (!DockArea->isHidden()) if (DockArea && !DockArea->isHidden())
{ {
return true; return true;
} }
@@ -1845,17 +1939,18 @@ bool CDockContainerWidget::restoreState(CDockingStateReader& s, bool Testing)
NewRootSplitter = d->newSplitter(Qt::Horizontal); NewRootSplitter = d->newSplitter(Qt::Horizontal);
} }
d->Layout->replaceWidget(d->RootSplitter, NewRootSplitter); QLayoutItem* li = d->Layout->replaceWidget(d->RootSplitter, NewRootSplitter);
QSplitter* OldRoot = d->RootSplitter; auto OldRoot = d->RootSplitter;
d->RootSplitter = qobject_cast<QSplitter*>(NewRootSplitter); d->RootSplitter = qobject_cast<CDockSplitter*>(NewRootSplitter);
OldRoot->deleteLater(); OldRoot->deleteLater();
delete li;
return true; return true;
} }
//============================================================================ //============================================================================
QSplitter* CDockContainerWidget::rootSplitter() const CDockSplitter* CDockContainerWidget::rootSplitter() const
{ {
return d->RootSplitter; return d->RootSplitter;
} }
@@ -1977,8 +2072,12 @@ CDockAreaWidget* CDockContainerWidget::topLevelDockArea() const
QList<CDockWidget*> CDockContainerWidget::dockWidgets() const QList<CDockWidget*> CDockContainerWidget::dockWidgets() const
{ {
QList<CDockWidget*> Result; QList<CDockWidget*> Result;
for (const auto DockArea : d->DockAreas) for (const auto& DockArea : d->DockAreas)
{ {
if (!DockArea)
{
continue;
}
Result.append(DockArea->dockWidgets()); Result.append(DockArea->dockWidgets());
} }
@@ -2009,8 +2108,12 @@ void CDockContainerWidget::removeAutoHideWidget(CAutoHideDockContainer* Autohide
CDockWidget::DockWidgetFeatures CDockContainerWidget::features() const CDockWidget::DockWidgetFeatures CDockContainerWidget::features() const
{ {
CDockWidget::DockWidgetFeatures Features(CDockWidget::AllDockWidgetFeatures); CDockWidget::DockWidgetFeatures Features(CDockWidget::AllDockWidgetFeatures);
for (const auto DockArea : d->DockAreas) for (const auto& DockArea : d->DockAreas)
{ {
if (!DockArea)
{
continue;
}
Features &= DockArea->features(); Features &= DockArea->features();
} }
@@ -2028,9 +2131,9 @@ CFloatingDockContainer* CDockContainerWidget::floatingWidget() const
//============================================================================ //============================================================================
void CDockContainerWidget::closeOtherAreas(CDockAreaWidget* KeepOpenArea) void CDockContainerWidget::closeOtherAreas(CDockAreaWidget* KeepOpenArea)
{ {
for (const auto DockArea : d->DockAreas) for (const auto& DockArea : d->DockAreas)
{ {
if (DockArea == KeepOpenArea) if (!DockArea || DockArea == KeepOpenArea)
{ {
continue; continue;
} }
@@ -2051,7 +2154,7 @@ void CDockContainerWidget::closeOtherAreas(CDockAreaWidget* KeepOpenArea)
} }
//============================================================================ //============================================================================
CAutoHideSideBar* CDockContainerWidget::sideTabBar(SideBarLocation area) const CAutoHideSideBar* CDockContainerWidget::autoHideSideBar(SideBarLocation area) const
{ {
return d->SideTabBarWidgets[area]; return d->SideTabBarWidgets[area];
} }
@@ -2065,7 +2168,21 @@ QRect CDockContainerWidget::contentRect() const
return QRect(); return QRect();
} }
return d->RootSplitter->geometry(); if (d->RootSplitter->hasVisibleContent())
{
return d->RootSplitter->geometry();
}
else
{
auto ContentRect = this->rect();
ContentRect.adjust(
autoHideSideBar(SideBarLeft)->sizeHint().width(),
autoHideSideBar(SideBarTop)->sizeHint().height(),
-autoHideSideBar(SideBarRight)->sizeHint().width(),
-autoHideSideBar(SideBarBottom)->sizeHint().height());
return ContentRect;
}
} }

View File

@@ -53,6 +53,7 @@ struct FloatingDragPreviewPrivate;
class CDockingStateReader; class CDockingStateReader;
class CAutoHideSideBar; class CAutoHideSideBar;
class CAutoHideTab; class CAutoHideTab;
class CDockSplitter;
struct AutoHideTabPrivate; struct AutoHideTabPrivate;
struct AutoHideDockContainerPrivate; struct AutoHideDockContainerPrivate;
@@ -94,14 +95,14 @@ protected:
/** /**
* Access function for the internal root splitter * Access function for the internal root splitter
*/ */
QSplitter* rootSplitter() const; CDockSplitter* rootSplitter() const;
/** /**
* Creates and initializes a dockwidget auto hide container into the given area. * Creates and initializes a dockwidget auto hide container into the given area.
* Initializing inserts the tabs into the side tab widget and hides it * 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 * Returns nullptr if you try and insert into an area where the configuration is not enabled
*/ */
CAutoHideDockContainer* createAndSetupAutoHideContainer(SideBarLocation area, CDockWidget* DockWidget); CAutoHideDockContainer* createAndSetupAutoHideContainer(SideBarLocation area, CDockWidget* DockWidget, int TabIndex = -1);
/** /**
* Helper function for creation of the root splitter * Helper function for creation of the root splitter
@@ -125,7 +126,8 @@ protected:
* a nullptr, then the DropArea indicates the drop area in the given * a nullptr, then the DropArea indicates the drop area in the given
* TargetAreaWidget * TargetAreaWidget
*/ */
void dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget); void dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget,
int TabIndex = -1);
/** /**
* Adds the given dock area to this container widget * Adds the given dock area to this container widget
@@ -137,6 +139,11 @@ protected:
*/ */
void removeDockArea(CDockAreaWidget* area); void removeDockArea(CDockAreaWidget* area);
/**
* Remove all dock areas and returns the list of removed dock areas
*/
QList<QPointer<CDockAreaWidget>> removeAllDockAreas();
/** /**
* Saves the state into the given stream * Saves the state into the given stream
*/ */
@@ -322,7 +329,7 @@ public:
/** /**
* Returns the side tab widget for the given area * Returns the side tab widget for the given area
*/ */
CAutoHideSideBar* sideTabBar(SideBarLocation area) const; CAutoHideSideBar* autoHideSideBar(SideBarLocation area) const;
/** /**

View File

@@ -115,6 +115,7 @@ DockFocusControllerPrivate::DockFocusControllerPrivate(
//============================================================================ //============================================================================
void DockFocusControllerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget) void DockFocusControllerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget)
{ {
if (!DockWidget) return;
if (!DockWidget->features().testFlag(CDockWidget::DockWidgetFocusable)) if (!DockWidget->features().testFlag(CDockWidget::DockWidgetFocusable))
{ {
return; return;
@@ -269,7 +270,7 @@ void CDockFocusController::onApplicationFocusChanged(QWidget* focusedOld, QWidge
Q_UNUSED(focusedOld); Q_UNUSED(focusedOld);
// Ignore focus changes if we are restoring state, or if user clicked // Ignore focus changes if we are restoring state, or if user clicked
// a tab wich in turn caused the focus change // a tab which in turn caused the focus change
if (d->DockManager->isRestoringState() || d->TabPressed) if (d->DockManager->isRestoringState() || d->TabPressed)
{ {
return; return;

View File

@@ -48,6 +48,7 @@
#include <QApplication> #include <QApplication>
#include <QWindow> #include <QWindow>
#include <QWindowStateChangeEvent> #include <QWindowStateChangeEvent>
#include <QVector>
#include "FloatingDockContainer.h" #include "FloatingDockContainer.h"
#include "DockOverlay.h" #include "DockOverlay.h"
@@ -94,6 +95,7 @@ enum eStateFileVersion
static CDockManager::ConfigFlags StaticConfigFlags = CDockManager::DefaultNonOpaqueConfig; static CDockManager::ConfigFlags StaticConfigFlags = CDockManager::DefaultNonOpaqueConfig;
static CDockManager::AutoHideFlags StaticAutoHideConfigFlags; // auto hide feature is disabled by default static CDockManager::AutoHideFlags StaticAutoHideConfigFlags; // auto hide feature is disabled by default
static QVector<QVariant> StaticConfigParams(CDockManager::ConfigParamCount);
static QString FloatingContainersTitle; static QString FloatingContainersTitle;
@@ -103,8 +105,8 @@ static QString FloatingContainersTitle;
struct DockManagerPrivate struct DockManagerPrivate
{ {
CDockManager* _this; CDockManager* _this;
QList<CFloatingDockContainer*> FloatingWidgets; QList<QPointer<CFloatingDockContainer>> FloatingWidgets;
QList<CFloatingDockContainer*> HiddenFloatingWidgets; QList<QPointer<CFloatingDockContainer>> HiddenFloatingWidgets;
QList<CDockContainerWidget*> Containers; QList<CDockContainerWidget*> Containers;
CDockOverlay* ContainerOverlay; CDockOverlay* ContainerOverlay;
CDockOverlay* DockAreaOverlay; CDockOverlay* DockAreaOverlay;
@@ -118,6 +120,11 @@ struct DockManagerPrivate
CDockFocusController* FocusController = nullptr; CDockFocusController* FocusController = nullptr;
CDockWidget* CentralWidget = nullptr; CDockWidget* CentralWidget = nullptr;
bool IsLeavingMinimized = false; bool IsLeavingMinimized = false;
Qt::ToolButtonStyle ToolBarStyleDocked = Qt::ToolButtonIconOnly;
Qt::ToolButtonStyle ToolBarStyleFloating = Qt::ToolButtonTextUnderIcon;
QSize ToolBarIconSizeDocked = QSize(16, 16);
QSize ToolBarIconSizeFloating = QSize(24, 24);
CDockWidget::DockWidgetFeatures LockedDockWidgetFeatures;
/** /**
* Private data constructor * Private data constructor
@@ -149,7 +156,10 @@ struct DockManagerPrivate
// Hide updates of floating widgets from user // Hide updates of floating widgets from user
for (auto FloatingWidget : FloatingWidgets) for (auto FloatingWidget : FloatingWidgets)
{ {
FloatingWidget->hide(); if (FloatingWidget)
{
FloatingWidget->hide();
}
} }
} }
@@ -329,7 +339,8 @@ bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int versi
int FloatingWidgetIndex = DockContainerCount - 1; int FloatingWidgetIndex = DockContainerCount - 1;
for (int i = FloatingWidgetIndex; i < FloatingWidgets.count(); ++i) for (int i = FloatingWidgetIndex; i < FloatingWidgets.count(); ++i)
{ {
auto* floatingWidget = FloatingWidgets[i]; CFloatingDockContainer* floatingWidget = FloatingWidgets[i];
if (!floatingWidget) continue;
_this->removeDockContainer(floatingWidget->dockContainer()); _this->removeDockContainer(floatingWidget->dockContainer());
floatingWidget->deleteLater(); floatingWidget->deleteLater();
} }
@@ -532,25 +543,41 @@ CDockManager::CDockManager(QWidget *parent) :
CDockManager::~CDockManager() CDockManager::~CDockManager()
{ {
// fix memory leaks, see https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/307 // fix memory leaks, see https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/307
std::vector<ads::CDockAreaWidget*> areas; std::vector<QPointer<ads::CDockAreaWidget>> areas;
for ( int i = 0; i != dockAreaCount(); ++i ) for (int i = 0; i != dockAreaCount(); ++i)
{ {
areas.push_back( dockArea(i) ); areas.push_back( dockArea(i) );
} }
for ( auto area : areas ) for ( auto area : areas )
{ {
for ( auto widget : area->dockWidgets() ) if (!area || area->dockManager() != this) continue;
delete widget;
delete area; // QPointer delete safety - just in case some dock wigdet in destruction
} // deletes another related/twin or child dock widget.
std::vector<QPointer<QWidget>> deleteWidgets;
for ( auto widget : area->dockWidgets() )
{
deleteWidgets.push_back(widget);
}
for ( auto ptrWdg : deleteWidgets)
{
delete ptrWdg;
}
}
auto FloatingWidgets = d->FloatingWidgets; auto FloatingWidgets = d->FloatingWidgets;
for (auto FloatingWidget : FloatingWidgets) for (auto FloatingWidget : FloatingWidgets)
{ {
FloatingWidget->deleteContent();
delete FloatingWidget; delete FloatingWidget;
} }
// Delete Dock Widgets before Areas so widgets can access them late (like dtor)
for ( auto area : areas )
{
delete area;
}
delete d; delete d;
} }
@@ -564,7 +591,7 @@ bool CDockManager::eventFilter(QObject *obj, QEvent *e)
// Window always on top of the MainWindow. // Window always on top of the MainWindow.
if (e->type() == QEvent::WindowActivate) if (e->type() == QEvent::WindowActivate)
{ {
for (auto _window : floatingWidgets()) for (auto _window : d->FloatingWidgets)
{ {
if (!_window->isVisible() || window()->isMinimized()) if (!_window->isVisible() || window()->isMinimized())
{ {
@@ -586,7 +613,7 @@ bool CDockManager::eventFilter(QObject *obj, QEvent *e)
} }
else if (e->type() == QEvent::WindowDeactivate) else if (e->type() == QEvent::WindowDeactivate)
{ {
for (auto _window : floatingWidgets()) for (auto _window : d->FloatingWidgets)
{ {
if (!_window->isVisible() || window()->isMinimized()) if (!_window->isVisible() || window()->isMinimized())
{ {
@@ -609,7 +636,7 @@ bool CDockManager::eventFilter(QObject *obj, QEvent *e)
// Sync minimize with MainWindow // Sync minimize with MainWindow
if (e->type() == QEvent::WindowStateChange) if (e->type() == QEvent::WindowStateChange)
{ {
for (auto _window : floatingWidgets()) for (auto _window : d->FloatingWidgets)
{ {
if (! _window->isVisible()) if (! _window->isVisible())
{ {
@@ -721,7 +748,12 @@ const QList<CDockContainerWidget*> CDockManager::dockContainers() const
//============================================================================ //============================================================================
const QList<CFloatingDockContainer*> CDockManager::floatingWidgets() const const QList<CFloatingDockContainer*> CDockManager::floatingWidgets() const
{ {
return d->FloatingWidgets; QList<CFloatingDockContainer*> res;
for (auto &fl : d->FloatingWidgets)
{
if (fl) res.append(fl);
}
return res;
} }
@@ -1121,7 +1153,7 @@ QAction* CDockManager::addToggleViewActionToMenu(QAction* ToggleViewAction,
bool AlphabeticallySorted = (MenuAlphabeticallySorted == d->MenuInsertionOrder); bool AlphabeticallySorted = (MenuAlphabeticallySorted == d->MenuInsertionOrder);
if (!Group.isEmpty()) if (!Group.isEmpty())
{ {
QMenu* GroupMenu = d->ViewMenuGroups.value(Group, 0); QMenu* GroupMenu = d->ViewMenuGroups.value(Group, nullptr);
if (!GroupMenu) if (!GroupMenu)
{ {
GroupMenu = new QMenu(Group, this); GroupMenu = new QMenu(Group, this);
@@ -1285,7 +1317,7 @@ void CDockManager::hideManagerAndFloatingWidgets()
d->HiddenFloatingWidgets.push_back( FloatingWidget ); d->HiddenFloatingWidgets.push_back( FloatingWidget );
FloatingWidget->hide(); FloatingWidget->hide();
// hidding floating widget automatically marked contained CDockWidgets as hidden // hiding floating widget automatically marked contained CDockWidgets as hidden
// but they must remain marked as visible as we want them to be restored visible // but they must remain marked as visible as we want them to be restored visible
// when CDockManager will be shown back // when CDockManager will be shown back
for ( auto dockWidget : VisibleWidgets ) for ( auto dockWidget : VisibleWidgets )
@@ -1314,7 +1346,7 @@ QList<int> CDockManager::splitterSizes(CDockAreaWidget *ContainedArea) const
{ {
if (ContainedArea) if (ContainedArea)
{ {
auto Splitter = internal::findParent<CDockSplitter*>(ContainedArea); auto Splitter = ContainedArea->parentSplitter();
if (Splitter) if (Splitter)
{ {
return Splitter->sizes(); return Splitter->sizes();
@@ -1331,7 +1363,7 @@ void CDockManager::setSplitterSizes(CDockAreaWidget *ContainedArea, const QList<
return; return;
} }
auto Splitter = internal::findParent<CDockSplitter*>(ContainedArea); auto Splitter = ContainedArea->parentSplitter();
if (Splitter && Splitter->count() == sizes.count()) if (Splitter && Splitter->count() == sizes.count())
{ {
Splitter->setSizes(sizes); Splitter->setSizes(sizes);
@@ -1361,6 +1393,104 @@ QString CDockManager::floatingContainersTitle()
return FloatingContainersTitle; return FloatingContainersTitle;
} }
//===========================================================================
void CDockManager::setDockWidgetToolBarStyle(Qt::ToolButtonStyle Style, CDockWidget::eState State)
{
if (CDockWidget::StateFloating == State)
{
d->ToolBarStyleFloating = Style;
}
else
{
d->ToolBarStyleDocked = Style;
}
}
//===========================================================================
Qt::ToolButtonStyle CDockManager::dockWidgetToolBarStyle(CDockWidget::eState State) const
{
if (CDockWidget::StateFloating == State)
{
return d->ToolBarStyleFloating;
}
else
{
return d->ToolBarStyleDocked;
}
}
//===========================================================================
void CDockManager::setDockWidgetToolBarIconSize(const QSize& IconSize, CDockWidget::eState State)
{
if (CDockWidget::StateFloating == State)
{
d->ToolBarIconSizeFloating = IconSize;
}
else
{
d->ToolBarIconSizeDocked = IconSize;
}
}
//===========================================================================
QSize CDockManager::dockWidgetToolBarIconSize(CDockWidget::eState State) const
{
if (CDockWidget::StateFloating == State)
{
return d->ToolBarIconSizeFloating;
}
else
{
return d->ToolBarIconSizeDocked;
}
}
//===========================================================================
void CDockManager::lockDockWidgetFeaturesGlobally(CDockWidget::DockWidgetFeatures Value)
{
// Limit the features to CDockWidget::GloballyLockableFeatures
Value &= CDockWidget::GloballyLockableFeatures;
if (d->LockedDockWidgetFeatures == Value)
{
return;
}
d->LockedDockWidgetFeatures = Value;
// Call the notifyFeaturesChanged() function for all dock widgets to update
// the state of the close and detach buttons
for (auto DockWidget : d->DockWidgetsMap)
{
DockWidget->notifyFeaturesChanged();
}
}
//===========================================================================
CDockWidget::DockWidgetFeatures CDockManager::globallyLockedDockWidgetFeatures() const
{
return d->LockedDockWidgetFeatures;
}
//===========================================================================
void CDockManager::setConfigParam(CDockManager::eConfigParam Param, QVariant Value)
{
StaticConfigParams[Param] = Value;
}
//===========================================================================
QVariant CDockManager::configParam(eConfigParam Param, QVariant Default)
{
return StaticConfigParams[Param].isValid() ? StaticConfigParams[Param] : Default;
}
} // namespace ads } // namespace ads
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -55,6 +55,8 @@ class CIconProvider;
class CDockComponentsFactory; class CDockComponentsFactory;
class CDockFocusController; class CDockFocusController;
class CAutoHideSideBar; class CAutoHideSideBar;
class CAutoHideTab;
struct AutoHideTabPrivate;
/** /**
* The central dock manager that maintains the complete docking system. * The central dock manager that maintains the complete docking system.
@@ -87,6 +89,8 @@ private:
friend class CDockAreaTitleBar; friend class CDockAreaTitleBar;
friend class CAutoHideDockContainer; friend class CAutoHideDockContainer;
friend CAutoHideSideBar; friend CAutoHideSideBar;
friend CAutoHideTab;
friend AutoHideTabPrivate;
public Q_SLOTS: public Q_SLOTS:
/** /**
@@ -150,7 +154,7 @@ protected:
virtual void showEvent(QShowEvent *event) override; virtual void showEvent(QShowEvent *event) override;
/** /**
* Acces for the internal dock focus controller. * Access for the internal dock focus controller.
* This function only returns a valid object, if the FocusHighlighting * This function only returns a valid object, if the FocusHighlighting
* flag is set. * flag is set.
*/ */
@@ -209,6 +213,8 @@ public:
//!< If neither this nor FloatingContainerForceNativeTitleBar is set (the default) native titlebars are used except on known bad systems. //!< If neither this nor FloatingContainerForceNativeTitleBar is set (the default) native titlebars are used except on known bad systems.
//! Users can overwrite this by setting the environment variable ADS_UseNativeTitle to "1" or "0". //! Users can overwrite this by setting the environment variable ADS_UseNativeTitle to "1" or "0".
MiddleMouseButtonClosesTab = 0x2000000, //! If the flag is set, the user can use the mouse middle button to close the tab under the mouse MiddleMouseButtonClosesTab = 0x2000000, //! If the flag is set, the user can use the mouse middle button to close the tab under the mouse
DisableTabTextEliding = 0x4000000, //! Set this flag to disable eliding of tab texts in dock area tabs
ShowTabTextOnlyForActiveTab =0x8000000, //! Set this flag to show label texts in dock area tabs only for active tabs
DefaultDockAreaButtons = DockAreaHasCloseButton DefaultDockAreaButtons = DockAreaHasCloseButton
| DockAreaHasUndockButton | DockAreaHasUndockButton
@@ -246,12 +252,26 @@ public:
AutoHideSideBarsIconOnly = 0x10,///< show only icons in auto hide side tab - if a tab has no icon, then the text will be shown AutoHideSideBarsIconOnly = 0x10,///< show only icons in auto hide side tab - if a tab has no icon, then the text will be shown
AutoHideShowOnMouseOver = 0x20, ///< show the auto hide window on mouse over tab and hide it if mouse leaves auto hide container AutoHideShowOnMouseOver = 0x20, ///< show the auto hide window on mouse over tab and hide it if mouse leaves auto hide container
AutoHideCloseButtonCollapsesDock = 0x40, ///< Close button of an auto hide container collapses the dock instead of hiding it completely AutoHideCloseButtonCollapsesDock = 0x40, ///< Close button of an auto hide container collapses the dock instead of hiding it completely
AutoHideHasCloseButton = 0x80, //< If the flag is set an auto hide title bar has a close button
AutoHideHasMinimizeButton = 0x100, ///< if this flag is set, the auto hide title bar has a minimize button to collapse the dock widget
AutoHideOpenOnDragHover = 0x200, ///< if this flag is set, dragging hover the tab bar will open the dock
DefaultAutoHideConfig = AutoHideFeatureEnabled DefaultAutoHideConfig = AutoHideFeatureEnabled
| DockAreaHasAutoHideButton ///< the default configuration for left and right side bars | DockAreaHasAutoHideButton
| AutoHideHasMinimizeButton
}; };
Q_DECLARE_FLAGS(AutoHideFlags, eAutoHideFlag) Q_DECLARE_FLAGS(AutoHideFlags, eAutoHideFlag)
/**
* Global configuration parameters that you can set via setConfigParam()
*/
enum eConfigParam
{
AutoHideOpenOnDragHoverDelay_ms, ///< Delay in ms before the dock opens on drag hover if AutoHideOpenOnDragHover flag is set
ConfigParamCount // just a delimiter to count number of config params
};
/** /**
* Default Constructor. * Default Constructor.
@@ -313,6 +333,17 @@ public:
*/ */
static bool testAutoHideConfigFlag(eAutoHideFlag Flag); static bool testAutoHideConfigFlag(eAutoHideFlag Flag);
/**
* Sets the value for the given config parameter
*/
static void setConfigParam(eConfigParam Param, QVariant Value);
/**
* Returns the value for the given config parameter or the default value
* if the parameter is not set.
*/
static QVariant configParam(eConfigParam Param, QVariant Default);
/** /**
* Returns the global icon provider. * Returns the global icon provider.
* The icon provider enables the use of custom icons in case using * The icon provider enables the use of custom icons in case using
@@ -535,7 +566,7 @@ public:
* The order defines how the actions are added to the view menu. * The order defines how the actions are added to the view menu.
* The default insertion order is MenuAlphabeticallySorted to make it * The default insertion order is MenuAlphabeticallySorted to make it
* easier for users to find the menu entry for a certain dock widget. * easier for users to find the menu entry for a certain dock widget.
* You need to call this function befor you insert the first menu item * You need to call this function before you insert the first menu item
* into the view menu. * into the view menu.
*/ */
void setViewMenuInsertionOrder(eViewMenuInsertionOrder Order); void setViewMenuInsertionOrder(eViewMenuInsertionOrder Order);
@@ -620,6 +651,68 @@ public:
*/ */
static QString floatingContainersTitle(); static QString floatingContainersTitle();
/**
* This function sets the tool button style for the given dock widget state.
* It is possible to switch the tool button style depending on the state.
* If a dock widget is floating, then here are more space and it is
* possible to select a style that requires more space like
* Qt::ToolButtonTextUnderIcon. For the docked state Qt::ToolButtonIconOnly
* might be better.
*/
void setDockWidgetToolBarStyle(Qt::ToolButtonStyle Style, CDockWidget::eState State);
/**
* Returns the tool button style for the given docking state.
* \see setToolBarStyle()
*/
Qt::ToolButtonStyle dockWidgetToolBarStyle(CDockWidget::eState State) const;
/**
* This function sets the tool button icon size for the given state.
* If a dock widget is floating, there is more space and increasing the
* icon size is possible. For docked widgets, small icon sizes, eg. 16 x 16
* might be better.
*/
void setDockWidgetToolBarIconSize(const QSize& IconSize, CDockWidget::eState State);
/**
* Returns the icon size for a given docking state.
* \see setToolBarIconSize()
*/
QSize dockWidgetToolBarIconSize(CDockWidget::eState State) const;
/**
* Returns all dock widget features that are globally locked by the dock
* manager.
* Globally locked features are removed from the features of all dock
* widgets.
*/
CDockWidget::DockWidgetFeatures globallyLockedDockWidgetFeatures() const;
/**
* Globally Lock features of all dock widgets to "freeze" the current
* workspace layout.
* For example, it is now possible to lock the workspace to avoid
* accidentally dragging a docked view. Locking wasnt possible before.
* So, users had to manually dock it back to the desired place after
* each accidental undock.
* You can use a combination of the following feature flags:
* - CDockWidget::DockWidgetClosable
* - CDockWidget::DockWidgetMovable
* - CDockWidget::DockWidgetFloatable
* - CDockWidget::DockWidgetPinable
*
* To clear the locked features, you can use CDockWidget::NoDockWidgetFeatures
* The following code shows how to lock and unlock dock widget features
* globally.
*
* \code
* DockManager->lockDockWidgetFeaturesGlobally();
* DockManager->lockDockWidgetFeaturesGlobally(CDockWidget::NoDockWidgetFeatures);
* \code
*/
void lockDockWidgetFeaturesGlobally(CDockWidget::DockWidgetFeatures Features = CDockWidget::GloballyLockableFeatures);
public Q_SLOTS: public Q_SLOTS:
/** /**
* Opens the perspective with the given name. * Opens the perspective with the given name.

View File

@@ -38,11 +38,18 @@
#include "DockAreaWidget.h" #include "DockAreaWidget.h"
#include "DockAreaTitleBar.h" #include "DockAreaTitleBar.h"
#include "DockContainerWidget.h"
#include "AutoHideSideBar.h"
#include "DockManager.h"
#include "DockAreaTabBar.h"
#include <iostream> #include <iostream>
namespace ads namespace ads
{ {
static const int AutoHideAreaWidth = 32;
static const int AutoHideAreaMouseZone = 8;
static const int InvalidTabIndex = -2;
/** /**
* Private data class of CDockOverlay * Private data class of CDockOverlay
@@ -57,11 +64,23 @@ struct DockOverlayPrivate
bool DropPreviewEnabled = true; bool DropPreviewEnabled = true;
CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay; CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay;
QRect DropAreaRect; QRect DropAreaRect;
int TabIndex = InvalidTabIndex;
/** /**
* Private data constructor * Private data constructor
*/ */
DockOverlayPrivate(CDockOverlay* _public) : _this(_public) {} DockOverlayPrivate(CDockOverlay* _public) : _this(_public) {}
/**
* Returns the overlay width / height depending on the visibility
* of the sidebar
*/
int sideBarOverlaySize(SideBarLocation sideBarLocation);
/**
* The area where the mouse is considered in the sidebar
*/
int sideBarMouseZone(SideBarLocation sideBarLocation);
}; };
/** /**
@@ -155,8 +174,20 @@ struct DockOverlayCrossPrivate
QLabel* l = new QLabel(); QLabel* l = new QLabel();
l->setObjectName("DockWidgetAreaLabel"); l->setObjectName("DockWidgetAreaLabel");
const qreal metric = dropIndicatiorWidth(l); qreal metric = dropIndicatiorWidth(l);
const QSizeF size(metric, metric); QSizeF size(metric, metric);
if (internal::isSideBarArea(DockWidgetArea))
{
auto SideBarLocation = internal::toSideBarLocation(DockWidgetArea);
if (internal::isHorizontalSideBarLocation(SideBarLocation))
{
size.setHeight(size.height() / 2);
}
else
{
size.setWidth(size.width() / 2);
}
}
l->setPixmap(createHighDpiDropIndicatorPixmap(size, DockWidgetArea, Mode)); l->setPixmap(createHighDpiDropIndicatorPixmap(size, DockWidgetArea, Mode));
l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
@@ -182,6 +213,11 @@ struct DockOverlayCrossPrivate
{ {
QColor borderColor = iconColor(CDockOverlayCross::FrameColor); QColor borderColor = iconColor(CDockOverlayCross::FrameColor);
QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor); QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor);
QColor overlayColor = iconColor(CDockOverlayCross::OverlayColor);
if (overlayColor.alpha() == 255)
{
overlayColor.setAlpha(64);
}
#if QT_VERSION >= 0x050600 #if QT_VERSION >= 0x050600
double DevicePixelRatio = _this->window()->devicePixelRatioF(); double DevicePixelRatio = _this->window()->devicePixelRatioF();
@@ -239,22 +275,22 @@ struct DockOverlayCrossPrivate
} }
QSizeF baseSize = baseRect.size(); QSizeF baseSize = baseRect.size();
if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea) bool IsOuterContainerArea = (CDockOverlay::ModeContainerOverlay == Mode)
&& (DockWidgetArea != CenterDockWidgetArea)
&& !internal::isSideBarArea(DockWidgetArea);
if (IsOuterContainerArea)
{ {
baseRect = areaRect; baseRect = areaRect;
} }
p.fillRect(baseRect, backgroundColor); p.fillRect(baseRect, backgroundColor);
if (areaRect.isValid()) if (areaRect.isValid())
{ {
pen = p.pen(); pen = p.pen();
pen.setColor(borderColor); pen.setColor(borderColor);
QColor Color = iconColor(CDockOverlayCross::OverlayColor); p.setBrush(overlayColor);
if (Color.alpha() == 255)
{
Color.setAlpha(64);
}
p.setBrush(Color);
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.drawRect(areaRect); p.drawRect(areaRect);
@@ -267,6 +303,7 @@ struct DockOverlayCrossPrivate
} }
p.restore(); p.restore();
p.save(); p.save();
// Draw outer border // Draw outer border
pen = p.pen(); pen = p.pen();
@@ -282,8 +319,9 @@ struct DockOverlayCrossPrivate
p.drawRect(FrameRect); p.drawRect(FrameRect);
p.restore(); p.restore();
// Draw arrow for outer container drop indicators // Draw arrow for outer container drop indicators
if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea) if (IsOuterContainerArea)
{ {
QRectF ArrowRect; QRectF ArrowRect;
ArrowRect.setSize(baseSize); ArrowRect.setSize(baseSize);
@@ -326,6 +364,38 @@ struct DockOverlayCrossPrivate
}; };
//============================================================================
int DockOverlayPrivate::sideBarOverlaySize(SideBarLocation sideBarLocation)
{
auto Container = qobject_cast<CDockContainerWidget*>(TargetWidget.data());
auto SideBar = Container->autoHideSideBar(sideBarLocation);
if (!SideBar || !SideBar->isVisibleTo(Container))
{
return AutoHideAreaWidth;
}
else
{
return (SideBar->orientation() == Qt::Horizontal) ? SideBar->height() : SideBar->width();
}
}
//============================================================================
int DockOverlayPrivate::sideBarMouseZone(SideBarLocation sideBarLocation)
{
auto Container = qobject_cast<CDockContainerWidget*>(TargetWidget.data());
auto SideBar = Container->autoHideSideBar(sideBarLocation);
if (!SideBar || !SideBar->isVisibleTo(Container))
{
return AutoHideAreaMouseZone;
}
else
{
return (SideBar->orientation() == Qt::Horizontal) ? SideBar->height() : SideBar->width();
}
}
//============================================================================ //============================================================================
CDockOverlay::CDockOverlay(QWidget* parent, eMode Mode) : CDockOverlay::CDockOverlay(QWidget* parent, eMode Mode) :
QFrame(parent), QFrame(parent),
@@ -359,12 +429,26 @@ CDockOverlay::~CDockOverlay()
void CDockOverlay::setAllowedAreas(DockWidgetAreas areas) void CDockOverlay::setAllowedAreas(DockWidgetAreas areas)
{ {
if (areas == d->AllowedAreas) if (areas == d->AllowedAreas)
{
return; return;
}
d->AllowedAreas = areas; d->AllowedAreas = areas;
d->Cross->reset(); d->Cross->reset();
} }
//============================================================================
void CDockOverlay::setAllowedArea(DockWidgetArea area, bool Enable)
{
auto AreasOld = d->AllowedAreas;
d->AllowedAreas.setFlag(area, Enable);
if (AreasOld != d->AllowedAreas)
{
d->Cross->reset();
}
}
//============================================================================ //============================================================================
DockWidgetAreas CDockOverlay::allowedAreas() const DockWidgetAreas CDockOverlay::allowedAreas() const
{ {
@@ -375,22 +459,68 @@ DockWidgetAreas CDockOverlay::allowedAreas() const
//============================================================================ //============================================================================
DockWidgetArea CDockOverlay::dropAreaUnderCursor() const DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
{ {
d->TabIndex = InvalidTabIndex;
if (!d->TargetWidget)
{
return InvalidDockWidgetArea;
}
DockWidgetArea Result = d->Cross->cursorLocation(); DockWidgetArea Result = d->Cross->cursorLocation();
if (Result != InvalidDockWidgetArea) if (Result != InvalidDockWidgetArea)
{ {
return Result; return Result;
} }
CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(d->TargetWidget.data()); auto CursorPos = QCursor::pos();
if (!DockArea) auto DockArea = qobject_cast<CDockAreaWidget*>(d->TargetWidget.data());
if (!DockArea && CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled))
{
auto Rect = rect();
const QPoint pos = mapFromGlobal(QCursor::pos());
if ((pos.x() < d->sideBarMouseZone(SideBarLeft))
&& d->AllowedAreas.testFlag(LeftAutoHideArea))
{
Result = LeftAutoHideArea;
}
else if (pos.x() > (Rect.width() - d->sideBarMouseZone(SideBarRight))
&& d->AllowedAreas.testFlag(RightAutoHideArea))
{
Result = RightAutoHideArea;
}
else if (pos.y() < d->sideBarMouseZone(SideBarTop)
&& d->AllowedAreas.testFlag(TopAutoHideArea))
{
Result = TopAutoHideArea;
}
else if (pos.y() > (Rect.height() - d->sideBarMouseZone(SideBarBottom))
&& d->AllowedAreas.testFlag(BottomAutoHideArea))
{
Result = BottomAutoHideArea;
}
auto SideBarLocation = ads::internal::toSideBarLocation(Result);
if (SideBarLocation != SideBarNone)
{
auto Container = qobject_cast<CDockContainerWidget*>(d->TargetWidget.data());
auto SideBar = Container->autoHideSideBar(SideBarLocation);
if (SideBar->isVisible())
{
d->TabIndex = SideBar->tabInsertIndexAt(SideBar->mapFromGlobal(CursorPos));
}
}
return Result;
}
else if (!DockArea)
{ {
return Result; return Result;
} }
if (DockArea->allowedAreas().testFlag(CenterDockWidgetArea) if (DockArea->allowedAreas().testFlag(CenterDockWidgetArea)
&& !DockArea->titleBar()->isHidden() && !DockArea->titleBar()->isHidden()
&& DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(QCursor::pos()))) && DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(CursorPos)))
{ {
auto TabBar = DockArea->titleBar()->tabBar();
d->TabIndex = TabBar->tabInsertIndexAt(TabBar->mapFromGlobal(CursorPos));
return CenterDockWidgetArea; return CenterDockWidgetArea;
} }
@@ -398,6 +528,13 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
} }
//============================================================================
int CDockOverlay::tabIndexUnderCursor() const
{
return d->TabIndex;
}
//============================================================================ //============================================================================
DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const
{ {
@@ -471,6 +608,7 @@ bool CDockOverlay::dropPreviewEnabled() const
void CDockOverlay::paintEvent(QPaintEvent* event) void CDockOverlay::paintEvent(QPaintEvent* event)
{ {
Q_UNUSED(event); Q_UNUSED(event);
// Draw rect based on location // Draw rect based on location
if (!d->DropPreviewEnabled) if (!d->DropPreviewEnabled)
{ {
@@ -490,8 +628,13 @@ void CDockOverlay::paintEvent(QPaintEvent* event)
case BottomDockWidgetArea: r.setY(r.height() * (1 - 1 / Factor)); break; case BottomDockWidgetArea: r.setY(r.height() * (1 - 1 / Factor)); break;
case LeftDockWidgetArea: r.setWidth(r.width() / Factor); break; case LeftDockWidgetArea: r.setWidth(r.width() / Factor); break;
case CenterDockWidgetArea: r = rect();break; case CenterDockWidgetArea: r = rect();break;
case LeftAutoHideArea: r.setWidth(d->sideBarOverlaySize(SideBarLeft)); break;
case RightAutoHideArea: r.setX(r.width() - d->sideBarOverlaySize(SideBarRight)); break;
case TopAutoHideArea: r.setHeight(d->sideBarOverlaySize(SideBarTop)); break;
case BottomAutoHideArea: r.setY(r.height() - d->sideBarOverlaySize(SideBarBottom)); break;
default: return; default: return;
} }
QPainter painter(this); QPainter painter(this);
QColor Color = palette().color(QPalette::Active, QPalette::Highlight); QColor Color = palette().color(QPalette::Active, QPalette::Highlight);
QPen Pen = painter.pen(); QPen Pen = painter.pen();
@@ -627,6 +770,7 @@ void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode)
areaWidgets.insert(BottomDockWidgetArea, d->createDropIndicatorWidget(BottomDockWidgetArea, Mode)); areaWidgets.insert(BottomDockWidgetArea, d->createDropIndicatorWidget(BottomDockWidgetArea, Mode));
areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode)); areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode));
areaWidgets.insert(CenterDockWidgetArea, d->createDropIndicatorWidget(CenterDockWidgetArea, Mode)); areaWidgets.insert(CenterDockWidgetArea, d->createDropIndicatorWidget(CenterDockWidgetArea, Mode));
#if QT_VERSION >= 0x050600 #if QT_VERSION >= 0x050600
d->LastDevicePixelRatio = devicePixelRatioF(); d->LastDevicePixelRatio = devicePixelRatioF();
#else #else

View File

@@ -72,6 +72,11 @@ public:
*/ */
void setAllowedAreas(DockWidgetAreas areas); void setAllowedAreas(DockWidgetAreas areas);
/**
* Enable / disable a certain area
*/
void setAllowedArea(DockWidgetArea area, bool Enable);
/** /**
* Returns flags with all allowed drop areas * Returns flags with all allowed drop areas
*/ */
@@ -82,6 +87,17 @@ public:
*/ */
DockWidgetArea dropAreaUnderCursor() const; DockWidgetArea dropAreaUnderCursor() const;
/**
* If the drop area is the CenterDockWidgetArea or a sidebar area,
* then this function returns the index of the tab under cursor.
* Call this function after call to dropAreaUnderCursor() because this
* function updates the tab index.
* A value of -1 indicates a position before the first tab and a value of
* tabCount() indicates a position behind the last tab.
* A value of -2 indicates an valid value
*/
int tabIndexUnderCursor() const;
/** /**
* This function returns the same like dropAreaUnderCursor() if this * This function returns the same like dropAreaUnderCursor() if this
* overlay is not hidden and if drop preview is enabled and returns * overlay is not hidden and if drop preview is enabled and returns

View File

@@ -39,7 +39,7 @@ struct DockSplitterPrivate;
/** /**
* Splitter used internally instead of QSplitter with some additional * Splitter used internally instead of QSplitter with some additional
* fuctionality. * functionality.
*/ */
class ADS_EXPORT CDockSplitter : public QSplitter class ADS_EXPORT CDockSplitter : public QSplitter
{ {

View File

@@ -80,8 +80,8 @@ struct DockWidgetPrivate
QWidget* Widget = nullptr; QWidget* Widget = nullptr;
CDockWidgetTab* TabWidget = nullptr; CDockWidgetTab* TabWidget = nullptr;
CDockWidget::DockWidgetFeatures Features = CDockWidget::DefaultDockWidgetFeatures; CDockWidget::DockWidgetFeatures Features = CDockWidget::DefaultDockWidgetFeatures;
CDockManager* DockManager = nullptr; QPointer<CDockManager> DockManager;
CDockAreaWidget* DockArea = nullptr; QPointer<CDockAreaWidget> DockArea;
QAction* ToggleViewAction = nullptr; QAction* ToggleViewAction = nullptr;
bool Closed = false; bool Closed = false;
QScrollArea* ScrollArea = nullptr; QScrollArea* ScrollArea = nullptr;
@@ -95,6 +95,7 @@ struct DockWidgetPrivate
CDockWidget::eMinimumSizeHintMode MinimumSizeHintMode = CDockWidget::MinimumSizeHintFromDockWidget; CDockWidget::eMinimumSizeHintMode MinimumSizeHintMode = CDockWidget::MinimumSizeHintFromDockWidget;
WidgetFactory* Factory = nullptr; WidgetFactory* Factory = nullptr;
QPointer<CAutoHideTab> SideTabWidget; QPointer<CAutoHideTab> SideTabWidget;
CDockWidget::eToolBarStyleSource ToolBarStyleSource = CDockWidget::ToolBarStyleFromDockManager;
/** /**
* Private data constructor * Private data constructor
@@ -139,6 +140,11 @@ struct DockWidgetPrivate
* returns true on success. * returns true on success.
*/ */
bool createWidgetFromFactory(); bool createWidgetFromFactory();
/**
* Use the dock manager toolbar style and icon size for the different states
*/
void setToolBarStyleFromDockManager();
}; };
// struct DockWidgetPrivate // struct DockWidgetPrivate
@@ -178,11 +184,11 @@ void DockWidgetPrivate::showDockWidget()
DockArea->setCurrentDockWidget(_this); DockArea->setCurrentDockWidget(_this);
DockArea->toggleView(true); DockArea->toggleView(true);
TabWidget->show(); TabWidget->show();
QSplitter* Splitter = internal::findParent<QSplitter*>(DockArea); auto Splitter = DockArea->parentSplitter();
while (Splitter && !Splitter->isVisible() && !DockArea->isAutoHide()) while (Splitter && !Splitter->isVisible() && !DockArea->isAutoHide())
{ {
Splitter->show(); Splitter->show();
Splitter = internal::findParent<QSplitter*>(Splitter); Splitter = internal::findParent<CDockSplitter*>(Splitter);
} }
CDockContainerWidget* Container = DockArea->dockContainer(); CDockContainerWidget* Container = DockArea->dockContainer();
@@ -213,6 +219,12 @@ void DockWidgetPrivate::hideDockWidget()
if (Features.testFlag(CDockWidget::DeleteContentOnClose)) if (Features.testFlag(CDockWidget::DeleteContentOnClose))
{ {
if (ScrollArea)
{
ScrollArea->takeWidget();
delete ScrollArea;
ScrollArea = nullptr;
}
Widget->deleteLater(); Widget->deleteLater();
Widget = nullptr; Widget = nullptr;
} }
@@ -259,7 +271,10 @@ void DockWidgetPrivate::closeAutoHideDockWidgetsIfNeeded()
return; return;
} }
if (!DockContainer->openedDockWidgets().isEmpty()) // If the dock container is the dock manager, or if it is not empty, then we
// don't need to do anything
if ((DockContainer == _this->dockManager())
|| !DockContainer->openedDockWidgets().isEmpty())
{ {
return; return;
} }
@@ -325,6 +340,22 @@ bool DockWidgetPrivate::createWidgetFromFactory()
} }
//============================================================================
void DockWidgetPrivate::setToolBarStyleFromDockManager()
{
if (!DockManager)
{
return;
}
auto State = CDockWidget::StateDocked;
_this->setToolBarIconSize(DockManager->dockWidgetToolBarIconSize(State), State);
_this->setToolBarStyle(DockManager->dockWidgetToolBarStyle(State), State);
State = CDockWidget::StateFloating;
_this->setToolBarIconSize(DockManager->dockWidgetToolBarIconSize(State), State);
_this->setToolBarStyle(DockManager->dockWidgetToolBarStyle(State), State);
}
//============================================================================ //============================================================================
CDockWidget::CDockWidget(const QString &title, QWidget *parent) : CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
QFrame(parent), QFrame(parent),
@@ -354,10 +385,24 @@ CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
//============================================================================ //============================================================================
CDockWidget::~CDockWidget() CDockWidget::~CDockWidget()
{ {
ADS_PRINT("~CDockWidget()"); ADS_PRINT("~CDockWidget(): " << this->windowTitle());
delete d; delete d;
} }
//============================================================================
void CDockWidget::setToggleViewAction(QAction* action)
{
if (!action)
{
return;
}
d->ToggleViewAction->setParent(nullptr);
delete d->ToggleViewAction;
d->ToggleViewAction = action;
d->ToggleViewAction->setParent(this);
connect(d->ToggleViewAction, &QAction::triggered, this, &CDockWidget::toggleView);
}
//============================================================================ //============================================================================
void CDockWidget::setToggleViewActionChecked(bool Checked) void CDockWidget::setToggleViewActionChecked(bool Checked)
@@ -469,10 +514,19 @@ void CDockWidget::setFeatures(DockWidgetFeatures features)
return; return;
} }
d->Features = features; d->Features = features;
notifyFeaturesChanged();
}
//============================================================================
void CDockWidget::notifyFeaturesChanged()
{
Q_EMIT featuresChanged(d->Features); Q_EMIT featuresChanged(d->Features);
d->TabWidget->onDockWidgetFeaturesChanged(); d->TabWidget->onDockWidgetFeaturesChanged();
if(CDockAreaWidget* DockArea = dockAreaWidget()) if(CDockAreaWidget* DockArea = dockAreaWidget())
{
DockArea->onDockWidgetFeaturesChanged(); DockArea->onDockWidgetFeaturesChanged();
}
} }
@@ -488,7 +542,14 @@ void CDockWidget::setFeature(DockWidgetFeature flag, bool on)
//============================================================================ //============================================================================
CDockWidget::DockWidgetFeatures CDockWidget::features() const CDockWidget::DockWidgetFeatures CDockWidget::features() const
{ {
return d->Features; if (d->DockManager)
{
return d->Features &~ d->DockManager->globallyLockedDockWidgetFeatures();
}
else
{
return d->Features;
}
} }
@@ -503,6 +564,15 @@ CDockManager* CDockWidget::dockManager() const
void CDockWidget::setDockManager(CDockManager* DockManager) void CDockWidget::setDockManager(CDockManager* DockManager)
{ {
d->DockManager = DockManager; d->DockManager = DockManager;
if (!DockManager)
{
return;
}
if (ToolBarStyleFromDockManager == d->ToolBarStyleSource)
{
d->setToolBarStyleFromDockManager();
}
} }
@@ -515,7 +585,7 @@ CDockContainerWidget* CDockWidget::dockContainer() const
} }
else else
{ {
return 0; return nullptr;
} }
} }
@@ -555,6 +625,13 @@ bool CDockWidget::isAutoHide() const
} }
//============================================================================
SideBarLocation CDockWidget::autoHideLocation() const
{
return isAutoHide() ? autoHideDockContainer()->sideBarLocation() : SideBarNone;
}
//============================================================================ //============================================================================
bool CDockWidget::isFloating() const bool CDockWidget::isFloating() const
{ {
@@ -691,11 +768,10 @@ void CDockWidget::toggleViewInternal(bool Open)
if (d->DockArea) if (d->DockArea)
{ {
d->DockArea->toggleDockWidgetView(this, Open); d->DockArea->toggleDockWidgetView(this, Open);
} if (d->DockArea->isAutoHide())
{
if (d->DockArea->isAutoHide()) d->DockArea->autoHideDockContainer()->toggleView(Open);
{ }
d->DockArea->autoHideDockContainer()->toggleView(Open);
} }
if (Open && TopLevelDockWidgetBefore) if (Open && TopLevelDockWidgetBefore)
@@ -1021,7 +1097,15 @@ void CDockWidget::setFloating()
{ {
return; return;
} }
d->TabWidget->detachDockWidget();
if (this->isAutoHide())
{
dockAreaWidget()->setFloating();
}
else
{
d->TabWidget->detachDockWidget();
}
} }
@@ -1044,6 +1128,22 @@ void CDockWidget::closeDockWidget()
} }
//============================================================================
void CDockWidget::requestCloseDockWidget()
{
if (features().testFlag(CDockWidget::DockWidgetDeleteOnClose)
|| features().testFlag(CDockWidget::CustomCloseHandling))
{
closeDockWidgetInternal(false);
}
else
{
toggleView(false);
}
}
//============================================================================ //============================================================================
bool CDockWidget::closeDockWidgetInternal(bool ForceClose) bool CDockWidget::closeDockWidgetInternal(bool ForceClose)
{ {
@@ -1190,7 +1290,7 @@ void CDockWidget::raise()
//============================================================================ //============================================================================
void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location) void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location, int TabIndex)
{ {
if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled)) if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
{ {
@@ -1198,20 +1298,25 @@ void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location)
} }
// Do nothing if nothing changes // Do nothing if nothing changes
if (Enable == isAutoHide()) if (Enable == isAutoHide() && Location == autoHideLocation())
{ {
return; return;
} }
auto DockArea = dockAreaWidget(); auto DockArea = dockAreaWidget();
if (!Enable) if (!Enable)
{ {
DockArea->setAutoHide(false); DockArea->setAutoHide(false);
} }
else if (isAutoHide())
{
autoHideDockContainer()->moveToNewSideBarLocation(Location);
}
else else
{ {
auto area = (SideBarNone == Location) ? DockArea->calculateSideTabBarArea() : Location; auto area = (SideBarNone == Location) ? DockArea->calculateSideTabBarArea() : Location;
dockContainer()->createAndSetupAutoHideContainer(area, this); dockContainer()->createAndSetupAutoHideContainer(area, this, TabIndex);
} }
} }
@@ -1228,6 +1333,24 @@ void CDockWidget::toggleAutoHide(SideBarLocation Location)
} }
//============================================================================
void CDockWidget::setToolBarStyleSource(eToolBarStyleSource Source)
{
d->ToolBarStyleSource = Source;
if (ToolBarStyleFromDockManager == d->ToolBarStyleSource)
{
d->setToolBarStyleFromDockManager();
}
}
//============================================================================
CDockWidget::eToolBarStyleSource CDockWidget::toolBarStyleSource() const
{
return d->ToolBarStyleSource;
}
} // namespace ads } // namespace ads
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -165,6 +165,7 @@ public:
DefaultDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable | DockWidgetFocusable | DockWidgetPinnable, DefaultDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable | DockWidgetFocusable | DockWidgetPinnable,
AllDockWidgetFeatures = DefaultDockWidgetFeatures | DockWidgetDeleteOnClose | CustomCloseHandling, AllDockWidgetFeatures = DefaultDockWidgetFeatures | DockWidgetDeleteOnClose | CustomCloseHandling,
DockWidgetAlwaysCloseAndDelete = DockWidgetForceCloseWithArea | DockWidgetDeleteOnClose, DockWidgetAlwaysCloseAndDelete = DockWidgetForceCloseWithArea | DockWidgetDeleteOnClose,
GloballyLockableFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable | DockWidgetPinnable,
NoDockWidgetFeatures = 0x000 NoDockWidgetFeatures = 0x000
}; };
Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature) Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature)
@@ -176,6 +177,12 @@ public:
StateFloating StateFloating
}; };
enum eToolBarStyleSource
{
ToolBarStyleFromDockManager,
ToolBarStyleFromDockWidget
};
/** /**
* Sets the widget for the dock widget to widget. * Sets the widget for the dock widget to widget.
* The InsertMode defines how the widget is inserted into the dock widget. * The InsertMode defines how the widget is inserted into the dock widget.
@@ -246,11 +253,11 @@ public:
* object name is required by the dock manager to properly save and restore * object name is required by the dock manager to properly save and restore
* the state of the dock widget. That means, the title needs to be unique. * the state of the dock widget. That means, the title needs to be unique.
* If your title is not unique or if you would like to change the title * If your title is not unique or if you would like to change the title
* during runtime, you need to set a unique object name explicitely * during runtime, you need to set a unique object name explicitly
* by calling setObjectName() after construction. * by calling setObjectName() after construction.
* Use the layoutFlags to configure the layout of the dock widget. * Use the layoutFlags to configure the layout of the dock widget.
*/ */
CDockWidget(const QString &title, QWidget* parent = 0); CDockWidget(const QString &title, QWidget* parent = nullptr);
/** /**
* Virtual Destructor * Virtual Destructor
@@ -330,6 +337,11 @@ public:
*/ */
DockWidgetFeatures features() const; DockWidgetFeatures features() const;
/**
* Triggers notification of feature change signals and functions
*/
void notifyFeaturesChanged();
/** /**
* Returns the dock manager that manages the dock widget or 0 if the widget * Returns the dock manager that manages the dock widget or 0 if the widget
* has not been assigned to any dock manager yet * has not been assigned to any dock manager yet
@@ -377,6 +389,12 @@ public:
*/ */
CAutoHideDockContainer* autoHideDockContainer() const; CAutoHideDockContainer* autoHideDockContainer() const;
/**
* Returns the auto hide side bar location or SideBarNone if, this is not
* an autohide dock widget
*/
SideBarLocation autoHideLocation() const;
/** /**
* This property holds whether the dock widget is floating. * This property holds whether the dock widget is floating.
* A dock widget is only floating, if it is the one and only widget inside * A dock widget is only floating, if it is the one and only widget inside
@@ -403,6 +421,12 @@ public:
*/ */
QAction* toggleViewAction() const; QAction* toggleViewAction() const;
/**
* Use provided action to be the default toggle view action for this dock widget.
* This dock widget now owns the action.
*/
void setToggleViewAction(QAction* action);
/** /**
* Configures the behavior of the toggle view action. * Configures the behavior of the toggle view action.
* \see eToggleViewActionMode for a detailed description * \see eToggleViewActionMode for a detailed description
@@ -439,7 +463,7 @@ public:
/** /**
* This function returns the dock widget top tool bar. * This function returns the dock widget top tool bar.
* If no toolbar is assigned, this function returns nullptr. To get a vaild * If no toolbar is assigned, this function returns nullptr. To get a valid
* toolbar you either need to create a default empty toolbar via * toolbar you either need to create a default empty toolbar via
* createDefaultToolBar() function or you need to assign your custom * createDefaultToolBar() function or you need to assign your custom
* toolbar via setToolBar(). * toolbar via setToolBar().
@@ -461,6 +485,17 @@ public:
*/ */
void setToolBar(QToolBar* ToolBar); void setToolBar(QToolBar* ToolBar);
/**
* Configures, if the dock widget uses the global tool bar styles from
* dock manager or if it uses its own tool bar style
*/
void setToolBarStyleSource(eToolBarStyleSource Source);
/**
* Returns the configured tool bar style source
*/
eToolBarStyleSource toolBarStyleSource() const;
/** /**
* This function sets the tool button style for the given dock widget state. * This function sets the tool button style for the given dock widget state.
* It is possible to switch the tool button style depending on the state. * It is possible to switch the tool button style depending on the state.
@@ -578,10 +613,19 @@ public Q_SLOTS:
void deleteDockWidget(); void deleteDockWidget();
/** /**
* Closes the dock widget * Closes the dock widget.
* The function forces closing of the dock widget even for CustomCloseHandling.
*/ */
void closeDockWidget(); void closeDockWidget();
/**
* Request closing of the dock widget.
* For DockWidget with default close handling, the function does the same
* like clodeDockWidget() but if the flas CustomCloseHandling is set,
* the function only emits the closeRequested() signal.
*/
void requestCloseDockWidget();
/** /**
* Shows the widget in full-screen mode. * Shows the widget in full-screen mode.
* Normally this function only affects windows. To make the interface * Normally this function only affects windows. To make the interface
@@ -606,7 +650,7 @@ public Q_SLOTS:
* Sets the dock widget into auto hide mode if this feature is enabled * Sets the dock widget into auto hide mode if this feature is enabled
* via CDockManager::setAutoHideFlags(CDockManager::AutoHideFeatureEnabled) * via CDockManager::setAutoHideFlags(CDockManager::AutoHideFeatureEnabled)
*/ */
void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone); void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone, int TabIndex = -1);
/** /**
* Switches the dock widget to auto hide mode or vice versa depending on its * Switches the dock widget to auto hide mode or vice versa depending on its

View File

@@ -56,7 +56,6 @@
namespace ads namespace ads
{ {
static const char* const LocationProperty = "Location";
using tTabLabel = CElidingLabel; using tTabLabel = CElidingLabel;
/** /**
@@ -79,7 +78,6 @@ struct DockWidgetTabPrivate
QSpacerItem* IconTextSpacer; QSpacerItem* IconTextSpacer;
QPoint TabDragStartPosition; QPoint TabDragStartPosition;
QSize IconSize; QSize IconSize;
bool MousePressed = false;
/** /**
* Private data constructor * Private data constructor
@@ -226,7 +224,7 @@ struct DockWidgetTabPrivate
QMenu* Menu) QMenu* Menu)
{ {
auto Action = Menu->addAction(Title); auto Action = Menu->addAction(Title);
Action->setProperty("Location", Location); Action->setProperty(internal::LocationProperty, Location);
QObject::connect(Action, &QAction::triggered, _this, &CDockWidgetTab::onAutoHideToActionClicked); QObject::connect(Action, &QAction::triggered, _this, &CDockWidgetTab::onAutoHideToActionClicked);
return Action; return Action;
} }
@@ -246,7 +244,14 @@ DockWidgetTabPrivate::DockWidgetTabPrivate(CDockWidgetTab* _public) :
void DockWidgetTabPrivate::createLayout() void DockWidgetTabPrivate::createLayout()
{ {
TitleLabel = new tTabLabel(); TitleLabel = new tTabLabel();
TitleLabel->setElideMode(Qt::ElideRight); if (CDockManager::testConfigFlag(CDockManager::DisableTabTextEliding))
{
TitleLabel->setElideMode(Qt::ElideNone);
}
else
{
TitleLabel->setElideMode(Qt::ElideRight);
}
TitleLabel->setText(DockWidget->windowTitle()); TitleLabel->setText(DockWidget->windowTitle());
TitleLabel->setObjectName("dockWidgetTabLabel"); TitleLabel->setObjectName("dockWidgetTabLabel");
TitleLabel->setAlignment(Qt::AlignCenter); TitleLabel->setAlignment(Qt::AlignCenter);
@@ -373,7 +378,6 @@ void CDockWidgetTab::mousePressEvent(QMouseEvent* ev)
if (ev->button() == Qt::LeftButton) if (ev->button() == Qt::LeftButton)
{ {
ev->accept(); ev->accept();
d->MousePressed = true;
d->saveDragStartMousePosition(internal::globalPositionOf(ev)); d->saveDragStartMousePosition(internal::globalPositionOf(ev));
d->DragState = DraggingMousePressed; d->DragState = DraggingMousePressed;
if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting)) if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
@@ -394,7 +398,6 @@ void CDockWidgetTab::mouseReleaseEvent(QMouseEvent* ev)
{ {
if (ev->button() == Qt::LeftButton) if (ev->button() == Qt::LeftButton)
{ {
d->MousePressed = false;
auto CurrentDragState = d->DragState; auto CurrentDragState = d->DragState;
d->GlobalDragStartMousePosition = QPoint(); d->GlobalDragStartMousePosition = QPoint();
d->DragStartMousePosition = QPoint(); d->DragStartMousePosition = QPoint();
@@ -417,11 +420,12 @@ void CDockWidgetTab::mouseReleaseEvent(QMouseEvent* ev)
break; break;
default: default:
if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting)) break;
{ }
d->focusController()->setDockWidgetTabPressed(false);
} if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
break; // do nothing {
d->focusController()->setDockWidgetTabPressed(false);
} }
} }
else if (ev->button() == Qt::MiddleButton) else if (ev->button() == Qt::MiddleButton)
@@ -502,7 +506,7 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
else if (d->DockArea->openDockWidgetsCount() > 1 else if (d->DockArea->openDockWidgetsCount() > 1
&& (internal::globalPositionOf(ev) - d->GlobalDragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving && (internal::globalPositionOf(ev) - d->GlobalDragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving
{ {
// If we start dragging the tab, we save its inital position to // If we start dragging the tab, we save its initial position to
// restore it later // restore it later
if (DraggingTab != d->DragState) if (DraggingTab != d->DragState)
{ {
@@ -525,26 +529,34 @@ void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev)
return; return;
} }
auto Menu = buildContextMenu(nullptr);
d->saveDragStartMousePosition(ev->globalPos()); d->saveDragStartMousePosition(ev->globalPos());
Menu->exec(ev->globalPos());
}
QMenu* CDockWidgetTab::buildContextMenu(QMenu *Menu)
{
if (Menu == nullptr) {
Menu = new QMenu(this);
}
const bool isFloatable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable); const bool isFloatable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable);
const bool isNotOnlyTabInContainer = !d->DockArea->dockContainer()->hasTopLevelDockWidget(); const bool isNotOnlyTabInContainer = !d->DockArea->dockContainer()->hasTopLevelDockWidget();
const bool isTopLevelArea = d->DockArea->isTopLevelArea(); const bool isTopLevelArea = d->DockArea->isTopLevelArea();
const bool isDetachable = isFloatable && isNotOnlyTabInContainer; const bool isDetachable = isFloatable && isNotOnlyTabInContainer;
QAction* Action; QAction* Action;
QMenu Menu(this);
if (!isTopLevelArea) if (!isTopLevelArea)
{ {
Action = Menu.addAction(tr("Detach"), this, SLOT(detachDockWidget())); Action = Menu->addAction(tr("Detach"), this, SLOT(detachDockWidget()));
Action->setEnabled(isDetachable); Action->setEnabled(isDetachable);
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled)) if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
{ {
Action = Menu.addAction(tr("Pin"), this, SLOT(autoHideDockWidget())); Action = Menu->addAction(tr("Pin"), this, SLOT(autoHideDockWidget()));
auto IsPinnable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable); auto IsPinnable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable);
Action->setEnabled(IsPinnable); Action->setEnabled(IsPinnable);
auto menu = Menu.addMenu(tr("Pin To...")); auto menu = Menu->addMenu(tr("Pin To..."));
menu->setEnabled(IsPinnable); menu->setEnabled(IsPinnable);
d->createAutoHideToAction(tr("Top"), SideBarTop, menu); d->createAutoHideToAction(tr("Top"), SideBarTop, menu);
d->createAutoHideToAction(tr("Left"), SideBarLeft, menu); d->createAutoHideToAction(tr("Left"), SideBarLeft, menu);
@@ -553,17 +565,16 @@ void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev)
} }
} }
Menu.addSeparator(); Menu->addSeparator();
Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested())); Action = Menu->addAction(tr("Close"), this, SIGNAL(closeRequested()));
Action->setEnabled(isClosable()); Action->setEnabled(isClosable());
if (d->DockArea->openDockWidgetsCount() > 1) if (d->DockArea->openDockWidgetsCount() > 1)
{ {
Action = Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested())); Action = Menu->addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested()));
} }
Menu.exec(ev->globalPos());
return Menu;
} }
//============================================================================ //============================================================================
bool CDockWidgetTab::isActiveTab() const bool CDockWidgetTab::isActiveTab() const
{ {
@@ -576,6 +587,14 @@ void CDockWidgetTab::setActiveTab(bool active)
{ {
d->updateCloseButtonVisibility(active); d->updateCloseButtonVisibility(active);
if(CDockManager::testConfigFlag(CDockManager::ShowTabTextOnlyForActiveTab) && !d->Icon.isNull())
{
if(active)
d->TitleLabel->setVisible(true);
else
d->TitleLabel->setVisible(false);
}
// Focus related stuff // Focus related stuff
if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting) && !d->DockWidget->dockManager()->isRestoringState()) if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting) && !d->DockWidget->dockManager()->isRestoringState())
{ {
@@ -751,7 +770,7 @@ void CDockWidgetTab::autoHideDockWidget()
//=========================================================================== //===========================================================================
void CDockWidgetTab::onAutoHideToActionClicked() void CDockWidgetTab::onAutoHideToActionClicked()
{ {
int Location = sender()->property(LocationProperty).toInt(); int Location = sender()->property(internal::LocationProperty).toInt();
d->DockWidget->toggleAutoHide((SideBarLocation)Location); d->DockWidget->toggleAutoHide((SideBarLocation)Location);
} }
@@ -777,6 +796,13 @@ bool CDockWidgetTab::event(QEvent *e)
} }
//============================================================================
eDragState CDockWidgetTab::dragState() const
{
return d->DragState;
}
//============================================================================ //============================================================================
void CDockWidgetTab::onDockWidgetFeaturesChanged() void CDockWidgetTab::onDockWidgetFeaturesChanged()
{ {

View File

@@ -35,6 +35,8 @@
#include "ads_globals.h" #include "ads_globals.h"
QT_FORWARD_DECLARE_CLASS(QMenu)
namespace ads namespace ads
{ {
class CDockWidget; class CDockWidget;
@@ -84,7 +86,7 @@ public:
* param[in] DockWidget The dock widget this title bar belongs to * param[in] DockWidget The dock widget this title bar belongs to
* param[in] parent The parent widget of this title bar * param[in] parent The parent widget of this title bar
*/ */
CDockWidgetTab(CDockWidget* DockWidget, QWidget* parent = 0); CDockWidgetTab(CDockWidget* DockWidget, QWidget* parent = nullptr);
/** /**
* Virtual Destructor * Virtual Destructor
@@ -173,16 +175,30 @@ public:
/** /**
* Set an explicit icon size. * Set an explicit icon size.
* If no icon size has been set explicitely, than the tab sets the icon size * If no icon size has been set explicitly, than the tab sets the icon size
* depending on the style * depending on the style
*/ */
void setIconSize(const QSize& Size); void setIconSize(const QSize& Size);
/** /**
* Returns true, if the tab has been clicked and the mouse is currently * Returns the current drag state of this tab.
* pressed. * Use this function to determine if the tab is currently being dragged
*/ */
bool mousePressed() const; eDragState dragState() const;
/**
* Fills the provided menu with standard entries. If a nullptr is passed, a
* new menu is created and filled with standard entries.
* This function is called from the actual version of contextMenuEvent, but
* can be called from any code. Caller is responsible of deleting the created
* object.
*
* @param menu The QMenu to fill with standard entries. If nullptr, a new
* QMenu will be created.
* @return The filled QMenu, either the provided one or a newly created one if
* nullptr was passed.
*/
virtual QMenu *buildContextMenu(QMenu *);
public Q_SLOTS: public Q_SLOTS:
virtual void setVisible(bool visible) override; virtual void setVisible(bool visible) override;

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