Compare commits

..

111 Commits
4.0.2 ... 4.2.0

Author SHA1 Message Date
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
957afe3a07 Updated cmake build for demo to use quick and quickwidgets 2023-06-30 14:01:56 +02:00
Uwe Kindler
4ab726fee3 Updated Linux install requirements in README.md for building the demo application with QQuickWidget 2023-06-30 13:07:42 +02:00
Uwe Kindler
8d4507e9d8 Fixed mouse pressed state for Linux (use memeber variable instead of static) 2023-06-30 11:28:11 +02:00
Uwe Kindler
5a00eece87 Added QQuickWidget to demo application for testing OpenGl QtQuick on Linux 2023-06-30 08:27:51 +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
09e4e6fa5a Fixed nullptr access in DockWidgetTab 2023-06-27 10:18:38 +02:00
Uwe Kindler
b9479dbd3d Started implementing autohide drag functionality 2023-06-27 10:12:51 +02:00
Uwe Kindler
34cc91a9af Fixed #527 - updateDockWidgetFocusStyle() function error 2023-06-23 21:06:52 +02:00
Uwe Kindler
36cdf4a252 Fixed warnings on MacOS: replaced QApplication::setActiveWindow(this); with QWidget::activateWindow 2023-06-23 10:28:55 +02:00
Uwe Kindler
85f65b3f1a Avoid multiple function calls of parentWidget() function in CAutoHideSideBar::visibleTabCount() and CAutoHideSideBar::hasVisibleTabs() 2023-06-23 10:21:08 +02:00
Ahmad Syarifuddin
92da2eb8bd Bug fix sidebar state during restore (#526)
* fix side bar state being incorrect during restore

* isVisible is invalid during restore state

* Make visibleTabCount function consistent with hasVisibleTabs. Add a bit of documentation.

---------

Co-authored-by: Syarif Fakhri <fakhri.s@duerr-ndt.com>
2023-06-23 09:15:24 +02:00
Uwe Kindler
27edfe63ee Fixed issue #524: Sometimes sidebar visibility state is incorrect 2023-06-22 14:45:29 +02:00
Uwe Kindler
5517822008 Updated README.md with information about filing PySide related issues 2023-06-19 10:25:32 +02:00
Uwe Kindler
702702cbfd Merge branch '7c0o-master' 2023-06-19 10:03:56 +02:00
Uwe Kindler
c552fef134 Added documentation for the queued _this->ensureWidgetVisible(TabWidget) call 2023-06-19 10:02:19 +02:00
Eric Wong
916df28fcd Update FloatingDockContainer.cpp
remove dock container
2023-06-16 17:37:31 +08:00
Eric Wong
c08d91687a Update FloatingDockContainer.cpp
saveState() may use the floatingDockContainer to be deleted
2023-06-14 12:07:45 +08:00
Eric Wong
ccbde05fb7 Update DockAreaWidget.cpp
memory leak
2023-06-14 09:42:47 +08:00
Eric Wong
1049576349 Update DockAreaTabBar.cpp
Sometimes the synchronous calculation of the rectangular area fails
2023-06-08 09:13:41 +08:00
Uwe Kindler
0bfee09b17 Merge branch 'master' of https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System 2023-06-06 15:26:21 +02:00
Uwe Kindler
87954e4459 Merged #518 - Add more options to determine the minimum size of a dock widget 2023-06-06 15:25:49 +02:00
githubuser0xFFFF
0301e345b4 Update linux-builds.yml 2023-05-12 19:32:39 +02:00
Uwe Kindler
f9b5ef8d89 Remove Ubuntu 18.04 from linux-builds 2023-05-09 13:36:42 +02:00
Uwe Kindler
0ed1f8f429 Fixed linux-builds.yml file 2023-05-08 10:32:58 +02:00
Uwe Kindler
659537916e Added documentation of new AutoHideCloseButtonCollapsesDock flag 2023-04-28 12:24:12 +02:00
Uwe Kindler
0cac9ac507 Merge branch 'close_button_collapse_dock' of https://github.com/duerr-ndt/Qt-Advanced-Docking-System into duerr-ndt-close_button_collapse_dock 2023-04-28 11:49:17 +02:00
Uwe Kindler
7a79ecab8a Fixed #511 - CDockWidget::toggleView now properly shows auto hide widgets 2023-04-28 11:47:01 +02:00
Uwe Kindler
1186d2b78c Fixed #509 - Implemented support for restoring maximized state of floating widgets on Windows 2023-04-28 11:12:22 +02:00
Syarif Fakhri
b46768537a Add config to make close button collapse auto hide dock 2023-04-28 15:27:22 +08:00
Uwe Kindler
44115d4bd9 Added support for printing events to diagnose window state ploblem 2023-04-28 08:33:45 +02:00
Uwe Kindler
f2d8e17981 Merge branch 'master' of https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System 2023-04-27 23:38:19 +02:00
Uwe Kindler
7890a408f4 Added KDE LabPlot to the showcase section 2023-04-27 23:38:05 +02:00
Murmele
a940fc29c6 Use code also for other unix systems like BSD (#507) 2023-04-18 19:17:10 +02:00
Murmele
c6595563af if QT_VERSION_MAJOR is defined, use this version instead of searching again. Labplot does not support Qt6 yet and therefore the version is set manually in the project. If Qt5 and Qt6 are installed, QAd overwrites the Qt5 requirement and then the configuration of the project does not work (#504) 2023-04-16 11:32:45 +02:00
Uwe Kindler
cb24317010 Merge branch 'master' of https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System 2023-04-11 08:31:26 +02:00
Uwe Kindler
fb1e427ab7 Added DREAM.3D NX to showcase section 2023-04-11 08:30:25 +02:00
Nicolas Elie
9d28a4d0d5 Fix typo in pyproject.toml (#501) 2023-04-08 09:08:01 +02:00
Uwe Kindler
df34b0eb2b An additional fix for #496 Nonfloatable hidden window disappears on drop in empty area 2023-03-22 18:22:34 +01:00
Uwe Kindler
db3dc80170 Fixed #496 Nonfloatable hidden window disappears on drop in empty area 2023-03-21 08:31:55 +01:00
Nicolas Elie
db16c5f1b5 Update python bindings to 4.0.2 (#495)
* start adaption of PyQt5 bindings to Qt-ADS 4.0

* Update PyQt bindings

* Fix Python bindings build on Linux

---------

Co-authored-by: Mira Weller <mweller@seemoo.tu-darmstadt.de>
2023-03-21 06:04:19 +01:00
Nicolas Elie
d28ca1e7a1 Add options to project.py to specify include and library directories (#493) 2023-03-11 08:34:23 +01:00
Nicolas Elie
e84b4a8146 Add namespace to default argument for python bindings (#492) 2023-03-06 14:53:43 +01:00
Nicolas Elie
46e0d832f8 Fix wrong include path in CMake install (#491) 2023-03-06 14:52:57 +01:00
Uwe Kindler
7e63919c08 Updated ads icons 2023-03-01 08:54:27 +01:00
Uwe Kindler
1873dde358 Added ADTF to showcase section and added video link for Resinsight to showcase section 2023-03-01 08:49:19 +01:00
Uwe Kindler
6362d14da6 Merge branch 'master' of https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System 2023-02-27 08:03:08 +01:00
Uwe Kindler
1f48f0f3ad Updated linux-builds.yml to fix broken Ubuntu 22.04 workflow 2023-02-27 07:51:39 +01:00
Nicolas Elie
82695d1b3d Remove setup.py and related files (#490) 2023-02-23 18:42:47 +01:00
Nicolas Elie
08b0f8ad54 Change targets name based on Qt version (#489) 2023-02-23 15:50:50 +01:00
githubuser0xFFFF
54c2bd0c30 Update linux-builds.yml 2023-02-10 14:55:18 +01:00
githubuser0xFFFF
d8784a22b7 Update linux-builds.yml 2023-02-10 14:09:02 +01:00
githubuser0xFFFF
bc9f136f20 Update linux-builds.yml 2023-02-10 13:58:03 +01:00
githubuser0xFFFF
7192a06eb8 Update linux-builds.yml 2023-02-10 13:42:31 +01:00
githubuser0xFFFF
a4c6f1d16c Update linux-builds.yml 2023-02-10 13:30:41 +01:00
githubuser0xFFFF
009af32e61 Update linux-builds.yml
added Ubuntu 22.04 build with Qt6
2023-02-10 13:25:58 +01:00
Uwe Kindler
fab41828ab Updated the build documentation for Ubuntu 22.04 2023-02-10 12:02:42 +01:00
Uwe Kindler
cae42939c8 Disable native windows on Linux if wayland is used 2023-02-10 11:36:40 +01:00
Uwe Kindler
7b30322946 Added ResInsight to showcase section 2023-01-24 16:07:00 +01:00
115 changed files with 2718 additions and 2771 deletions

View File

@@ -6,7 +6,7 @@ jobs:
build:
strategy:
matrix:
os: [ubuntu-20.04, ubuntu-18.04]
os: [ubuntu-20.04]
runs-on: ${{ matrix.os }}
@@ -16,8 +16,44 @@ jobs:
run: |
sudo apt-get update --fix-missing
sudo apt-get install qt5-default
sudo apt-get install qtbase5-private-dev
sudo apt-get install qtbase5-private-dev qtdeclarative5-dev
- name: qmake
run: qmake
- name: make
run: make -j4
build_ubuntu_2204:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- name: Cache Qt
id: cache-qt-6-4
uses: actions/cache@v1 # not v2!
with:
path: ../Qt/6.4.2
key: ${{ runner.os }}-QtCache-Qt6-4
- name: Install Qt
uses: jurplel/install-qt-action@v2
with:
version: '6.4.2'
host: 'linux'
target: 'desktop'
install-deps: true
cached: ${{ steps.cache-qt-6-4.outputs.cache-hit }}
setup-python: true
tools: ''
tools-only: false
- name: Install needed xkbcommon symlink
run: sudo apt-get install libxkbcommon-dev -y
- name: Ubuntu and Qt version
run: |
cat /etc/issue
echo number of processors: $(nproc)
qmake -v
- name: qmake
run: qmake
- name: make
run: make -j$(nproc)

View File

@@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.5)
if (POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif (POLICY CMP0091)
# By default, the version information is extracted from the git index. However,
# we can override this behavior by explicitly setting ADS_VERSION and
# skipping the git checks. This is useful for cases where this project is being

163
README.md
View File

@@ -22,6 +22,70 @@ integrated development environments (IDEs) such as Visual Studio.
## 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)
adds the following features:
@@ -77,6 +141,12 @@ know it from Visual Studio.
### Overview
- [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)
- [Overview](#overview)
- [Docking everywhere - no central widget](#docking-everywhere---no-central-widget)
@@ -98,6 +168,9 @@ know it from Visual Studio.
- [macOS](#macos)
- [Linux](#linux)
- [Build](#build)
- [Qt5 on Ubuntu 18.04 or 20.04](#qt5-on-ubuntu-1804-or-2004)
- [Qt5 on Ubuntu 22.04](#qt5-on-ubuntu-2204)
- [Qt6 on Ubuntu 22.04](#qt6-on-ubuntu-2204)
- [Getting started / Example](#getting-started--example)
- [License information](#license-information)
- [Donation](#donation)
@@ -114,6 +187,10 @@ know it from Visual Studio.
- [MetGem](#metgem)
- [PRE Workbench](#pre-workbench)
- [RDE Robox Development Environment](#rde--robox-development-environment)
- [ResInsight](#resinsight)
- [ADTF 3](#adtf-3)
- [DREAM.3D NX](#dream3d-nx)
- [LabPlot](#labplot)
- [Alternative Docking System Implementations](#alternative-docking-system-implementations)
- [KDDockWidgets](#kddockwidgets)
- [QtitanDocking](#qtitandocking)
@@ -249,7 +326,7 @@ The PySide6 bindings were contributed by:
- [mborgerson](https://github.com/mborgerson)
For more information about the PySide6 bindings read [this](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/298) issue.
Please file PySide6-QtAds-specific issues on its [pyside6_qtads](https://github.com/mborgerson/pyside6_qtads) fork for tracking. For more information about the PySide6 bindings read [this](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/298) issue.
### PyQt5
@@ -291,10 +368,13 @@ 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://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 following Linux distributions:
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
with native title bars are supported or not. If native title bars are not supported,
the library switches to `QWidget` based title bars.
- **Kubuntu 18.04 and 19.10**
- **Ubuntu 18.04, 19.10 and 20.04**
- **Kubuntu 18.04 and 19.10** - uses KWin - no native title bars
- **Ubuntu 18.04, 19.10 and 20.04** - native title bars are supported
- **Ubuntu 22.04** - uses Wayland -> no native title bars
There are some requirements for the Linux distribution that have to be met:
@@ -309,10 +389,27 @@ Screenshot Ubuntu:
## Build
The Linux build requires private header files. Make sure that they are installed:
The Linux build requires private header files. Make sure that they are installed.
The library uses SVG icons, so ensure that Qt SVG support is installed. The demo
application creates a `QQuickWidget` for testing, so ensure that the required
libraries are installed.
### Qt5 on Ubuntu 18.04 or 20.04
```bash
sudo apt install qtbase5-private-dev
sudo apt install qt5-default qtbase5-private-dev
```
### Qt5 on Ubuntu 22.04
```bash
sudo apt install qtbase5-dev qtbase5-private-dev qtbase5-dev-tools libqt5svg5 libqt5qml5 qtdeclarative5-dev
```
### Qt6 on Ubuntu 22.04
```bash
sudo apt install qt6-default qt6-base-dev qt6-base-private-dev qt6-tools-dev libqt6svg6 qt6-qtdeclarative
```
Open the `ads.pro` file with QtCreator and start the build, that's it.
@@ -538,13 +635,65 @@ development experience.
![RDE](doc/showcase_robox_ide.png)
### [ResInsight](https://www.ceetronsolutions.com/projects/resinsight)
ResInsight as a software from Ceetron Solutions for visualization of oil and
gas reservoir simulation data. It allows reservoir models, simulation results,
and measurements to be visualized with very high performance. Optimized use of
graphics technology and simultaneous processing on multiple CPU cores have been
vital to enhance the performance and capacity of ResInsight for large data sets.
The Advanced Docking System has empowered Ceetron to build a much more intuitive
user interface for its ResInsight users.
[read more...](https://resinsight.org/)
[![ResInsight](doc/showcase_resinsight.png)](https://www.youtube.com/watch?v=HzLaQ1p6AUc)
### [ADTF 3](https://www.digitalwerk.net/adtf/)
The Automotive Data and Time-Triggered Framework was designed as a Rapid Prototyping Toolset, Simulation Framework and Test- and Measurement Tool. It is meant for:
- Developing and testing ADAS and HAD components
- Recording of vehicle data for visualisation
- Simulation of complex scenarios in SIL/HIL test environments
The software features time-based processing of multiple data streams and graphical editing of dynamic filter graphs. It also includes an SDK for custom plug-ins and reusable components, as well as components for data visualization in both 2D and 3D. This is was the
[manual](https://support.digitalwerk.net/adtf/v3/adtf_html/page_adtf_xsystem_plugin.html)
says about the switch to Qt Advanced Docking:
> After several minor improvements the Qt5 ADTF XSystem uses the Advanced Docking System for Qt since ADTF 3.10.0 for more convenience and usability regarding layouting, docking and embedding several widgets.
[read more...](https://support.digitalwerk.net/adtf/v3/adtf_html/index.html)
![ADTF](doc/showcase_adtf.png)
### [DREAM.3D NX](https://github.com/BlueQuartzSoftware/DREAM3D)
DREAM.3D *(Digital Representation Environment for Analysis of Materials in 3D)* is an open source, cross-platform and modular, software suite that allows users to prepare, reconstruct, quantify, instantiate, and mesh, multidimensional, multimodal microstructural data, as well as many other applications.
[BlueQuartz Software](http://www.bluequartz.net/) is currently completely rewriting the DREAM.3D application. For the upcoming version **[DREAM3D NX](http://www.dream3d.io/)** they improved the UI by using the Advanced Docking System. An [early version](http://www.dream3d.io/) of **DREAM3D NX** with ADS is already available to any user who would like to take the brand new version out for a spin.
![DREAM.3D NX](doc/showcase_dream3d_nx.png)
[read more...](http://dream3d.bluequartz.net/)
### [LabPlot](https://labplot.kde.org/)
KDE LabPlot is the ultimate free, open source and cross-platform tool for scientists, engineers, and students who need to analyze and visualize data. With its intuitive interface and powerful features, you can create stunning plots and diagrams with ease. Whether you're working with CSV, FITS, or HDF5 data, KDE LabPlot makes it simple to import and analyze your data.
The LabPlot project recently switched to the Qt Advanced Docking System for their user interface. This switch represents a significant improvement to the LabPlot software, allowing users to create and manage complex data visualization layouts with ease.
![LabPlot](doc/showcase_labplot.png)
[read more...](https://labplot.kde.org/)
## Alternative Docking System Implementations
If this Qt Advanced Docking System does not fit to your needs you may consider some of the alternative docking system solutions for Qt.
### KDDockWidgets
This is an advanced docking framework for Qt from [KDAB](https://www.kdab.com/). The interesting thing is, that they separated GUI code from logic, so they can easily provide a QtQuick backend in the future.
This is an advanced docking framework for Qt from [KDAB](https://www.kdab.com/). The interesting thing is, that they separated GUI code from logic, so they can easily provide a QtQuick backend in the future.
- [Blog post about KDDockWidgets](https://www.kdab.com/kddockwidgets/)
- [GitHub project](https://github.com/KDAB/KDDockWidgets)

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5)
project(ads_demo VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets Quick QuickWidgets REQUIRED)
if(WIN32 AND QT_VERSION_MAJOR LESS 6)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS AxContainer REQUIRED)
endif()
@@ -21,11 +21,13 @@ add_executable(AdvancedDockingSystemDemo WIN32 ${ads_demo_SRCS})
target_include_directories(AdvancedDockingSystemDemo PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../src")
target_link_libraries(AdvancedDockingSystemDemo PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::QuickWidgets)
if(WIN32 AND QT_VERSION_MAJOR LESS 6)
target_link_libraries(AdvancedDockingSystemDemo PUBLIC Qt${QT_VERSION_MAJOR}::AxContainer)
endif()
target_link_libraries(AdvancedDockingSystemDemo PRIVATE qtadvanceddocking)
target_link_libraries(AdvancedDockingSystemDemo PRIVATE qt${QT_VERSION_MAJOR}advanceddocking)
set_target_properties(AdvancedDockingSystemDemo PROPERTIES
AUTOMOC ON
AUTORCC ON

View File

@@ -62,6 +62,7 @@
#include <QPointer>
#include <QMap>
#include <QElapsedTimer>
#include <QQuickWidget>
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
@@ -270,6 +271,10 @@ struct MainWindowPrivate
auto ToolBar = DockWidget->createDefaultToolBar();
ToolBar->addAction(ui.actionSaveState);
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;
}
@@ -407,6 +412,17 @@ struct MainWindowPrivate
return DockWidget;
}
/**
* Create QQuickWidget for test for OpenGL and QQuick
*/
ads::CDockWidget *createQQuickWidget()
{
QQuickWidget *widget = new QQuickWidget();
ads::CDockWidget *dockWidget = new ads::CDockWidget("Quick");
dockWidget->setWidget(widget);
return dockWidget;
}
#ifdef Q_OS_WIN
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
@@ -424,7 +440,6 @@ struct MainWindowPrivate
}
#endif
#endif
};
//============================================================================
@@ -437,8 +452,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):
{
SpecialDockArea->setAllowedAreas(ads::OuterDockAreas);
//SpecialDockArea->setAllowedAreas({ads::LeftDockWidgetArea, ads::RightDockWidgetArea}); // just for testing
//SpecialDockArea->setAllowedAreas(ads::OuterDockAreas);
SpecialDockArea->setAllowedAreas({ads::LeftDockWidgetArea, ads::RightDockWidgetArea, ads::TopDockWidgetArea}); // just for testing
}
DockWidget = createLongTextLabelDockWidget();
@@ -506,7 +521,9 @@ void MainWindowPrivate::createContent()
// Test dock area docking
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);
DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea);
auto LabelDockWidget = createLongTextLabelDockWidget();
@@ -514,6 +531,7 @@ void MainWindowPrivate::createContent()
// Tests CustomCloseHandling without DeleteOnClose
LabelDockWidget->setFeature(ads::CDockWidget::CustomCloseHandling, true);
LabelDockWidget->setWindowTitle(LabelDockWidget->windowTitle() + " [Custom Close]");
QObject::connect(LabelDockWidget, &ads::CDockWidget::closeRequested, [LabelDockWidget, this]()
{
int Result = QMessageBox::question(_this, "Custom Close Request",
@@ -557,6 +575,11 @@ void MainWindowPrivate::createContent()
// Create image viewer
DockWidget = createImageViewer();
DockManager->addDockWidget(ads::LeftDockWidgetArea, DockWidget);
// Create quick widget
DockWidget = createQQuickWidget();
DockWidget->setFeature(ads::CDockWidget::DockWidgetClosable, true);
DockManager->addDockWidget(ads::LeftDockWidgetArea, DockWidget);
}
@@ -734,7 +757,7 @@ CMainWindow::CMainWindow(QWidget *parent) :
CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true);
// uncomment if you would like to enable dock widget auto hiding
CDockManager::setAutoHideConfigFlags(CDockManager::DefaultAutoHideConfig);
CDockManager::setAutoHideConfigFlags({CDockManager::DefaultAutoHideConfig});
// uncomment if you would like to enable an equal distribution of the
// available size of a splitter to all contained dock widgets
@@ -745,6 +768,7 @@ CMainWindow::CMainWindow(QWidget *parent) :
// Now create the dock manager and its content
d->DockManager = new CDockManager(this);
d->DockManager->setDockWidgetToolBarStyle(Qt::ToolButtonIconOnly, ads::CDockWidget::StateFloating);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
connect(d->PerspectiveComboBox, SIGNAL(activated(QString)),

View File

@@ -2,7 +2,7 @@ ADS_OUT_ROOT = $${OUT_PWD}/..
TARGET = AdvancedDockingSystemDemo
DESTDIR = $${ADS_OUT_ROOT}/lib
QT += core gui widgets
QT += core gui widgets quick quickwidgets
include(../ads.pri)

View File

@@ -2,7 +2,7 @@ import os
import sys
from PyQt5 import uic
from PyQtAds import QtAds
import PyQtAds as QtAds
UI_FILE = os.path.join(os.path.dirname(__file__), 'StatusDialog.ui')
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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@@ -65,7 +65,7 @@ If this flag is cleared, the widget resizing is deferred until the mouse button
### Opaque and non-opaque undocking
By default, opaque undocking is active. That means, as soon as you drag a dock widget or a dock area with a number of dock widgets it will be undocked and moved into a floating widget and then the floating widget will be dragged around. That means undocking will take place immediatelly. You can compare this with opaque splitter resizing. If the flag `OpaqueUndocking` is cleared, then non-opaque undocking is active. In this mode, undocking is more like a standard drag and drop operation. That means, the dragged dock widget or dock area is not undocked immediatelly. Instead, a drag preview widget is created and dragged around to indicate the future position of the dock widget or dock area. The actual dock operation is only executed when the mouse button is released. That makes it possible, to cancel an active drag operation with the escape key.
By default, opaque undocking is active. That means, as soon as you drag a dock widget or a dock area with a number of dock widgets it will be undocked and moved into a floating widget and then the floating widget will be dragged around. That means undocking will take place immediately. You can compare this with opaque splitter resizing. If the flag `OpaqueUndocking` is cleared, then non-opaque undocking is active. In this mode, undocking is more like a standard drag and drop operation. That means, the dragged dock widget or dock area is not undocked immediately. Instead, a drag preview widget is created and dragged around to indicate the future position of the dock widget or dock area. The actual dock operation is only executed when the mouse button is released. That makes it possible, to cancel an active drag operation with the escape key.
The drag preview widget can be configured by a number of global dock manager flags:

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

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: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
doc/showcase_adtf.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

BIN
doc/showcase_dream3d_nx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

BIN
doc/showcase_labplot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

BIN
doc/showcase_resinsight.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 311 KiB

After

Width:  |  Height:  |  Size: 363 KiB

View File

@@ -27,10 +27,16 @@
- [`FloatingContainerForceNativeTitleBar` (Linux only)](#floatingcontainerforcenativetitlebar-linux-only)
- [`FloatingContainerForceQWidgetTitleBar` (Linux only)](#floatingcontainerforceqwidgettitlebar-linux-only)
- [`MiddleMouseButtonClosesTab`](#middlemousebuttonclosestab)
- [`DisableTabTextEliding`](#disabletabtexteliding)
- [Auto-Hide Configuration Flags](#auto-hide-configuration-flags)
- [Auto Hide Dock Widgets](#auto-hide-dock-widgets)
- [Pinning Auto-Hide Widgets to a certain border](#pinning-auto-hide-widgets-to-a-certain-border)
- [Show / Hide Auto-Hide Widgets via Mouse Over](#show--hide-auto-hide-widgets-via-mouse-over)
- [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)
- [Setting Auto-Hide Flags](#setting-auto-hide-flags)
- [`AutoHideFeatureEnabled`](#autohidefeatureenabled)
@@ -39,6 +45,9 @@
- [`AutoHideButtonCheckable`](#autohidebuttoncheckable)
- [`AutoHideSideBarsIconOnly`](#autohidesidebarsicononly)
- [`AutoHideShowOnMouseOver`](#autohideshowonmouseover)
- [`AutoHideCloseButtonCollapsesDock`](#autohideclosebuttoncollapsesdock)
- [`AutoHideHasCloseButton`](#autohidehasclosebutton)
- [`AutoHideHasMinimizeButton`](#autohidehasminimizebutton)
- [DockWidget Feature Flags](#dockwidget-feature-flags)
- [`DockWidgetClosable`](#dockwidgetclosable)
- [`DockWidgetMovable`](#dockwidgetmovable)
@@ -466,6 +475,17 @@ possible in various web browsers.
![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)
## Auto-Hide Configuration Flags
### Auto Hide Dock Widgets
@@ -480,7 +500,7 @@ Enabling this feature adds a button with a pin icon to each dock area.
![DockAreaHasAutoHideButton true](cfg_flag_DockAreaHasAutoHideButton.png)
By clicking this button, the current dock widget (or the complete area - depending on the
configuration flags) will be pinned to a certain border. The border is choosen
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
holding down the **Ctrl** key, the whole dock area will be pinned to a certain
border.
@@ -502,6 +522,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
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 an auto hide widget is similar to adding a dock widget, simply call
@@ -589,6 +662,39 @@ is shown, if the user hovers over the Auto-Hide tab or if the users moves the
mouse outside of the Auto-Hide widget. Showing and hiding my mouse click still
works if this feature is enabled.
### `AutoHideCloseButtonCollapsesDock`
Some users don't understand the distinction between closing an auto hide dock and
collapsing an auto hide dock. This may lead to situations where they press the
close button (losing the side tab widget) instead of simply clicking outside
the auto hide dock (collapsing the dock).
![AutoHideCloseButtonCollapsesDock false](cfg_flag_AutoHideCloseButtonCollapsesDock_false.gif)
If `AutoHideCloseButtonCollapsesDock` option is active, the
close button in an auto hide widget collapses the auto hide widget instead of
closing it.
![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)
## DockWidget Feature Flags
### `DockWidgetClosable`

View File

@@ -9,7 +9,7 @@ add_executable(AutoHideExample WIN32
mainwindow.ui
)
target_include_directories(AutoHideExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(AutoHideExample PRIVATE qtadvanceddocking)
target_link_libraries(AutoHideExample PRIVATE qt${QT_VERSION_MAJOR}advanceddocking)
target_link_libraries(AutoHideExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)

View File

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

View File

@@ -9,7 +9,7 @@ add_executable(CentralWidgetExample WIN32
mainwindow.ui
)
target_include_directories(CentralWidgetExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(CentralWidgetExample PRIVATE qtadvanceddocking)
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)

View File

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

View File

@@ -7,7 +7,7 @@ add_executable(DeleteOnCloseTest WIN32
main.cpp
)
target_include_directories(DeleteOnCloseTest PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(DeleteOnCloseTest PRIVATE qtadvanceddocking)
target_link_libraries(DeleteOnCloseTest PRIVATE qt${QT_VERSION_MAJOR}advanceddocking)
target_link_libraries(DeleteOnCloseTest PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)

View File

@@ -1,6 +1,6 @@
import sys
from PyQtAds import QtAds
import PyQtAds as QtAds
from PyQt5.QtGui import QCloseEvent
from PyQt5.QtCore import (qDebug, pyqtSlot, QObject, pyqtSignal)
from PyQt5.QtWidgets import (QMainWindow, QAction, QTextEdit, QApplication,
@@ -70,4 +70,4 @@ if __name__ == '__main__':
action.triggered.connect(on_action2_triggered)
w.show()
app.exec_()
app.exec_()

View File

@@ -12,7 +12,7 @@ add_executable(DockInDockExample WIN32
mainframe.cpp
)
target_include_directories(DockInDockExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(DockInDockExample PRIVATE qtadvanceddocking)
target_link_libraries(DockInDockExample PRIVATE qt${QT_VERSION_MAJOR}advanceddocking)
target_link_libraries(DockInDockExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)

View File

@@ -3,7 +3,7 @@ import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QMessageBox,
QInputDialog, QMenu, QLineEdit)
from PyQt5.QtGui import QIcon
from PyQtAds import QtAds
import PyQtAds as QtAds
from dockindockmanager import DockInDockManager
from perspectiveactions import LoadPerspectiveAction, RemovePerspectiveAction
@@ -200,4 +200,4 @@ class DockInDockWidget(QWidget):
for closed in self.getManager().dockWidgetsMap().values():
if not closed in visible_widgets:
self.dumpStatus(widget=closed, tab=tab, suffix=" (closed)")
self.dumpStatus(widget=closed, tab=tab, suffix=" (closed)")

View File

@@ -1,7 +1,7 @@
from PyQt5.QtWidgets import QAction, QMenu, QInputDialog, QLineEdit
from PyQt5.QtCore import QSettings
from PyQtAds import QtAds
import PyQtAds as QtAds
CHILD_PREFIX = "Child-"
@@ -211,4 +211,4 @@ class MoveDockWidgetAction(QAction):
widget.dockManager().removeDockWidget(widget)
move_to.addDockWidget(QtAds.CenterDockWidgetArea, widget, move_to.getInsertDefaultPos())
else:
assert False
assert False

View File

@@ -4,7 +4,7 @@ import atexit
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
from PyQt5.QtCore import Qt
from PyQtAds import QtAds
import PyQtAds as QtAds
from perspectives import PerspectivesManager
from dockindock import DockInDockWidget
@@ -69,4 +69,4 @@ if __name__ == '__main__':
w = MainWindow()
w.show()
app.exec_()
app.exec_()

View File

@@ -4,7 +4,7 @@ import shutil
import atexit
from PyQt5.QtCore import pyqtSignal, QSettings, QObject
from PyQtAds import QtAds
import PyQtAds as QtAds
from dockindockmanager import DockInDockManager
from dockindock import DockInDockWidget
@@ -200,4 +200,4 @@ class PerspectivesManager(QObject):
except FileNotFoundError:
pass
if not shutil.copy(settings.fileName(), to_save):
assert False
assert False

View File

@@ -9,7 +9,7 @@ add_executable(EmptyDockAreaExample WIN32
mainwindow.ui
)
target_include_directories(EmptyDockAreaExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(EmptyDockAreaExample PRIVATE qtadvanceddocking)
target_link_libraries(EmptyDockAreaExample PRIVATE qt${QT_VERSION_MAJOR}advanceddocking)
target_link_libraries(EmptyDockAreaExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)

View File

@@ -6,7 +6,7 @@ from PyQt5.QtCore import Qt, QSignalBlocker
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QComboBox, QTableWidget,
QAction, QWidgetAction, QSizePolicy, QInputDialog)
from PyQt5.QtGui import QCloseEvent
from PyQtAds import QtAds
import PyQtAds as QtAds
UI_FILE = os.path.join(os.path.dirname(__file__), 'mainwindow.ui')
@@ -105,4 +105,4 @@ if __name__ == '__main__':
w = CMainWindow()
w.show()
app.exec_()
app.exec_()

View File

@@ -9,7 +9,7 @@ add_executable(HideShowExample WIN32
MainWindow.ui
)
target_include_directories(HideShowExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(HideShowExample PRIVATE qtadvanceddocking)
target_link_libraries(HideShowExample PRIVATE qt${QT_VERSION_MAJOR}advanceddocking)
target_link_libraries(HideShowExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)

View File

@@ -9,7 +9,7 @@ add_executable(SidebarExample WIN32
MainWindow.ui
)
target_include_directories(SidebarExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(SidebarExample PRIVATE qtadvanceddocking)
target_link_libraries(SidebarExample PRIVATE qt${QT_VERSION_MAJOR}advanceddocking)
target_link_libraries(SidebarExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)

View File

@@ -5,7 +5,7 @@ from PyQt5 import uic
from PyQt5.QtCore import Qt, QMargins
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')
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)

View File

@@ -9,7 +9,7 @@ add_executable(SimpleExample WIN32
MainWindow.ui
)
target_include_directories(SimpleExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(SimpleExample PRIVATE qtadvanceddocking)
target_link_libraries(SimpleExample PRIVATE qt${QT_VERSION_MAJOR}advanceddocking)
target_link_libraries(SimpleExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)

View File

@@ -6,7 +6,7 @@ from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QCloseEvent
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')
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)

View File

@@ -1,4 +1,5 @@
import os
import sys
from pyqtbuild import PyQtBindings, PyQtProject
from sipbuild import Option
@@ -16,12 +17,37 @@ class ads(PyQtBindings):
""" Initialise the bindings. """
super().__init__(project, 'ads')
def get_options(self):
"""Our custom options that a user can pass to sip-build."""
options = super().get_options()
options += [
Option('ads_incdir',
help='the directory containing the ads header file',
metavar='DIR'),
Option('ads_libdir',
help='the directory containing the ads library',
metavar='DIR'),
Option('ads_lib',
help='the ads library',
metavar='LIB'),
]
return options
def apply_user_defaults(self, tool):
""" Set default values for user options that haven't been set yet. """
resource_file = os.path.join(self.project.root_dir,'src','ads.qrc')
print("Adding resource file to qmake project: ", resource_file)
self.builder_settings.append('RESOURCES += '+resource_file)
if self.ads_lib is not None:
self.libraries.append(self.ads_lib)
if self.ads_incdir is not None:
self.include_dirs.append(self.ads_incdir)
if self.ads_libdir is not None:
self.library_dirs.append(self.ads_libdir)
super().apply_user_defaults(tool)

View File

@@ -1,12 +1,12 @@
# Specify the build system.
[build-system]
requires = ["sip >=6.0.2, <6.6", "PyQt-builder >=1.6, <2", "PyQt5>=5.15.4", "PyQt5-sip<13,>=12.8"]
requires = ["sip >=6.0.2", "PyQt-builder >=1.6", "PyQt5>=5.15", "PyQt5-sip>=12.8"]
build-backend = "sipbuild.api"
# Specify the PEP 566 metadata for the project.
[tool.sip.metadata]
name = "PyQtAds"
version = "3.8.2"
version = "4.4.1"
summary = "Python bindings for Qt Advanced Docking System"
home-page = "https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/"
license = "LGPL v2.1"
@@ -16,13 +16,18 @@ description-content-type = "text/markdown"
[tool.sip.project]
tag-prefix = "QtAds"
dunder-init = true
[tool.sip.bindings.ads]
pep484-pyi = true
define-macros = ["ADS_SHARED_EXPORT"]
sip-file = "ads.sip"
include-dirs = ["src"]
qmake-QT = ["widgets"]
qmake-QT = ["widgets", "gui-private; platform_system == 'Linux'"]
headers = [
"src/AutoHideDockContainer.h",
"src/AutoHideSideBar.h",
"src/AutoHideTab.h",
"src/DockAreaTabBar.h",
"src/DockAreaTitleBar.h",
"src/DockAreaTitleBar_p.h",
@@ -40,10 +45,15 @@ headers = [
"src/FloatingDockContainer.h",
"src/FloatingDragPreview.h",
"src/IconProvider.h",
"src/PushButton.h",
"src/ResizeHandle.h",
"src/ads_globals.h",
# "src/linux/FloatingWidgetTitleBar.h",
"src/linux/FloatingWidgetTitleBar.h; platform_system == 'Linux'",
]
sources = [
"src/AutoHideTab.cpp",
"src/AutoHideDockContainer.cpp",
"src/AutoHideSideBar.cpp",
"src/DockAreaTabBar.cpp",
"src/DockAreaTitleBar.cpp",
"src/DockAreaWidget.cpp",
@@ -60,6 +70,8 @@ sources = [
"src/FloatingDockContainer.cpp",
"src/FloatingDragPreview.cpp",
"src/IconProvider.cpp",
"src/PushButton.cpp",
"src/ResizeHandle.cpp",
"src/ads_globals.cpp",
# "src/linux/FloatingWidgetTitleBar.cpp",
"src/linux/FloatingWidgetTitleBar.cpp; platform_system == 'Linux'",
]

View File

@@ -1,7 +0,0 @@
[versioneer]
VCS = git
style = pep440
versionfile_source = PyQtAds/_version.py
versionfile_build = PyQtAds/_version.py
tag_prefix =

396
setup.py
View File

@@ -1,396 +0,0 @@
import os
import sys
import shlex
import shutil
import subprocess
import glob
import versioneer
from setuptools import setup, find_packages
from setuptools.command.build_py import build_py
from setuptools.extension import Extension
from distutils import sysconfig, dir_util, spawn, log, cmd
from distutils.dep_util import newer
import sipdistutils
import sipconfig
from PyQt5.QtCore import PYQT_CONFIGURATION
from PyQt5.pyrcc_main import processResourceFile
MODULE_NAME = "ads"
SRC_PATH = "PyQtAds"
REQUIRE_PYQT = True
if "--conda-recipe" in sys.argv:
REQUIRE_PYQT = False
sys.argv.remove("--conda-recipe")
class HostPythonConfiguration(object):
def __init__(self):
self.platform = sys.platform
self.version = sys.hexversion>>8
self.inc_dir = sysconfig.get_python_inc()
self.venv_inc_dir = sysconfig.get_python_inc(prefix=sys.prefix)
self.module_dir = sysconfig.get_python_lib(plat_specific=1)
if sys.platform == 'win32':
self.data_dir = sys.prefix
self.lib_dir = sys.prefix +'\\libs'
else:
self.data_dir = sys.prefix + '/share'
self.lib_dir = sys.prefix + '/lib'
class TargetQtConfiguration(object):
def __init__(self, qmake):
pipe = os.popen(' '.join([qmake, '-query']))
for l in pipe:
l = l.strip()
tokens = l.split(':', 1)
if isinstance(tokens, list):
if len(tokens) != 2:
error("Unexpected output from qmake: '%s'\n" % l)
name, value = tokens
else:
name = tokens
value = None
name = name.replace('/', '_')
setattr(self, name, value)
pipe.close()
class build_ext(sipdistutils.build_ext):
description = "Builds the " + MODULE_NAME + " module."
user_options = sipdistutils.build_ext.user_options + [
('qmake-bin=', None, "Path to qmake binary"),
('sip-bin=', None, "Path to sip binary"),
('qt-include-dir=', None, "Path to Qt headers"),
('pyqt-sip-dir=', None, "Path to PyQt's SIP files"),
('pyqt-sip-flags=', None, "SIP flags used to generate PyQt bindings"),
('sip-dir=', None, "Path to module's SIP files"),
('inc-dir=', None, "Path to module's include files")
]
def initialize_options (self):
super().initialize_options()
self.qmake_bin = 'qmake'
self.sip_bin = None
self.qt_include_dir = None
self.qt_libinfix = ''
self.pyqt_sip_dir = None
self.pyqt_sip_flags = None
self.sip_files_dir = None
self.sip_inc_dir = None
self.inc_dir = None
self.pyconfig = HostPythonConfiguration()
self.qtconfig = TargetQtConfiguration(self.qmake_bin)
self.config = sipconfig.Configuration()
self.config.default_mod_dir = ("/usr/local/lib/python%i.%i/dist-packages" %
(sys.version_info.major, sys.version_info.minor))
def finalize_options (self):
super().finalize_options()
if not self.qt_include_dir:
self.qt_include_dir = self.qtconfig.QT_INSTALL_HEADERS
if not self.qt_libinfix:
try:
with open(os.path.join(self.qtconfig.QT_INSTALL_PREFIX, 'mkspecs', 'qconfig.pri'), 'r') as f:
for line in f.readlines():
if line.startswith('QT_LIBINFIX'):
self.qt_libinfix = line.split('=')[1].strip('\n').strip()
except (FileNotFoundError, IndexError):
pass
if not self.pyqt_sip_dir:
self.pyqt_sip_dir = os.path.join(self.pyconfig.data_dir, 'sip', 'PyQt5')
if not self.pyqt_sip_flags:
self.pyqt_sip_flags = PYQT_CONFIGURATION.get('sip_flags', '')
if not self.sip_files_dir:
self.sip_files_dir = os.path.abspath(os.path.join(".", "sip"))
if not self.sip_inc_dir:
self.sip_inc_dir = self.pyconfig.venv_inc_dir
if not self.inc_dir:
self.inc_dir = os.path.abspath(os.path.join(".", "src"))
if not self.qt_include_dir:
raise SystemExit('Could not find Qt5 headers. '
'Please specify via --qt-include-dir=')
if not self.pyqt_sip_dir:
raise SystemExit('Could not find PyQt SIP files. '
'Please specify containing directory via '
'--pyqt-sip-dir=')
if not self.pyqt_sip_flags:
raise SystemExit('Could not find PyQt SIP flags. '
'Please specify via --pyqt-sip-flags=')
def _find_sip(self):
"""override _find_sip to allow for manually speficied sip path."""
# 1. Manually specified sip_bin
if self.sip_bin:
return self.sip_bin
# 2. Path determined from sipconfig.Configuration()
# This may not exist, depending on conda build configuration.
sip_bin = super()._find_sip()
if os.path.exists(sip_bin):
return sip_bin
# 3. Finally, fall back to sip binary found in path
sip_bin = shutil.which('sip')
if sip_bin:
return sip_bin
raise SystemExit('Could not find PyQt SIP binary.')
def _sip_sipfiles_dir(self):
sip_dir = super()._sip_sipfiles_dir()
if os.path.exists(sip_dir):
return sip_dir
return os.path.join(sys.prefix, 'sip', 'PyQt5')
def _sip_compile(self, sip_bin, source, sbf):
target_dir = os.path.dirname(__file__) if self.inplace else self.build_lib
pyi = os.path.join(target_dir, "PyQtAds", "QtAds", "ads.pyi")
if not os.path.exists(os.path.dirname(pyi)):
os.makedirs(os.path.dirname(pyi))
cmd = [sip_bin]
if hasattr(self, 'sip_opts'):
cmd += self.sip_opts
if hasattr(self, '_sip_sipfiles_dir'):
cmd += ['-I', self._sip_sipfiles_dir()]
cmd += [
"-I", self.sip_files_dir,
"-I", self.pyqt_sip_dir,
"-I", self.sip_inc_dir,
"-I", self.inc_dir,
"-c", self._sip_output_dir(),
"-b", sbf,
"-y", pyi,
"-w", "-o"]
cmd += shlex.split(self.pyqt_sip_flags) # use same SIP flags as for PyQt5
cmd.append(source)
self.spawn(cmd)
if os.path.exists(pyi):
with open(pyi) as f:
content = f.readlines()
with open(pyi, "w") as f:
for line in content:
if not line.startswith("class ads"):
f.write(line)
def swig_sources (self, sources, extension=None):
if not self.extensions:
return
# Add the local include directory to the include path
if extension is not None:
extension.extra_compile_args += ['-D', 'QT_CORE_LIB',
'-D', 'QT_GUI_LIB',
'-D', 'QT_WIDGETS_LIB',
'-D', 'ADS_SHARED_EXPORT']
extension.include_dirs += [self.qt_include_dir, self.inc_dir,
os.path.join(self.qt_include_dir, 'QtCore'),
os.path.join(self.qt_include_dir, 'QtGui'),
os.path.join(self.qt_include_dir, 'QtWidgets')]
extension.libraries += ['Qt5Core' + self.qt_libinfix,
'Qt5Gui' + self.qt_libinfix,
'Qt5Widgets' + self.qt_libinfix]
if sys.platform == 'win32':
extension.library_dirs += [self.qtconfig.QT_INSTALL_LIBS,
self.inc_dir, self._sip_output_dir()]
elif sys.platform == 'darwin':
extension.extra_compile_args += ['-F' + self.qtconfig.QT_INSTALL_LIBS,
'-std=c++11', '-stdlib=libc++', '-mmacosx-version-min=10.9']
extension.extra_link_args += ['-F' + self.qtconfig.QT_INSTALL_LIBS,
'-mmacosx-version-min=10.9']
elif sys.platform == 'linux':
extension.extra_compile_args += ['-std=c++11']
return super().swig_sources(sources, extension)
def build_extension(self, ext):
cppsources = [source for source in ext.sources if source.endswith(".cpp")]
headersources = ['src/DockAreaTitleBar_p.h']
dir_util.mkpath(self.build_temp, dry_run=self.dry_run)
def get_moc_args(out_file, source):
if sys.platform.startswith('linux'):
return ["moc", "-D", "Q_OS_LINUX=1", "-o", out_file, source]
if sys.platform.startswith('darwin'):
return ["moc", "-D", "Q_OS_MACOS=1", "-o", out_file, source]
if sys.platform.startswith('win'):
return ["moc", "-D", "Q_OS_WIN=1", "-o", out_file, source]
return ["moc", "-o", out_file, source]
# Run moc on all header files.
for source in cppsources:
# *.cpp -> *.moc
moc_file = os.path.basename(source).replace(".cpp", ".moc")
out_file = os.path.join(self.build_temp, moc_file)
if newer(source, out_file) or self.force:
spawn.spawn(get_moc_args(out_file, source), dry_run=self.dry_run)
header = source.replace(".cpp", ".h")
if os.path.exists(header):
# *.h -> moc_*.cpp
moc_file = "moc_" + os.path.basename(header).replace(".h", ".cpp")
out_file = os.path.join(self.build_temp, moc_file)
if newer(header, out_file) or self.force:
spawn.spawn(get_moc_args(out_file, header), dry_run=self.dry_run)
if os.path.getsize(out_file) > 0:
ext.sources.append(out_file)
# Run moc on all orphan header files.
for source in headersources:
# *.cpp -> *.moc
moc_file = os.path.basename(source).replace(".h", ".moc")
out_file = os.path.join(self.build_temp, moc_file)
if newer(source, out_file) or self.force:
spawn.spawn(get_moc_args(out_file, source),
dry_run=self.dry_run)
header = source
if os.path.exists(header):
# *.h -> moc_*.cpp
moc_file = "moc_" + os.path.basename(header).replace(
".h", ".cpp")
out_file = os.path.join(self.build_temp, moc_file)
if newer(header, out_file) or self.force:
spawn.spawn(get_moc_args(out_file, header),
dry_run=self.dry_run)
if os.path.getsize(out_file) > 0:
ext.sources.append(out_file)
# Add the temp build directory to include path, for compiler to find
# the created .moc files
ext.include_dirs += [self._sip_output_dir()]
# Run rcc on all resource files
resources = [source for source in ext.sources if source.endswith(".qrc")]
for source in resources:
ext.sources.remove(source)
out_file = os.path.join(self.build_temp, "qrc_" + os.path.basename(source).replace(".qrc", ".cpp"))
if newer(header, out_file) or self.force:
spawn.spawn(["rcc", "-name", os.path.splitext(os.path.basename(source))[0], source, "-o", out_file], dry_run=self.dry_run)
if os.path.getsize(out_file) > 0:
ext.sources.append(out_file)
sipdistutils.build_ext.build_extension(self, ext)
import inspect
sys.path.append(os.path.join(self.build_lib, 'PyQtAds', 'QtAds'))
import ads
with open(os.path.join(self.build_lib, 'PyQtAds', 'QtAds', '__init__.py'), 'w') as f:
f.write('from .._version import *\n')
f.write('from .ads import ads\n')
for name, member in sorted(inspect.getmembers(ads.ads)):
if not name.startswith('_'):
f.write('{0} = ads.{0}\n'.format(name))
class ProcessResourceCommand(cmd.Command):
"""A custom command to compile the resource file into a Python file"""
description = "Compile the qrc file into a python file"
def initialize_options(self):
return
def finalize_options(self):
return
def run(self):
processResourceFile([os.path.join('src', 'ads.qrc')],
os.path.join(SRC_PATH, 'rc.py'), False)
class BuildPyCommand(build_py):
"""Custom build command to include ProcessResource command"""
def run(self):
self.run_command("process_resource")
build_py.run(self)
setup_requires = ["PyQt5"] if REQUIRE_PYQT else []
cpp_sources = glob.glob(os.path.join('src', '*.cpp'))
sip_sources = [os.path.join('sip', MODULE_NAME + '.sip')]
resources = [os.path.join('src', MODULE_NAME + '.qrc')]
if sys.platform == 'linux':
cpp_sources += glob.glob(os.path.join('src', 'linux', '*.cpp'))
ext_modules = [Extension('PyQtAds.QtAds.ads', cpp_sources + sip_sources + resources)]
install_requires = ["PyQt5"]
if sys.platform == 'win32':
install_requires.append("pywin32")
with open('README.md', 'r') as f:
LONG_DESCRIPTION = f.read()
setup(
name = SRC_PATH,
author = "Nicolas Elie",
author_email = "nicolas.elie@cnrs.fr",
url = "https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System",
version = versioneer.get_version(),
description = "Advanced Docking System for Qt",
long_description = LONG_DESCRIPTION,
keywords = ["qt"],
license = "LGPLv2+",
classifiers = ["Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)",
"Operating System :: OS Independent",
"Topic :: Software Development :: Libraries :: Python Modules",
"Environment :: Win32 (MS Windows)",
"Environment :: MacOS X",
"Environment :: X11 Applications :: Qt",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.2",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7"],
ext_modules = ext_modules,
cmdclass = versioneer.get_cmdclass({'process_resource': ProcessResourceCommand,
'build_py': BuildPyCommand,
'build_ext': build_ext}),
packages = find_packages(),
setup_requires = setup_requires,
install_requires = install_requires,
zip_safe=False
)

View File

@@ -0,0 +1,49 @@
%Import QtWidgets/QtWidgetsmod.sip
%If (Qt_5_0_0 -)
namespace ads
{
class CAutoHideDockContainer : QFrame
{
%TypeHeaderCode
#include <AutoHideDockContainer.h>
%End
protected:
virtual bool eventFilter(QObject* watched, QEvent* event);
virtual void resizeEvent(QResizeEvent* event);
virtual void leaveEvent(QEvent *event);
virtual bool event(QEvent* event);
void updateSize();
void saveState(QXmlStreamWriter& Stream);
public:
CAutoHideDockContainer(ads::CDockWidget* DockWidget /Transfer/, ads::SideBarLocation area,
ads::CDockContainerWidget* parent /TransferThis/);
virtual ~CAutoHideDockContainer();
ads::CAutoHideSideBar* autoHideSideBar() const;
ads::CAutoHideTab* autoHideTab() const;
ads::CDockWidget* dockWidget() const;
int tabIndex() const;
void addDockWidget(ads::CDockWidget* DockWidget /Transfer/);
ads::SideBarLocation sideBarLocation() const;
void setSideBarLocation(ads::SideBarLocation SideBarLocation);
ads::CDockAreaWidget* dockAreaWidget() const;
ads::CDockContainerWidget* dockContainer() const;
void moveContentsToParent();
void cleanupAndDelete();
void toggleView(bool Enable);
void collapseView(bool Enable);
void toggleCollapseState();
void setSize(int Size);
void resetToInitialDockWidgetSize();
Qt::Orientation orientation() const;
void moveToNewSideBarLocation(ads::SideBarLocation);
};
};
%End

46
sip/AutoHideSideBar.sip Normal file
View File

@@ -0,0 +1,46 @@
%Import QtWidgets/QtWidgetsmod.sip
%If (Qt_5_0_0 -)
namespace ads
{
class CAutoHideSideBar : QScrollArea
{
%TypeHeaderCode
#include <AutoHideSideBar.h>
%End
protected:
virtual bool eventFilter(QObject *watched, QEvent *event);
void saveState(QXmlStreamWriter& Stream) const;
void insertTab(int Index, ads::CAutoHideTab* SideTab /Transfer/);
public:
CAutoHideSideBar(ads::CDockContainerWidget* parent /TransferThis/, SideBarLocation area);
virtual ~CAutoHideSideBar();
void removeTab(ads::CAutoHideTab* SideTab) /TransferBack/;
ads::CAutoHideDockContainer* insertDockWidget(int Index, ads::CDockWidget* DockWidget /Transfer/);
void removeAutoHideWidget(ads::CAutoHideDockContainer* AutoHideWidget) /TransferBack/;
void addAutoHideWidget(ads::CAutoHideDockContainer* AutoHideWidget, int Index);
Qt::Orientation orientation() const;
ads::CAutoHideTab* tab(int index) 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;
virtual QSize minimumSizeHint() const;
virtual QSize sizeHint() const;
int spacing() const;
void setSpacing(int Spacing);
CDockContainerWidget* dockContainer() const;
};
};
%End

44
sip/AutoHideTab.sip Normal file
View File

@@ -0,0 +1,44 @@
%Import QtWidgets/QtWidgetsmod.sip
%If (Qt_5_0_0 -)
namespace ads
{
class CAutoHideTab : CPushButton
{
%TypeHeaderCode
#include <AutoHideTab.h>
%End
protected:
void setSideBar(ads::CAutoHideSideBar *SideTabBar);
void removeFromSideBar();
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:
CAutoHideTab(QWidget* parent /TransferThis/ = 0);
virtual ~CAutoHideTab();
void updateStyle();
ads::SideBarLocation sideBarLocation() const;
void setOrientation(Qt::Orientation Orientation);
Qt::Orientation orientation() const;
bool isActiveTab() const;
ads::CDockWidget* dockWidget() const;
void setDockWidget(ads::CDockWidget* DockWidget);
bool iconOnly() const;
ads::CAutoHideSideBar* sideBar() const;
int tabIndex() const;
void setDockWidgetFloating();
void unpinDockWidget();
void requestCloseDockWidget();
};
};
%End

View File

@@ -23,6 +23,8 @@ public:
int currentIndex() const;
ads::CDockWidgetTab* currentTab() 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);
bool isTabOpen(int Index) const;
virtual QSize minimumSizeHint() const;

View File

@@ -5,6 +5,22 @@
namespace ads
{
class CTitleBarButton : QToolButton
{
%TypeHeaderCode
#include <DockAreaTitleBar.h>
%End
public:
CTitleBarButton(bool visible = true, QWidget* parent /TransferThis/ = Q_NULLPTR );
virtual void setVisible(bool);
void setShowInTitleBar(bool);
protected:
bool event(QEvent *ev);
};
class CDockAreaTitleBar : QFrame
{
%TypeHeaderCode
@@ -26,12 +42,15 @@ public:
CDockAreaTitleBar(ads::CDockAreaWidget* parent /TransferThis/);
virtual ~CDockAreaTitleBar();
ads::CDockAreaTabBar* tabBar() const;
QAbstractButton* button(ads::TitleBarButton which) const;
ads::CTitleBarButton* button(ads::TitleBarButton which) const;
ads::CElidingLabel* autoHideTitleLabel() const;
void updateDockWidgetActionsButtons();
virtual void setVisible(bool Visible);
void insertWidget(int index, QWidget *widget /Transfer/ );
int indexOf(QWidget *widget) const;
QString titleBarButtonToolTip(ads::TitleBarButton Button) const;
void setAreaFloating();
signals:
void tabBarClicked(int index);

View File

@@ -5,21 +5,6 @@
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
{
%TypeHeaderCode

View File

@@ -23,6 +23,7 @@ protected:
void updateTitleBarVisibility();
void internalSetCurrentDockWidget(ads::CDockWidget* DockWidget /Transfer/);
void markTitleBarMenuOutdated();
void updateTitleBarButtonVisibility(bool IsTopLevel) const;
protected slots:
void toggleView(bool Open);
@@ -39,6 +40,9 @@ public:
virtual ~CDockAreaWidget();
ads::CDockManager* dockManager() const;
ads::CDockContainerWidget* dockContainer() const;
ads::CAutoHideDockContainer* autoHideDockContainer() const;
bool isAutoHide() const;
void setAutoHideDockContainer(CAutoHideDockContainer*);
virtual QSize minimumSizeHint() const;
QRect titleBarGeometry() const;
QRect contentAreaGeometry() const;
@@ -52,6 +56,8 @@ public:
ads::CDockWidget* currentDockWidget() const;
void setCurrentDockWidget(ads::CDockWidget* DockWidget);
void saveState(QXmlStreamWriter& Stream) const;
static bool restoreState(ads::CDockingStateReader& Stream, ads::CDockAreaWidget*& CreatedWidget,
bool Testing, ads::CDockContainerWidget* ParentContainer);
ads::CDockWidget::DockWidgetFeatures features(ads::eBitwiseOperator Mode = ads::BitwiseAnd) const;
QAbstractButton* titleBarButton(ads::TitleBarButton which) const;
virtual void setVisible(bool Visible);
@@ -65,11 +71,16 @@ public:
void setDockAreaFlag(eDockAreaFlag Flag, bool On);
bool isCentralWidgetArea() const;
bool containsCentralWidget() const;
bool isTopLevelArea() const;
public slots:
void setCurrentIndex(int index);
void closeArea();
void setAutoHide(bool Enable, SideBarLocation Location = ads::SideBarNone, int TabIndex = -1);
void toggleAutoHide(SideBarLocation Location = ads::SideBarNone);
void closeOtherAreas();
void setFloating();
signals:
void tabBarClicked(int index);

View File

@@ -13,6 +13,7 @@ class CDockComponentsFactory
public:
virtual ~CDockComponentsFactory();
virtual CDockWidgetTab* createDockWidgetTab(CDockWidget* DockWidget /Transfer/ ) const;
virtual CAutoHideTab* createDockWidgetSideTab(CDockWidget* DockWidget /Transfer/) const;
virtual CDockAreaTabBar* createDockAreaTabBar(CDockAreaWidget* DockArea /Transfer/ ) const;
virtual CDockAreaTitleBar* createDockAreaTitleBar(CDockAreaWidget* DockArea /Transfer/ ) const;
static const CDockComponentsFactory* factory();

View File

@@ -9,8 +9,8 @@ namespace ads
* Container that manages a number of dock areas with single dock widgets
* or tabyfied dock widgets in each area.
* Each window that support docking has a DockContainerWidget. That means
* the main application window and all floating windows are ore contain
* an DockContainerWidget.
* the main application window and all floating windows contain a
* DockContainerWidget.
*/
class CDockContainerWidget : QFrame
{
@@ -21,9 +21,10 @@ class CDockContainerWidget : QFrame
protected:
virtual bool event(QEvent *e);
QSplitter* rootSplitter() const;
ads::CAutoHideDockContainer* createAndSetupAutoHideContainer(ads::SideBarLocation area, ads::CDockWidget* DockWidget /Transfer/, int TabIndex = -1);
void createRootSplitter();
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 removeDockArea(ads::CDockAreaWidget* area /TransferBack/);
void saveState(QXmlStreamWriter& Stream) const;
@@ -33,124 +34,44 @@ protected:
ads::CDockAreaWidget* topLevelDockArea() const;
QList<ads::CDockWidget*> dockWidgets() const;
void updateSplitterHandles(QSplitter* splitter);
void registerAutoHideWidget(ads::CAutoHideDockContainer* AutoHideWidget /Transfer/);
void removeAutoHideWidget(ads::CAutoHideDockContainer* AutoHideWidget /TransferBack/);
void handleAutoHideWidgetEvent(QEvent* e, QWidget* w);
public:
/**
* Default Constructor
*/
CDockContainerWidget(ads::CDockManager* DockManager /TransferThis/, QWidget* parent /TransferThis/ = 0);
/**
* Virtual Destructor
*/
virtual ~CDockContainerWidget();
/**
* Adds dockwidget into the given area.
* If DockAreaWidget is not null, then the area parameter indicates the area
* into the DockAreaWidget. If DockAreaWidget is null, the Dockwidget will
* be dropped into the container.
* \return Returns the dock area widget that contains the new DockWidget
*/
ads::CDockAreaWidget* addDockWidget(ads::DockWidgetArea area, ads::CDockWidget* Dockwidget /Transfer/,
ads::CDockAreaWidget* DockAreaWidget /Transfer/ = 0);
/**
* Removes dockwidget
*/
ads::CDockAreaWidget* DockAreaWidget /Transfer/ = 0,
int Index = -1);
void removeDockWidget(ads::CDockWidget* Dockwidget) /TransferBack/;
/**
* Returns the current zOrderIndex
*/
virtual unsigned int zOrderIndex() const;
/**
* This function returns true if this container widgets z order index is
* higher than the index of the container widget given in Other parameter
*/
bool isInFrontOf(ads::CDockContainerWidget* Other) const;
/**
* Returns the dock area at teh given global position or 0 if there is no
* dock area at this position
*/
ads::CDockAreaWidget* dockAreaAt(const QPoint& GlobalPos) const;
/**
* Returns the dock area at the given Index or 0 if the index is out of
* range
*/
ads::CDockAreaWidget* dockArea(int Index) const;
/**
* Returns the list of dock areas that are not closed
* If all dock widgets in a dock area are closed, the dock area will be closed
*/
QList<ads::CDockAreaWidget*> openedDockAreas() const;
QList<ads::CDockWidget*> openedDockWidgets() const;
bool hasTopLevelDockWidget() const;
/**
* Returns the number of dock areas in this container
*/
int dockAreaCount() const;
/**
* Returns the number of visible dock areas
*/
int visibleDockAreaCount() const;
/**
* This function returns true, if this container is in a floating widget
*/
bool isFloating() const;
/**
* Dumps the layout for debugging purposes
*/
void dumpLayout();
/**
* This functions returns the dock widget features of all dock widget in
* this container.
* A bitwise and is used to combine the flags of all dock widgets. That
* means, if only dock widget does not support a certain flag, the whole
* dock are does not support the flag.
*/
ads::CDockWidget::DockWidgetFeatures features() const;
/**
* If this dock container is in a floating widget, this function returns
* the floating widget.
* Else, it returns a nullptr.
*/
ads::CFloatingDockContainer* floatingWidget() const;
/**
* Call this function to close all dock areas except the KeepOpenArea
*/
void closeOtherAreas(ads::CDockAreaWidget* KeepOpenArea);
ads::CAutoHideSideBar* autoHideSideBar(SideBarLocation area) const;
QList<ads::CAutoHideDockContainer*> autoHideWidgets() const;
QRect contentRect() const;
QRect contentRectGlobal() const;
ads::CDockManager* dockManager() const;
signals:
/**
* This signal is emitted if one or multiple dock areas has been added to
* the internal list of dock areas.
* If multiple dock areas are inserted, this signal is emitted only once
*/
void dockAreasAdded();
/**
* This signal is emitted if one or multiple dock areas has been removed
*/
void autoHideWidgetCreated(ads::CAutoHideDockContainer* AutoHideWidget);
void dockAreasRemoved();
/**
* This signal is emitted if a dock area is opened or closed via
* toggleView() function
*/
void dockAreaViewToggled(ads::CDockAreaWidget* DockArea, bool Open);
}; // class DockContainerWidget
};
// namespace ads
};
%End

View File

@@ -22,6 +22,8 @@ public:
void notifyFloatingWidgetDrop(ads::CFloatingDockContainer* FloatingWidget);
ads::CDockWidget* focusedDockWidget() const;
void setDockWidgetTabFocused(ads::CDockWidgetTab* Tab);
void clearDockWidgetFocus(ads::CDockWidget* dockWidget);
void setDockWidgetTabPressed(bool Value);
public slots:
void setDockWidgetFocused(ads::CDockWidget* focusedNow);

View File

@@ -156,7 +156,6 @@ public:
TabCloseButtonIsToolButton,
AllTabsHaveCloseButton,
RetainTabSizeWhenCloseButtonHidden,
OpaqueUndocking,
DragPreviewIsDynamic,
DragPreviewShowsContentPixmap,
DragPreviewHasWindowFrame,
@@ -180,6 +179,18 @@ public:
NonOpaqueWithWindowFrame,
};
typedef QFlags<ads::CDockManager::eConfigFlag> ConfigFlags;
enum eAutoHideFlag
{
AutoHideFeatureEnabled,
DockAreaHasAutoHideButton,
AutoHideButtonTogglesArea,
AutoHideButtonCheckable,
AutoHideSideBarsIconOnly,
AutoHideShowOnMouseOver,
AutoHideCloseButtonCollapsesDock,
DefaultAutoHideConfig,
};
typedef QFlags<ads::CDockManager::eAutoHideFlag> AutoHideFlags;
CDockManager(QWidget* parent /TransferThis/ = 0);
virtual ~CDockManager();
@@ -187,13 +198,24 @@ public:
static void setConfigFlags(const ads::CDockManager::ConfigFlags Flags);
static void setConfigFlag(ads::CDockManager::eConfigFlag Flag, bool On = true);
static bool testConfigFlag(eConfigFlag Flag);
static ads::CDockManager::AutoHideFlags autoHideConfigFlags();
static void setAutoHideConfigFlags(const ads::CDockManager::AutoHideFlags Flags);
static void setAutoHideConfigFlag(ads::CDockManager::eAutoHideFlag Flag, bool On = true);
static bool testAutoHideConfigFlag(eAutoHideFlag Flag);
static ads::CIconProvider& iconProvider();
ads::CDockAreaWidget* addDockWidget(ads::DockWidgetArea area, ads::CDockWidget* Dockwidget /Transfer/,
ads::CDockAreaWidget* DockAreaWidget /Transfer/ = 0);
ads::CDockAreaWidget* DockAreaWidget /Transfer/ = 0,
int Index = -1);
ads::CDockAreaWidget* addDockWidgetToContainer(ads::DockWidgetArea area, ads::CDockWidget* Dockwidget /Transfer/,
ads::CDockContainerWidget* DockContainerWidget /Transfer/ = 0);
ads::CAutoHideDockContainer* addAutoHideDockWidget(ads::SideBarLocation Location, ads::CDockWidget* Dockwidget /Transfer/);
ads::CAutoHideDockContainer* addAutoHideDockWidgetToContainer(SideBarLocation Location,
ads::CDockWidget* Dockwidget /Transfer/, ads::CDockContainerWidget* DockContainerWidget);
ads::CDockAreaWidget* addDockWidgetTab(ads::DockWidgetArea area,
ads::CDockWidget* Dockwidget /Transfer/);
ads::CDockAreaWidget* addDockWidgetTabToArea(ads::CDockWidget* Dockwidget /Transfer/,
ads::CDockAreaWidget* DockAreaWidget /Transfer/);
ads::CDockAreaWidget* DockAreaWidget /Transfer/,
int Index = -1);
ads::CFloatingDockContainer* addDockWidgetFloating(ads::CDockWidget* DockWidget /Transfer/);
ads::CDockWidget* findDockWidget(const QString& ObjectName) const;
void removeDockWidget(ads::CDockWidget* Dockwidget) /TransferBack/;
@@ -216,12 +238,16 @@ public:
QMenu* viewMenu() const;
void setViewMenuInsertionOrder(ads::CDockManager::eViewMenuInsertionOrder Order);
bool isRestoringState() const;
bool isLeavingMinimizedState() const;
static int startDragDistance();
ads::CDockWidget* focusedDockWidget() const;
QList<int> splitterSizes(ads::CDockAreaWidget *ContainedArea) const;
void setSplitterSizes(ads::CDockAreaWidget *ContainedArea, const QList<int>& sizes);
static void setFloatingContainersTitle(const QString& Title);
static QString floatingContainersTitle();
public slots:
void endLeavingMinimizedState();
void openPerspective(const QString& PerspectiveName);
void setDockWidgetFocused(ads::CDockWidget* DockWidget);

View File

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

View File

@@ -35,6 +35,7 @@ public:
DockWidgetForceCloseWithArea,
NoTab,
DeleteContentOnClose,
DockWidgetPinnable,
DefaultDockWidgetFeatures,
AllDockWidgetFeatures,
DockWidgetAlwaysCloseAndDelete,
@@ -59,7 +60,9 @@ public:
enum eMinimumSizeHintMode
{
MinimumSizeHintFromDockWidget,
MinimumSizeHintFromContent
MinimumSizeHintFromContent,
MinimumSizeHintFromDockWidgetMinimumSize,
MinimumSizeHintFromContentMinimumSize,
};
enum eToggleViewActionMode
@@ -81,13 +84,20 @@ public:
ads::CDockWidget::DockWidgetFeatures features() const;
ads::CDockManager* dockManager() const;
ads::CDockContainerWidget* dockContainer() const;
ads::CFloatingDockContainer* floatingDockContainer() const;
ads::CDockAreaWidget* dockAreaWidget() const;
ads::CAutoHideTab* sideTabWidget() const;
void setSideTabWidget(ads::CAutoHideTab* SideTab /Transfer/) const;
bool isAutoHide() const;
ads::CAutoHideDockContainer* autoHideDockContainer() const;
ads::SideBarLocation autoHideLocation() const;
bool isFloating() const;
bool isInFloatingContainer() const;
bool isClosed() const;
QAction* toggleViewAction() const;
void setToggleViewActionMode(ads::CDockWidget::eToggleViewActionMode Mode);
void setMinimumSizeHintMode(ads::CDockWidget::eMinimumSizeHintMode Mode);
ads::CDockWidget::eMinimumSizeHintMode minimumSizeHintMode() const;
bool isCentralWidget() const;
void setIcon(const QIcon& Icon);
QIcon icon() const;
@@ -116,8 +126,11 @@ public slots:
void setFloating();
void deleteDockWidget();
void closeDockWidget();
void requestCloseDockWidget();
void showFullScreen();
void showNormal();
void setAutoHide(bool Enable, ads::SideBarLocation Location = ads::SideBarNone, int TabIndex = -1);
void toggleAutoHide(ads::SideBarLocation Location = ads::SideBarNone);
signals:
void viewToggled(bool Open);

View File

@@ -64,6 +64,7 @@ protected:
%If (WS_X11)
virtual void moveEvent(QMoveEvent *event);
virtual void resizeEvent(QResizeEvent *event);
virtual bool event(QEvent *e);
%End
%If (WS_WIN)

View File

@@ -27,10 +27,9 @@ public:
public: // implements IFloatingWidget
virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
ads::eDragState DragState, QWidget* MouseEventHandler);
virtual void moveFloating();
virtual void finishDragging();
void cleanupAutoHideContainerWidget(ads::DockWidgetArea ContainerDropArea);
signals:
void draggingCanceled();

31
sip/PushButton.sip Normal file
View File

@@ -0,0 +1,31 @@
%Import QtWidgets/QtWidgetsmod.sip
%If (Qt_5_0_0 -)
namespace ads
{
class CPushButton : QPushButton
{
%TypeHeaderCode
#include <PushButton.h>
%End
public:
enum Orientation {
Horizontal,
VerticalTopToBottom,
VerticalBottomToTop
};
virtual QSize sizeHint() const;
ads::CPushButton::Orientation buttonOrientation() const;
void setButtonOrientation(ads::CPushButton::Orientation orientation);
};
};
%End

36
sip/ResizeHandle.sip Normal file
View File

@@ -0,0 +1,36 @@
%Import QtWidgets/QtWidgetsmod.sip
%If (Qt_5_0_0 -)
namespace ads
{
class CResizeHandle : QFrame
{
%TypeHeaderCode
#include <ResizeHandle.h>
%End
protected:
void mouseMoveEvent(QMouseEvent *);
void mousePressEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
public:
CResizeHandle(Qt::Edge HandlePosition, QWidget* parent /TransferThis/);
virtual ~CResizeHandle();
void setHandlePosition(Qt::Edge HandlePosition);
Qt::Edge handlePostion() const;
Qt::Orientation orientation() const;
QSize sizeHint() const;
bool isResizing() const;
void setMinResizeSize(int MinSize);
void setMaxResizeSize(int MaxSize);
void setOpaqueResize(bool opaque = true);
bool opaqueResize() const;
};
};
%End

View File

@@ -1,8 +1,13 @@
%Module(name=PyQtAds, call_super_init=True, keyword_arguments="Optional", use_limited_api=True)
%HideNamespace(name=ads)
%Import QtCore/QtCoremod.sip
%DefaultSupertype sip.simplewrapper
%Include ads_globals.sip
%Include AutoHideDockContainer.sip
%Include AutoHideSideBar.sip
%Include AutoHideTab.sip
%Include DockWidget.sip
%Include DockAreaTabBar.sip
%Include DockAreaTitleBar_p.sip
@@ -20,6 +25,8 @@
%Include FloatingDockContainer.sip
%Include FloatingDragPreview.sip
%Include IconProvider.sip
%Include PushButton.sip
%Include ResizeHandle.sip
%If (WS_X11)
%Include linux/FloatingWidgetTitleBar.sip
%End

View File

@@ -50,19 +50,30 @@ namespace ads
TopDockWidgetArea,
BottomDockWidgetArea,
CenterDockWidgetArea,
LeftAutoHideArea,
RightAutoHideArea,
TopAutoHideArea,
BottomAutoHideArea,
InvalidDockWidgetArea,
OuterDockAreas,
AutoHideDockAreas,
AllDockAreas
};
typedef QFlags<ads::DockWidgetArea> DockWidgetAreas;
enum eTabIndex
{
TabDefaultInsertIndex,
TabInvalidIndex
};
enum TitleBarButton
{
TitleBarButtonTabsMenu,
TitleBarButtonUndock,
TitleBarButtonClose
TitleBarButtonClose,
TitleBarButtonAutoHide
};
enum eDragState
@@ -76,10 +87,10 @@ namespace ads
enum eIcon
{
TabCloseIcon,
AutoHideIcon,
DockAreaMenuIcon,
DockAreaUndockIcon,
DockAreaCloseIcon,
IconCount,
};
@@ -89,6 +100,15 @@ namespace ads
BitwiseOr
};
enum SideBarLocation
{
SideBarTop,
SideBarLeft,
SideBarRight,
SideBarBottom,
SideBarNone
};
namespace internal
{
void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To);
@@ -106,6 +126,9 @@ namespace ads
int insertOffset() const;
};
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"/;
%MethodCode
@@ -131,6 +154,7 @@ namespace ads
};
void repolishStyle(QWidget* w, ads::internal::eRepolishChildOptions Options = ads::internal::RepolishIgnoreChildren);
QRect globalGeometry(QWidget* w);
};
};

View File

@@ -117,6 +117,7 @@ struct AutoHideDockContainerPrivate
CResizeHandle* ResizeHandle = nullptr;
QSize Size; // creates invalid size
QPointer<CAutoHideTab> SideTab;
QSize SizeCache;
/**
* Private data constructor
@@ -215,6 +216,7 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarL
bool OpaqueResize = CDockManager::testConfigFlag(CDockManager::OpaqueSplitterResize);
d->ResizeHandle->setOpaqueResize(OpaqueResize);
d->Size = d->DockArea->size();
d->SizeCache = DockWidget->size();
addDockWidget(DockWidget);
parent->registerAutoHideWidget(this);
@@ -237,7 +239,6 @@ void CAutoHideDockContainer::updateSize()
}
auto rect = dockContainerParent->contentRect();
switch (sideBarLocation())
{
case SideBarLocation::SideBarTop:
@@ -271,6 +272,15 @@ void CAutoHideDockContainer::updateSize()
default:
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)
{
@@ -303,7 +313,7 @@ CAutoHideSideBar* CAutoHideDockContainer::sideBar() const
else
{
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);
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,56 @@ bool CAutoHideDockContainer::event(QEvent* event)
return Super::event(event);
}
//============================================================================
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

@@ -91,9 +91,9 @@ public:
virtual ~CAutoHideDockContainer();
/**
* Get's the side tab bar
* Gets the side tab bar
*/
CAutoHideSideBar* sideBar() const;
CAutoHideSideBar* autoHideSideBar() const;
/**
* Returns the side tab
@@ -101,10 +101,15 @@ public:
CAutoHideTab* autoHideTab() const;
/**
* Get's the dock widget in this dock container
* Gets the dock widget in this dock container
*/
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
*/
@@ -162,10 +167,34 @@ public:
/**
* 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.
*/
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

View File

@@ -127,27 +127,6 @@ void AutoHideSideBarPrivate::handleViewportEvent(QEvent* e)
}
break;
case QEvent::Resize:
if (_this->tabCount())
{
auto ev = static_cast<QResizeEvent*>(e);
auto Tab = _this->tabAt(0);
int Size = isHorizontal() ? ev->size().height() : ev->size().width();
int TabSize = isHorizontal() ? Tab->size().height() : Tab->size().width();
// If the size of the side bar is less than the size of the first tab
// then there are no visible tabs in this side bar. This check will
// fail if someone will force a very big border via CSS!!
if (Size < TabSize)
{
_this->hide();
}
}
else
{
_this->hide();
}
break;
default:
break;
}
@@ -217,6 +196,7 @@ void CAutoHideSideBar::insertTab(int Index, CAutoHideTab* SideTab)
{
SideTab->setSideBar(this);
SideTab->installEventFilter(this);
// Default insertion is append
if (Index < 0)
{
d->TabsLayout->insertWidget(d->TabsLayout->count() - 1, SideTab);
@@ -254,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();
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)
@@ -269,7 +262,7 @@ void CAutoHideSideBar::addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget)
AutoHideWidget->setParent(d->ContainerWidget);
AutoHideWidget->setSideBarLocation(d->SideTabArea);
d->ContainerWidget->registerAutoHideWidget(AutoHideWidget);
insertTab(-1, AutoHideWidget->autoHideTab());
insertTab(TabIndex, AutoHideWidget->autoHideTab());
}
@@ -288,20 +281,33 @@ void CAutoHideSideBar::removeTab(CAutoHideTab* SideTab)
//============================================================================
bool CAutoHideSideBar::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() != QEvent::ShowToParent)
auto Tab = qobject_cast<CAutoHideTab*>(watched);
if (!Tab)
{
return false;
}
// As soon as on tab is shown, we need to show the side tab bar
auto Tab = qobject_cast<CAutoHideTab*>(watched);
if (Tab)
switch (event->type())
{
show();
case QEvent::ShowToParent:
show();
break;
case QEvent::HideToParent:
if (!hasVisibleTabs())
{
hide();
}
break;
default:
break;
}
return false;
}
//============================================================================
Qt::Orientation CAutoHideSideBar::orientation() const
{
@@ -310,19 +316,67 @@ 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());
}
//============================================================================
int CAutoHideSideBar::tabCount() const
int CAutoHideSideBar::count() const
{
return d->TabsLayout->count() - 1;
}
//============================================================================
int CAutoHideSideBar::visibleTabCount() const
{
int VisibleTabCount = 0;
auto ParentWidget = parentWidget();
for (auto i = 0; i < count(); i++)
{
if (tab(i)->isVisibleTo(ParentWidget))
{
VisibleTabCount++;
}
}
return VisibleTabCount;
}
//============================================================================
bool CAutoHideSideBar::hasVisibleTabs() const
{
auto ParentWidget = parentWidget();
for (auto i = 0; i < count(); i++)
{
if (tab(i)->isVisibleTo(ParentWidget))
{
return true;
}
}
return false;
}
//============================================================================
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
{
@@ -333,18 +387,18 @@ SideBarLocation CAutoHideSideBar::sideBarLocation() const
//============================================================================
void CAutoHideSideBar::saveState(QXmlStreamWriter& s) const
{
if (!tabCount())
if (!count())
{
return;
}
s.writeStartElement("SideBar");
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)
{
continue;
@@ -392,5 +446,56 @@ CDockContainerWidget* CAutoHideSideBar::dockContainer() const
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

View File

@@ -117,7 +117,7 @@ public:
* If the AutoHideWidget is in another sidebar, then it will be removed
* from this sidebar.
*/
void addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget);
void addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget, int Index = TabDefaultInsertIndex);
/**
* Returns orientation of side tab.
@@ -125,14 +125,45 @@ public:
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
*/
int tabCount() const;
int count() const;
/**
* Returns the number of visible tabs to its parent widget.
*/
int visibleTabCount() const;
/**
* Returns true, if the sidebar contains visible tabs to its parent widget.
* The function returns as soon as it finds the first visible tab.
* That means, if you just want to find out if there are visible tabs
* then this function is quicker than visibleTabCount()
*/
bool hasVisibleTabs() const;
/**
* Getter for side tab bar area property
@@ -142,7 +173,7 @@ public:
/**
* Overrides the minimumSizeHint() function of QScrollArea
* The minimumSizeHint() is bigger than the sizeHint () for the scroll
* area because even if the scrollbars are invisible, the required speace
* area because even if the scrollbars are invisible, the required space
* is reserved in the minimumSizeHint(). This override simply returns
* sizeHint();
*/

View File

@@ -32,15 +32,20 @@
#include <QBoxLayout>
#include <QApplication>
#include <QElapsedTimer>
#include <QMenu>
#include "AutoHideDockContainer.h"
#include "AutoHideSideBar.h"
#include "DockAreaWidget.h"
#include "DockManager.h"
#include "DockWidget.h"
#include "FloatingDragPreview.h"
#include "DockOverlay.h"
namespace ads
{
static const char* const LocationProperty = "Location";
/**
* Private data class of CDockWidgetTab class (pimpl)
*/
@@ -51,6 +56,12 @@ struct AutoHideTabPrivate
CAutoHideSideBar* SideBar = nullptr;
Qt::Orientation Orientation{Qt::Vertical};
QElapsedTimer TimeSinceHoverMousePress;
bool MousePressed = false;
eDragState DragState = DraggingInactive;
QPoint GlobalDragStartMousePosition;
QPoint DragStartMousePosition;
IFloatingWidget* FloatingWidget = nullptr;
Qt::Orientation DragStartOrientation;
/**
* Private data constructor
@@ -82,6 +93,55 @@ struct AutoHideTabPrivate
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("Location", 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
@@ -110,6 +170,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)
{
@@ -250,32 +357,205 @@ bool CAutoHideTab::event(QEvent* event)
d->forwardEventToDockContainer(event);
break;
case QEvent::MouseButtonPress:
// If AutoHideShowOnMouseOver is active, then the showing is triggered
// by a MousePressEvent sent to this tab. To prevent accidental hiding
// of the tab by a mouse click, we wait at least 500 ms before we accept
// the mouse click
if (!event->spontaneous())
{
d->TimeSinceHoverMousePress.restart();
d->forwardEventToDockContainer(event);
}
else if (d->TimeSinceHoverMousePress.hasExpired(500))
{
d->forwardEventToDockContainer(event);
}
break;
default:
break;
}
return Super::event(event);
}
//============================================================================
bool CAutoHideTab::iconOnly() const
{
return CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideSideBarsIconOnly) && !icon().isNull();
}
//============================================================================
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(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::requestCloseDockWidget()
{
d->DockWidget->requestCloseDockWidget();
}
//============================================================================
int CAutoHideTab::tabIndex() const
{
if (!d->SideBar)
{
return -1;
}
return d->SideBar->indexOfTab(*this);
}
}

View File

@@ -65,11 +65,17 @@ private:
friend class CDockContainerWidget;
friend DockContainerWidgetPrivate;
private Q_SLOTS:
void onAutoHideToActionClicked();
protected:
void setSideBar(CAutoHideSideBar *SideTabBar);
void removeFromSideBar();
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;
public:
using Super = CPushButton;
@@ -133,6 +139,27 @@ public:
* not in a side bar
*/
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
}
// namespace ads

View File

@@ -1,6 +1,11 @@
cmake_minimum_required(VERSION 3.5)
project(QtAdvancedDockingSystem LANGUAGES CXX VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
if (${QT_VERSION_MAJOR})
message(STATUS "Forced to use Qt version ${QT_VERSION_MAJOR}")
find_package(QT NAMES Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
else()
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
endif()
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Widgets REQUIRED)
if (UNIX AND NOT APPLE)
include_directories(${Qt${QT_VERSION_MAJOR}Gui_PRIVATE_INCLUDE_DIRS})
@@ -64,50 +69,58 @@ if (UNIX AND NOT APPLE)
set(ads_SRCS linux/FloatingWidgetTitleBar.cpp ${ads_SRCS})
set(ads_HEADERS linux/FloatingWidgetTitleBar.h ${ads_HEADERS})
endif()
set(library_name "qt${QT_VERSION_MAJOR}advanceddocking")
if(BUILD_STATIC)
add_library(qtadvanceddocking STATIC ${ads_SRCS} ${ads_HEADERS})
target_compile_definitions(qtadvanceddocking PUBLIC ADS_STATIC)
add_library(${library_name} STATIC ${ads_SRCS} ${ads_HEADERS})
target_compile_definitions( ${library_name} PUBLIC ADS_STATIC)
else()
add_library(qtadvanceddocking SHARED ${ads_SRCS} ${ads_HEADERS})
target_compile_definitions(qtadvanceddocking PRIVATE ADS_SHARED_EXPORT)
add_library( ${library_name} SHARED ${ads_SRCS} ${ads_HEADERS})
target_compile_definitions( ${library_name} PRIVATE ADS_SHARED_EXPORT)
endif()
add_library(ads::qtadvanceddocking ALIAS qtadvanceddocking)
add_library(ads::${library_name} ALIAS ${library_name})
target_link_libraries(qtadvanceddocking PUBLIC Qt${QT_VERSION_MAJOR}::Core
target_link_libraries(${library_name} PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
if (UNIX AND NOT APPLE)
target_link_libraries(qtadvanceddocking PUBLIC xcb)
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()
set_target_properties(qtadvanceddocking PROPERTIES
set_target_properties(${library_name} PROPERTIES
AUTOMOC ON
AUTORCC ON
CXX_EXTENSIONS OFF
VERSION ${VERSION_SHORT}
EXPORT_NAME "qtadvanceddocking"
EXPORT_NAME ${library_name}
DEBUG_POSTFIX "d"
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"
)
if(QT_VERSION_MAJOR STREQUAL "5")
set_target_properties(qtadvanceddocking PROPERTIES
set_target_properties(${library_name} PROPERTIES
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON)
elseif(QT_VERSION_MAJOR STREQUAL "6")
set_target_properties(qtadvanceddocking PROPERTIES
set_target_properties(${library_name} PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON)
endif()
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"qtadvanceddockingConfigVersion.cmake"
"${library_name}ConfigVersion.cmake"
VERSION ${VERSION_SHORT}
COMPATIBILITY SameMajorVersion
)
install(FILES ${ads_HEADERS}
DESTINATION include
DESTINATION include/${library_name}
COMPONENT headers
)
install(FILES
@@ -116,24 +129,27 @@ install(FILES
DESTINATION license/ads
COMPONENT license
)
install(TARGETS qtadvanceddocking
install(TARGETS ${library_name}
EXPORT adsTargets
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
INCLUDES DESTINATION include
INCLUDES DESTINATION include/${library_name}
)
install(EXPORT adsTargets
FILE adsTargets.cmake
NAMESPACE ads::
DESTINATION lib/cmake/qtadvanceddocking
DESTINATION lib/cmake/${library_name}
)
install(FILES qtadvanceddockingConfig.cmake "${CMAKE_CURRENT_BINARY_DIR}/qtadvanceddockingConfigVersion.cmake"
DESTINATION lib/cmake/qtadvanceddocking
install(FILES qtadvanceddockingConfig.cmake RENAME ${library_name}Config.cmake
DESTINATION lib/cmake/${library_name}
)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${library_name}ConfigVersion.cmake"
DESTINATION lib/cmake/${library_name}
)
target_include_directories(qtadvanceddocking PUBLIC
target_include_directories(${library_name} PUBLIC
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
)

View File

@@ -36,6 +36,7 @@
#include <QBoxLayout>
#include <QApplication>
#include <QtGlobal>
#include <QTimer>
#include "FloatingDockContainer.h"
#include "DockAreaWidget.h"
@@ -107,7 +108,12 @@ void DockAreaTabBarPrivate::updateTabs()
{
TabWidget->show();
TabWidget->setActiveTab(true);
_this->ensureWidgetVisible(TabWidget);
// Sometimes the synchronous calculation of the rectangular area fails
// Therefore we use QTimer::singleShot here to execute the call
// within the event loop - see #520
QTimer::singleShot(0, [&, TabWidget]{
_this->ensureWidgetVisible(TabWidget);
});
}
else
{
@@ -294,7 +300,7 @@ int CDockAreaTabBar::currentIndex() const
//===========================================================================
CDockWidgetTab* CDockAreaTabBar::currentTab() const
{
if (d->CurrentIndex < 0)
if (d->CurrentIndex < 0 || d->CurrentIndex >= d->TabsLayout->count())
{
return nullptr;
}
@@ -498,6 +504,46 @@ QSize CDockAreaTabBar::sizeHint() const
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;
}
}
} // namespace ads

View File

@@ -113,6 +113,19 @@ public:
*/
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
*/
@@ -128,7 +141,7 @@ public:
/**
* Overrides the minimumSizeHint() function of QScrollArea
* The minimumSizeHint() is bigger than the sizeHint () for the scroll
* area because even if the scrollbars are invisible, the required speace
* area because even if the scrollbars are invisible, the required space
* is reserved in the minimumSizeHint(). This override simply returns
* sizeHint();
*/

View File

@@ -68,14 +68,15 @@ static const char* const LocationProperty = "Location";
struct DockAreaTitleBarPrivate
{
CDockAreaTitleBar* _this;
QPointer<tTitleBarButton> TabsMenuButton;
QPointer<tTitleBarButton> AutoHideButton;
QPointer<tTitleBarButton> UndockButton;
QPointer<tTitleBarButton> CloseButton;
QPointer<CTitleBarButton> TabsMenuButton;
QPointer<CTitleBarButton> AutoHideButton;
QPointer<CTitleBarButton> UndockButton;
QPointer<CTitleBarButton> CloseButton;
QPointer<CTitleBarButton> MinimizeButton;
QBoxLayout* Layout;
CDockAreaWidget* DockArea;
CDockAreaTabBar* TabBar;
CElidingLabel* AutoHideTitleLabel;
CElidingLabel* AutoHideTitleLabel = nullptr;
bool MenuOutdated = true;
QMenu* TabsMenu;
QList<tTitleBarButton*> DockWidgetActionsButtons;
@@ -218,6 +219,17 @@ void DockAreaTitleBarPrivate::createButtons()
Layout->addWidget(AutoHideButton, 0);
_this->connect(AutoHideButton, SIGNAL(clicked()), SLOT(onAutoHideButtonClicked()));
// Minimize button
MinimizeButton = new CTitleBarButton(testAutoHideConfigFlag(CDockManager::AutoHideHasMinimizeButton));
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
CloseButton = new CTitleBarButton(testConfigFlag(CDockManager::DockAreaHasCloseButton));
CloseButton->setObjectName("dockAreaCloseButton");
@@ -236,7 +248,10 @@ void DockAreaTitleBarPrivate::createAutoHideTitleLabel()
{
AutoHideTitleLabel = new CElidingLabel("");
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 +339,8 @@ CDockAreaTitleBar::CDockAreaTitleBar(CDockAreaWidget* parent) :
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
d->createTabBar();
d->createAutoHideTitleLabel();
d->AutoHideTitleLabel->setVisible(false); // Default hidden
d->Layout->addWidget(new CSpacerWidget(this));
d->createButtons();
d->createAutoHideTitleLabel();
setFocusPolicy(Qt::NoFocus);
}
@@ -415,7 +428,12 @@ void CDockAreaTitleBar::onTabsMenuAboutToShow()
void CDockAreaTitleBar::onCloseButtonClicked()
{
ADS_PRINT("CDockAreaTitleBar::onCloseButtonClicked");
if (d->testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideCloseButtonCollapsesDock) &&
d->DockArea->autoHideDockContainer())
{
d->DockArea->autoHideDockContainer()->collapseView(true);
}
else if (d->testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
{
d->TabBar->closeTab(d->TabBar->currentIndex());
}
@@ -426,6 +444,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()
{
@@ -534,7 +570,7 @@ void CDockAreaTitleBar::onAutoHideToActionClicked()
//============================================================================
QAbstractButton* CDockAreaTitleBar::button(TitleBarButton which) const
CTitleBarButton* CDockAreaTitleBar::button(TitleBarButton which) const
{
switch (which)
{
@@ -542,6 +578,7 @@ QAbstractButton* CDockAreaTitleBar::button(TitleBarButton which) const
case TitleBarButtonUndock: return d->UndockButton;
case TitleBarButtonClose: return d->CloseButton;
case TitleBarButtonAutoHide: return d->AutoHideButton;
case TitleBarButtonMinimize: return d->MinimizeButton;
default:
return nullptr;
}
@@ -672,6 +709,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)
{
@@ -708,7 +767,17 @@ void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev)
}
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));
if (!isAutoHide && !isTopLevelArea)
{
@@ -755,7 +824,8 @@ QString CDockAreaTitleBar::titleBarButtonToolTip(TitleBarButton Button) const
case TitleBarButtonClose:
if (d->DockArea->isAutoHide())
{
return tr("Close");
bool Minimize = CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideCloseButtonCollapsesDock);
return Minimize ? tr("Minimize") : tr("Close");
}
if (CDockManager::testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
@@ -775,10 +845,20 @@ QString CDockAreaTitleBar::titleBarButtonToolTip(TitleBarButton Button) const
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);
}
//============================================================================
CTitleBarButton::CTitleBarButton(bool showInTitleBar, QWidget* parent)
: tTitleBarButton(parent),
Visible(visible),
ShowInTitleBar(showInTitleBar),
HideWhenDisabled(CDockManager::testConfigFlag(CDockManager::DockAreaHideDisabledButtons))
{
setFocusPolicy(Qt::NoFocus);
@@ -787,8 +867,8 @@ CTitleBarButton::CTitleBarButton(bool visible, QWidget* parent)
//============================================================================
void CTitleBarButton::setVisible(bool visible)
{
// 'visible' can stay 'true' if and only if this button is configured to generaly visible:
visible = visible && this->Visible;
// 'visible' can stay 'true' if and only if this button is configured to generally 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:
if (visible && HideWhenDisabled)
@@ -799,6 +879,18 @@ void CTitleBarButton::setVisible(bool visible)
Super::setVisible(visible);
}
//============================================================================
void CTitleBarButton::setShowInTitleBar(bool Show)
{
this->ShowInTitleBar = Show;
if (!Show)
{
setVisible(false);
}
}
//============================================================================
bool CTitleBarButton::event(QEvent *ev)
{
@@ -819,6 +911,7 @@ CSpacerWidget::CSpacerWidget(QWidget* Parent /*= 0*/) : Super(Parent)
setStyleSheet("border: none; background: none;");
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@@ -30,6 +30,7 @@
//============================================================================
// INCLUDES
//============================================================================
#include <QToolButton>
#include <QFrame>
#include "ads_globals.h"
@@ -43,6 +44,44 @@ class CDockAreaWidget;
struct DockAreaTitleBarPrivate;
class CElidingLabel;
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;
public:
using Super = tTitleBarButton;
CTitleBarButton(bool ShowInTitleBar = true, 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);
protected:
/**
* Handle EnabledChanged signal to set button invisible if the configured
*/
bool event(QEvent *ev) override;
};
/**
* Title bar of a dock area.
* The title bar contains a tabbar with all tabs for a dock widget group and
@@ -58,6 +97,8 @@ private:
private Q_SLOTS:
void onTabsMenuAboutToShow();
void onCloseButtonClicked();
void onAutoHideCloseActionTriggered();
void minimizeAutoHideContainer();
void onUndockButtonClicked();
void onTabsMenuActionTriggered(QAction* Action);
void onCurrentTabChanged(int Index);
@@ -121,7 +162,7 @@ public:
/**
* 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
@@ -163,6 +204,17 @@ public:
*/
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);
Q_SIGNALS:
/**
* This signal is emitted if a tab in the tab bar is clicked by the user

View File

@@ -31,43 +31,12 @@
// INCLUDES
//============================================================================
#include <QFrame>
#include <QToolButton>
#include "ads_globals.h"
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;
};
/**

View File

@@ -140,6 +140,7 @@ public:
{
LayoutItem->widget()->setParent(nullptr);
}
delete LayoutItem;
m_CurrentWidget = nullptr;
m_CurrentIndex = -1;
}
@@ -316,12 +317,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();
/**
* Udpates the enable state of the close and detach button
* Updates the enable state of the close and detach button
*/
void updateTitleBarButtonVisibility(bool isTopLevel);
@@ -389,20 +390,29 @@ void DockAreaWidgetPrivate::updateTitleBarButtonVisibility(bool IsTopLevel)
return;
}
if (IsTopLevel)
bool IsAutoHide = _this->isAutoHide();
if (IsAutoHide)
{
bool ShowCloseButton = CDockManager::autoHideConfigFlags().testFlag(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(TitleBarButtonAutoHide)->setVisible(!container->isFloating());
// Undock and tabs should never show when auto hidden
TitleBar->button(TitleBarButtonUndock)->setVisible(!container->isFloating() && !_this->isAutoHide());
TitleBar->button(TitleBarButtonTabsMenu)->setVisible(!_this->isAutoHide());
TitleBar->button(TitleBarButtonUndock)->setVisible(!container->isFloating());
TitleBar->button(TitleBarButtonTabsMenu)->setVisible(true);
}
else
{
TitleBar->button(TitleBarButtonClose)->setVisible(true);
TitleBar->button(TitleBarButtonAutoHide)->setVisible(true);
TitleBar->button(TitleBarButtonUndock)->setVisible(!_this->isAutoHide());
TitleBar->button(TitleBarButtonTabsMenu)->setVisible(!_this->isAutoHide());
TitleBar->button(TitleBarButtonUndock)->setVisible(true);
TitleBar->button(TitleBarButtonTabsMenu)->setVisible(true);
}
}
@@ -466,6 +476,7 @@ void CDockAreaWidget::setAutoHideDockContainer(CAutoHideDockContainer* AutoHideD
d->AutoHideDockContainer = AutoHideDockContainer;
updateAutoHideButtonCheckState();
updateTitleBarButtonsToolTips();
d->TitleBar->button(TitleBarButtonAutoHide)->setShowInTitleBar(true);
}
@@ -625,15 +636,7 @@ void CDockAreaWidget::hideAreaWithNoVisibleContent()
void CDockAreaWidget::onTabCloseRequested(int Index)
{
ADS_PRINT("CDockAreaWidget::onTabCloseRequested " << Index);
auto* DockWidget = dockWidget(Index);
if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) || DockWidget->features().testFlag(CDockWidget::CustomCloseHandling))
{
DockWidget->closeDockWidgetInternal();
}
else
{
DockWidget->toggleView(false);
}
dockWidget(Index)->requestCloseDockWidget();
}
@@ -853,9 +856,7 @@ void CDockAreaWidget::updateTitleBarVisibility()
if (isAutoHideFeatureEnabled())
{
auto tabBar = d->TitleBar->tabBar();
tabBar->setVisible(!IsAutoHide); // Never show tab bar when auto hidden
d->TitleBar->autoHideTitleLabel()->setVisible(IsAutoHide); // Always show when auto hidden, never otherwise
d->TitleBar->showAutoHideControls(IsAutoHide);
updateTitleBarButtonVisibility(Container->topLevelDockArea() == this);
}
}
@@ -1289,17 +1290,17 @@ SideBarLocation CDockAreaWidget::calculateSideTabBarArea() const
case BorderHorizontalLeft: SideTab = SideBarLocation::SideBarLeft; 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 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 BorderTopRight : SideTab = HorizontalOrientation ? SideBarLocation::SideBarTop : SideBarLocation::SideBarRight; break;
case BorderBottomLeft : SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarLeft; break;
case BorderBottomRight : SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarRight; break;
// 5 Ists touching only one border
// 5. It's touching only one border
case BorderLeft: SideTab = SideBarLocation::SideBarLeft; break;
case BorderRight: SideTab = SideBarLocation::SideBarRight; break;
case BorderTop: SideTab = SideBarLocation::SideBarTop; break;
@@ -1311,7 +1312,7 @@ SideBarLocation CDockAreaWidget::calculateSideTabBarArea() const
//============================================================================
void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location)
void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location, int TabIndex)
{
if (!isAutoHideFeatureEnabled())
{
@@ -1322,11 +1323,18 @@ void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location)
{
if (isAutoHide())
{
autoHideDockContainer()->moveContentsToParent();
d->AutoHideDockContainer->moveContentsToParent();
}
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;
for (const auto DockWidget : openedDockWidgets())
{
@@ -1340,7 +1348,7 @@ void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location)
continue;
}
dockContainer()->createAndSetupAutoHideContainer(area, DockWidget);
dockContainer()->createAndSetupAutoHideContainer(area, DockWidget, TabIndex++);
}
}
@@ -1441,6 +1449,13 @@ bool CDockAreaWidget::isTopLevelArea() const
}
//============================================================================
void CDockAreaWidget::setFloating()
{
d->TitleBar->setAreaFloating();
}
#ifdef Q_OS_WIN
//============================================================================
bool CDockAreaWidget::event(QEvent *e)

View File

@@ -221,7 +221,6 @@ public:
*/
bool isAutoHide() const;
/**
* Sets the current auto hide dock container
*/
@@ -401,7 +400,7 @@ public Q_SLOTS:
* If the dock area is switched to auto hide mode, then all dock widgets
* that are pinable will be added to the sidebar
*/
void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone);
void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone, int TabIndex = -1);
/**
* Switches the dock area to auto hide mode or vice versa depending on its
@@ -414,6 +413,12 @@ public Q_SLOTS:
*/
void closeOtherAreas();
/**
* Moves the dock area into its own floating widget if the area
* DockWidgetFloatable flag is true
*/
void setFloating();
Q_SIGNALS:
/**
* This signal is emitted when user clicks on a tab at an index.

View File

@@ -145,7 +145,7 @@ public:
QList<CAutoHideDockContainer*> AutoHideWidgets;
QMap<SideBarLocation, CAutoHideSideBar*> SideTabBarWidgets;
QGridLayout* Layout = nullptr;
QSplitter* RootSplitter = nullptr;
CDockSplitter* RootSplitter = nullptr;
bool isFloating = false;
CDockAreaWidget* LastAddedAreaCache[5];
int VisibleDockAreaCount = -1;
@@ -181,17 +181,29 @@ public:
*/
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
*/
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
* 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
@@ -202,13 +214,13 @@ public:
/**
* Creates a new tab for a widget dropped into the center of a section
*/
void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget,
CDockAreaWidget* TargetArea);
void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea, int TabIndex = 0);
/**
* 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
* the parsed widget was an empty splitter
* \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 Testing);
@@ -454,7 +466,7 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
CDockContainerWidget* FloatingDockContainer = FloatingWidget->dockContainer();
auto NewDockAreas = FloatingDockContainer->findChildren<CDockAreaWidget*>(
QString(), Qt::FindChildrenRecursively);
QSplitter* Splitter = RootSplitter;
auto Splitter = RootSplitter;
if (DockAreas.count() <= 1)
{
@@ -462,7 +474,7 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
}
else if (Splitter->orientation() != InsertParam.orientation())
{
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
auto NewSplitter = newSplitter(InsertParam.orientation());
QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
NewSplitter->addWidget(Splitter);
updateSplitterHandles(NewSplitter);
@@ -505,14 +517,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(
CFloatingDockContainer* FloatingWidget, CDockAreaWidget* TargetArea)
CFloatingDockContainer* FloatingWidget, CDockAreaWidget* TargetArea, int TabIndex)
{
CDockContainerWidget* FloatingContainer = FloatingWidget->dockContainer();
auto NewDockWidgets = FloatingContainer->dockWidgets();
auto TopLevelDockArea = FloatingContainer->topLevelDockArea();
int NewCurrentIndex = -1;
TabIndex = qMax(0, TabIndex);
// 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
@@ -525,7 +556,7 @@ void DockContainerWidgetPrivate::dropIntoCenterOfSection(
for (int i = 0; i < NewDockWidgets.count(); ++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
// simply pick the first visible open dock widget and make it
// the current one.
@@ -534,7 +565,7 @@ void DockContainerWidgetPrivate::dropIntoCenterOfSection(
NewCurrentIndex = i;
}
}
TargetArea->setCurrentIndex(NewCurrentIndex);
TargetArea->setCurrentIndex(NewCurrentIndex + TabIndex);
TargetArea->updateTitleBarVisibility();
return;
}
@@ -542,13 +573,13 @@ void DockContainerWidgetPrivate::dropIntoCenterOfSection(
//============================================================================
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
// widget will become tabs of the drop area
if (CenterDockWidgetArea == area)
{
dropIntoCenterOfSection(FloatingWidget, TargetArea);
dropIntoCenterOfSection(FloatingWidget, TargetArea, TabIndex);
return;
}
@@ -638,11 +669,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 DroppedArea = qobject_cast<CDockAreaWidget*>(Widget);
TabIndex = qMax(0, TabIndex);
if (DroppedDockWidget)
{
CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget();
@@ -655,7 +688,7 @@ void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockA
{
OldDockArea->removeDockWidget(DroppedDockWidget);
}
TargetArea->insertDockWidget(0, DroppedDockWidget, true);
TargetArea->insertDockWidget(TabIndex, DroppedDockWidget, true);
}
else
{
@@ -664,9 +697,9 @@ void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockA
for (int i = 0; i < NewDockWidgets.count(); ++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->deleteLater();
}
@@ -677,13 +710,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
// widget will become tabs of the drop area
if (CenterDockWidgetArea == area)
{
moveIntoCenterOfSection(Widget, TargetArea);
moveIntoCenterOfSection(Widget, TargetArea, TabIndex);
return;
}
@@ -738,6 +772,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 )
{
@@ -908,7 +984,7 @@ void DockContainerWidgetPrivate::saveAutoHideWidgetsState(QXmlStreamWriter& s)
{
for (const auto sideTabBar : SideTabBarWidgets.values())
{
if (!sideTabBar->tabCount())
if (!sideTabBar->count())
{
continue;
}
@@ -1101,12 +1177,12 @@ bool DockContainerWidgetPrivate::restoreSideBar(CDockingStateReader& s,
continue;
}
auto SideBar = _this->sideTabBar(Area);
auto SideBar = _this->autoHideSideBar(Area);
CAutoHideDockContainer* AutoHideContainer;
if (DockWidget->isAutoHide())
{
AutoHideContainer = DockWidget->autoHideDockContainer();
if (AutoHideContainer->sideBar() != SideBar)
if (AutoHideContainer->autoHideSideBar() != SideBar)
{
SideBar->addAutoHideWidget(AutoHideContainer);
}
@@ -1193,7 +1269,7 @@ void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockW
}
else
{
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
auto NewSplitter = newSplitter(InsertParam.orientation());
if (InsertParam.append())
{
QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
@@ -1404,7 +1480,7 @@ CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockW
//============================================================================
CAutoHideDockContainer* CDockContainerWidget::createAndSetupAutoHideContainer(
SideBarLocation area, CDockWidget* DockWidget)
SideBarLocation area, CDockWidget* DockWidget, int TabIndex)
{
if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
{
@@ -1417,7 +1493,7 @@ CAutoHideDockContainer* CDockContainerWidget::createAndSetupAutoHideContainer(
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);
}
@@ -1528,7 +1604,7 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
}
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
// then we are finished
if (!ChildSplitter)
@@ -1629,11 +1705,12 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
ADS_PRINT("CDockContainerWidget::dropFloatingWidget");
CDockWidget* SingleDroppedDockWidget = FloatingWidget->topLevelDockWidget();
CDockWidget* SingleDockWidget = topLevelDockWidget();
CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
auto dropArea = InvalidDockWidgetArea;
auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
bool Dropped = false;
CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
// mouse is over dock area
if (DockArea)
{
auto dropOverlay = d->DockManager->dockAreaOverlay();
@@ -1648,28 +1725,33 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
if (dropArea != InvalidDockWidgetArea)
{
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;
}
}
// mouse is over container
if (InvalidDockWidgetArea == dropArea)
// mouse is over container or auto hide side bar
if (InvalidDockWidgetArea == dropArea && InvalidDockWidgetArea != ContainerDropArea)
{
dropArea = ContainerDropArea;
ADS_PRINT("Container Drop Content: " << dropArea);
if (dropArea != InvalidDockWidgetArea)
{
d->dropIntoContainer(FloatingWidget, dropArea);
Dropped = true;
}
if (internal::isSideBarArea(ContainerDropArea))
{
ADS_PRINT("Container Drop Content: " << ContainerDropArea);
d->dropIntoAutoHideSideBar(FloatingWidget, ContainerDropArea);
}
else
{
ADS_PRINT("Container Drop Content: " << ContainerDropArea);
d->dropIntoContainer(FloatingWidget, ContainerDropArea);
}
Dropped = true;
}
// Remove the auto hide widgets from the FloatingWidget and insert
// them into this widget
for (auto AutohideWidget : FloatingWidget->dockContainer()->autoHideWidgets())
{
auto SideBar = sideTabBar(AutohideWidget->sideBarLocation());
auto SideBar = autoHideSideBar(AutohideWidget->sideBarLocation());
SideBar->addAutoHideWidget(AutohideWidget);
}
@@ -1697,12 +1779,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();
if (TargetAreaWidget)
{
d->moveToNewSection(Widget, TargetAreaWidget, DropArea);
d->moveToNewSection(Widget, TargetAreaWidget, DropArea, TabIndex);
}
else if (internal::isSideBarArea(DropArea))
{
d->moveToAutoHideSideBar(Widget, DropArea, TabIndex);
}
else
{
@@ -1845,10 +1932,11 @@ bool CDockContainerWidget::restoreState(CDockingStateReader& s, bool Testing)
NewRootSplitter = d->newSplitter(Qt::Horizontal);
}
d->Layout->replaceWidget(d->RootSplitter, NewRootSplitter);
QSplitter* OldRoot = d->RootSplitter;
d->RootSplitter = qobject_cast<QSplitter*>(NewRootSplitter);
QLayoutItem* li = d->Layout->replaceWidget(d->RootSplitter, NewRootSplitter);
auto OldRoot = d->RootSplitter;
d->RootSplitter = qobject_cast<CDockSplitter*>(NewRootSplitter);
OldRoot->deleteLater();
delete li;
return true;
}
@@ -2051,7 +2139,7 @@ void CDockContainerWidget::closeOtherAreas(CDockAreaWidget* KeepOpenArea)
}
//============================================================================
CAutoHideSideBar* CDockContainerWidget::sideTabBar(SideBarLocation area) const
CAutoHideSideBar* CDockContainerWidget::autoHideSideBar(SideBarLocation area) const
{
return d->SideTabBarWidgets[area];
}
@@ -2065,7 +2153,21 @@ QRect CDockContainerWidget::contentRect() const
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

@@ -101,7 +101,7 @@ protected:
* Initializing inserts the tabs into the side tab widget and hides it
* Returns nullptr if you try and insert into an area where the configuration is not enabled
*/
CAutoHideDockContainer* createAndSetupAutoHideContainer(SideBarLocation area, CDockWidget* DockWidget);
CAutoHideDockContainer* createAndSetupAutoHideContainer(SideBarLocation area, CDockWidget* DockWidget, int TabIndex = -1);
/**
* Helper function for creation of the root splitter
@@ -125,12 +125,13 @@ protected:
* a nullptr, then the DropArea indicates the drop area in the given
* 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
*/
void addDockArea(CDockAreaWidget* DockAreaWidget, DockWidgetArea area = CenterDockWidgetArea);
void addDockArea(CDockAreaWidget* DockAreaWidget, DockWidgetArea area = ads::CenterDockWidgetArea);
/**
* Removes the given dock area from this container
@@ -322,7 +323,7 @@ public:
/**
* Returns the side tab widget for the given area
*/
CAutoHideSideBar* sideTabBar(SideBarLocation area) const;
CAutoHideSideBar* autoHideSideBar(SideBarLocation area) const;
/**

View File

@@ -27,7 +27,7 @@
#include "DockManager.h"
#include "DockAreaTitleBar.h"
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
#include "linux/FloatingWidgetTitleBar.h"
#endif
@@ -44,11 +44,12 @@ struct DockFocusControllerPrivate
QPointer<CDockWidget> FocusedDockWidget = nullptr;
QPointer<CDockAreaWidget> FocusedArea = nullptr;
QPointer<CDockWidget> OldFocusedDockWidget = nullptr;
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
QPointer<CFloatingDockContainer> FloatingWidget = nullptr;
#endif
CDockManager* DockManager;
bool ForceFocusChangedSignal = false;
bool TabPressed = false;
/**
* Private data constructor
@@ -84,7 +85,7 @@ static void updateDockAreaFocusStyle(CDockAreaWidget* DockArea, bool Focused)
//===========================================================================
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
static void updateFloatingWidgetFocusStyle(CFloatingDockContainer* FloatingWidget, bool Focused)
{
if (FloatingWidget->hasNativeTitleBar())
@@ -168,7 +169,7 @@ void DockFocusControllerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget)
}
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
// This code is required for styling the floating widget titlebar for linux
// depending on the current focus state
if (FloatingWidget != NewFloatingWidget)
@@ -267,7 +268,9 @@ void CDockFocusController::onApplicationFocusChanged(QWidget* focusedOld, QWidge
{
Q_UNUSED(focusedOld);
if (d->DockManager->isRestoringState())
// Ignore focus changes if we are restoring state, or if user clicked
// a tab which in turn caused the focus change
if (d->DockManager->isRestoringState() || d->TabPressed)
{
return;
}
@@ -285,7 +288,7 @@ void CDockFocusController::onApplicationFocusChanged(QWidget* focusedOld, QWidge
DockWidget = internal::findParent<CDockWidget*>(focusedNow);
}
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
if (!DockWidget)
{
return;
@@ -418,6 +421,12 @@ CDockWidget* CDockFocusController::focusedDockWidget() const
return d->FocusedDockWidget.data();
}
//==========================================================================
void CDockFocusController::setDockWidgetTabPressed(bool Value)
{
d->TabPressed = Value;
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@@ -80,6 +80,12 @@ public:
*/
void clearDockWidgetFocus(CDockWidget* dockWidget);
/**
* Notifies the dock focus controller, that a the mouse is pressed or
* released
*/
void setDockWidgetTabPressed(bool Value);
public Q_SLOTS:
/**
* Request a focus change to the given dock widget

View File

@@ -47,6 +47,7 @@
#include <QMenu>
#include <QApplication>
#include <QWindow>
#include <QWindowStateChangeEvent>
#include "FloatingDockContainer.h"
#include "DockOverlay.h"
@@ -59,7 +60,7 @@
#include "DockFocusController.h"
#include "DockSplitter.h"
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
#include "linux/FloatingWidgetTitleBar.h"
#endif
@@ -116,6 +117,11 @@ struct DockManagerPrivate
QVector<CFloatingDockContainer*> UninitializedFloatingWidgets;
CDockFocusController* FocusController = nullptr;
CDockWidget* CentralWidget = nullptr;
bool IsLeavingMinimized = false;
Qt::ToolButtonStyle ToolBarStyleDocked = Qt::ToolButtonIconOnly;
Qt::ToolButtonStyle ToolBarStyleFloating = Qt::ToolButtonTextUnderIcon;
QSize ToolBarIconSizeDocked = QSize(16, 16);
QSize ToolBarIconSizeFloating = QSize(24, 24);
/**
* Private data constructor
@@ -192,7 +198,7 @@ void DockManagerPrivate::loadStylesheet()
QString FileName = ":ads/stylesheets/";
FileName += CDockManager::testConfigFlag(CDockManager::FocusHighlighting)
? "focus_highlighting" : "default";
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
FileName += "_linux";
#endif
FileName += ".css";
@@ -510,9 +516,10 @@ CDockManager::CDockManager(QWidget *parent) :
d->FocusController = new CDockFocusController(this);
}
#ifdef Q_OS_LINUX
window()->installEventFilter(this);
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
connect(qApp, &QApplication::focusWindowChanged, [](QWindow* focusWindow)
{
// bring modal dialogs to foreground to ensure that they are in front of any
@@ -552,7 +559,7 @@ CDockManager::~CDockManager()
}
//============================================================================
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
bool CDockManager::eventFilter(QObject *obj, QEvent *e)
{
// Emulate Qt:Tool behaviour.
@@ -629,8 +636,39 @@ bool CDockManager::eventFilter(QObject *obj, QEvent *e)
}
return Super::eventFilter(obj, e);
}
#else
//============================================================================
bool CDockManager::eventFilter(QObject *obj, QEvent *e)
{
if (e->type() == QEvent::WindowStateChange)
{
QWindowStateChangeEvent* ev = static_cast<QWindowStateChangeEvent*>(e);
if (ev->oldState().testFlag(Qt::WindowMinimized))
{
d->IsLeavingMinimized = true;
QMetaObject::invokeMethod(this, "endLeavingMinimizedState", Qt::QueuedConnection);
}
}
return Super::eventFilter(obj, e);
}
#endif
//============================================================================
void CDockManager::endLeavingMinimizedState()
{
d->IsLeavingMinimized = false;
this->activateWindow();
}
//============================================================================
bool CDockManager::isLeavingMinimizedState() const
{
return d->IsLeavingMinimized;
}
//============================================================================
void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget)
{
@@ -1251,7 +1289,7 @@ void CDockManager::hideManagerAndFloatingWidgets()
d->HiddenFloatingWidgets.push_back( FloatingWidget );
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
// when CDockManager will be shown back
for ( auto dockWidget : VisibleWidgets )
@@ -1327,6 +1365,63 @@ QString CDockManager::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;
}
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@@ -55,6 +55,8 @@ class CIconProvider;
class CDockComponentsFactory;
class CDockFocusController;
class CAutoHideSideBar;
class CAutoHideTab;
struct AutoHideTabPrivate;
/**
* The central dock manager that maintains the complete docking system.
@@ -87,6 +89,14 @@ private:
friend class CDockAreaTitleBar;
friend class CAutoHideDockContainer;
friend CAutoHideSideBar;
friend CAutoHideTab;
friend AutoHideTabPrivate;
public Q_SLOTS:
/**
* Ends the isRestoringFromMinimizedState
*/
void endLeavingMinimizedState();
protected:
@@ -144,7 +154,7 @@ protected:
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
* flag is set.
*/
@@ -203,6 +213,7 @@ public:
//!< 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".
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
DefaultDockAreaButtons = DockAreaHasCloseButton
| DockAreaHasUndockButton
@@ -239,9 +250,15 @@ public:
AutoHideButtonCheckable = 0x08, //!< If the flag is set, the auto hide button will be checked and unchecked depending on the auto hide state. Mainly for styling purposes.
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
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
DefaultAutoHideConfig = AutoHideFeatureEnabled
| DockAreaHasAutoHideButton ///< the default configuration for left and right side bars
| DockAreaHasAutoHideButton
| AutoHideCloseButtonCollapsesDock
| AutoHideHasCloseButton
};
Q_DECLARE_FLAGS(AutoHideFlags, eAutoHideFlag)
@@ -528,7 +545,7 @@ public:
* The order defines how the actions are added to the view menu.
* The default insertion order is MenuAlphabeticallySorted to make it
* 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.
*/
void setViewMenuInsertionOrder(eViewMenuInsertionOrder Order);
@@ -539,6 +556,15 @@ public:
*/
bool isRestoringState() const;
/**
* This function returns true, if the DockManager window is restoring from
* minimized state.
* The DockManager is in this state starting from the QWindowStateChangeEvent
* that signals the state change from minimized to normal until
* endLeavingMinimizedState() function is called.
*/
bool isLeavingMinimizedState() const;
/**
* The distance the user needs to move the mouse with the left button
* hold down before a dock widget start floating
@@ -560,9 +586,7 @@ public:
widget->setFocus(Qt::OtherFocusReason);
}
#ifdef Q_OS_LINUX
bool eventFilter(QObject *obj, QEvent *e) override;
#endif
/**
* Returns the dock widget that has focus style in the ui or a nullptr if
@@ -606,6 +630,36 @@ public:
*/
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;
public Q_SLOTS:
/**
* Opens the perspective with the given name.

View File

@@ -38,11 +38,18 @@
#include "DockAreaWidget.h"
#include "DockAreaTitleBar.h"
#include "DockContainerWidget.h"
#include "AutoHideSideBar.h"
#include "DockManager.h"
#include "DockAreaTabBar.h"
#include <iostream>
namespace ads
{
static const int AutoHideAreaWidth = 32;
static const int AutoHideAreaMouseZone = 8;
static const int InvalidTabIndex = -2;
/**
* Private data class of CDockOverlay
@@ -57,11 +64,23 @@ struct DockOverlayPrivate
bool DropPreviewEnabled = true;
CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay;
QRect DropAreaRect;
int TabIndex = InvalidTabIndex;
/**
* Private data constructor
*/
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);
};
/**
@@ -139,7 +158,7 @@ struct DockOverlayCrossPrivate
*/
qreal dropIndicatiorWidth(QLabel* l) const
{
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
Q_UNUSED(l)
return 40;
#else
@@ -155,8 +174,20 @@ struct DockOverlayCrossPrivate
QLabel* l = new QLabel();
l->setObjectName("DockWidgetAreaLabel");
const qreal metric = dropIndicatiorWidth(l);
const QSizeF size(metric, metric);
qreal metric = dropIndicatiorWidth(l);
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->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
@@ -182,6 +213,11 @@ struct DockOverlayCrossPrivate
{
QColor borderColor = iconColor(CDockOverlayCross::FrameColor);
QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor);
QColor overlayColor = iconColor(CDockOverlayCross::OverlayColor);
if (overlayColor.alpha() == 255)
{
overlayColor.setAlpha(64);
}
#if QT_VERSION >= 0x050600
double DevicePixelRatio = _this->window()->devicePixelRatioF();
@@ -239,22 +275,22 @@ struct DockOverlayCrossPrivate
}
QSizeF baseSize = baseRect.size();
if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea)
bool IsOuterContainerArea = (CDockOverlay::ModeContainerOverlay == Mode)
&& (DockWidgetArea != CenterDockWidgetArea)
&& !internal::isSideBarArea(DockWidgetArea);
if (IsOuterContainerArea)
{
baseRect = areaRect;
}
p.fillRect(baseRect, backgroundColor);
if (areaRect.isValid())
{
pen = p.pen();
pen.setColor(borderColor);
QColor Color = iconColor(CDockOverlayCross::OverlayColor);
if (Color.alpha() == 255)
{
Color.setAlpha(64);
}
p.setBrush(Color);
p.setBrush(overlayColor);
p.setPen(Qt::NoPen);
p.drawRect(areaRect);
@@ -267,6 +303,7 @@ struct DockOverlayCrossPrivate
}
p.restore();
p.save();
// Draw outer border
pen = p.pen();
@@ -282,8 +319,9 @@ struct DockOverlayCrossPrivate
p.drawRect(FrameRect);
p.restore();
// Draw arrow for outer container drop indicators
if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea)
if (IsOuterContainerArea)
{
QRectF ArrowRect;
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) :
QFrame(parent),
@@ -333,7 +403,7 @@ CDockOverlay::CDockOverlay(QWidget* parent, eMode Mode) :
{
d->Mode = Mode;
d->Cross = new CDockOverlayCross(this);
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
#else
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
@@ -359,12 +429,26 @@ CDockOverlay::~CDockOverlay()
void CDockOverlay::setAllowedAreas(DockWidgetAreas areas)
{
if (areas == d->AllowedAreas)
{
return;
}
d->AllowedAreas = areas;
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
{
@@ -375,22 +459,68 @@ DockWidgetAreas CDockOverlay::allowedAreas() const
//============================================================================
DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
{
d->TabIndex = InvalidTabIndex;
if (!d->TargetWidget)
{
return InvalidDockWidgetArea;
}
DockWidgetArea Result = d->Cross->cursorLocation();
if (Result != InvalidDockWidgetArea)
{
return Result;
}
CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(d->TargetWidget.data());
if (!DockArea)
auto CursorPos = QCursor::pos();
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;
}
if (DockArea->allowedAreas().testFlag(CenterDockWidgetArea)
&& !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;
}
@@ -398,6 +528,13 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
}
//============================================================================
int CDockOverlay::tabIndexUnderCursor() const
{
return d->TabIndex;
}
//============================================================================
DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const
{
@@ -471,6 +608,7 @@ bool CDockOverlay::dropPreviewEnabled() const
void CDockOverlay::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
// Draw rect based on location
if (!d->DropPreviewEnabled)
{
@@ -490,8 +628,13 @@ void CDockOverlay::paintEvent(QPaintEvent* event)
case BottomDockWidgetArea: r.setY(r.height() * (1 - 1 / Factor)); break;
case LeftDockWidgetArea: r.setWidth(r.width() / Factor); 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;
}
QPainter painter(this);
QColor Color = palette().color(QPalette::Active, QPalette::Highlight);
QPen Pen = painter.pen();
@@ -595,7 +738,7 @@ CDockOverlayCross::CDockOverlayCross(CDockOverlay* overlay) :
d(new DockOverlayCrossPrivate(this))
{
d->DockOverlay = overlay;
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
#else
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
@@ -627,6 +770,7 @@ void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode)
areaWidgets.insert(BottomDockWidgetArea, d->createDropIndicatorWidget(BottomDockWidgetArea, Mode));
areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode));
areaWidgets.insert(CenterDockWidgetArea, d->createDropIndicatorWidget(CenterDockWidgetArea, Mode));
#if QT_VERSION >= 0x050600
d->LastDevicePixelRatio = devicePixelRatioF();
#else

View File

@@ -72,6 +72,11 @@ public:
*/
void setAllowedAreas(DockWidgetAreas areas);
/**
* Enable / disable a certain area
*/
void setAllowedArea(DockWidgetArea area, bool Enable);
/**
* Returns flags with all allowed drop areas
*/
@@ -82,6 +87,17 @@ public:
*/
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
* 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
* fuctionality.
* functionality.
*/
class ADS_EXPORT CDockSplitter : public QSplitter
{

View File

@@ -95,6 +95,7 @@ struct DockWidgetPrivate
CDockWidget::eMinimumSizeHintMode MinimumSizeHintMode = CDockWidget::MinimumSizeHintFromDockWidget;
WidgetFactory* Factory = nullptr;
QPointer<CAutoHideTab> SideTabWidget;
CDockWidget::eToolBarStyleSource ToolBarStyleSource = CDockWidget::ToolBarStyleFromDockManager;
/**
* Private data constructor
@@ -139,6 +140,11 @@ struct DockWidgetPrivate
* returns true on success.
*/
bool createWidgetFromFactory();
/**
* Use the dock manager toolbar style and icon size for the different states
*/
void setToolBarStyleFromDockManager();
};
// struct DockWidgetPrivate
@@ -213,6 +219,12 @@ void DockWidgetPrivate::hideDockWidget()
if (Features.testFlag(CDockWidget::DeleteContentOnClose))
{
if (ScrollArea)
{
ScrollArea->takeWidget();
delete ScrollArea;
ScrollArea = nullptr;
}
Widget->deleteLater();
Widget = nullptr;
}
@@ -325,6 +337,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) :
QFrame(parent),
@@ -358,6 +386,20 @@ CDockWidget::~CDockWidget()
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)
@@ -503,6 +545,15 @@ CDockManager* CDockWidget::dockManager() const
void CDockWidget::setDockManager(CDockManager* DockManager)
{
d->DockManager = DockManager;
if (!DockManager)
{
return;
}
if (ToolBarStyleFromDockManager == d->ToolBarStyleSource)
{
d->setToolBarStyleFromDockManager();
}
}
@@ -555,6 +606,13 @@ bool CDockWidget::isAutoHide() const
}
//============================================================================
SideBarLocation CDockWidget::autoHideLocation() const
{
return isAutoHide() ? autoHideDockContainer()->sideBarLocation() : SideBarNone;
}
//============================================================================
bool CDockWidget::isFloating() const
{
@@ -622,6 +680,13 @@ void CDockWidget::setMinimumSizeHintMode(eMinimumSizeHintMode Mode)
}
//============================================================================
CDockWidget::eMinimumSizeHintMode CDockWidget::minimumSizeHintMode() const
{
return d->MinimumSizeHintMode;
}
//============================================================================
bool CDockWidget::isCentralWidget() const
{
@@ -643,14 +708,20 @@ void CDockWidget::toggleView(bool Open)
// If the dock widget state is different, then we really need to toggle
// the state. If we are in the right state, then we simply make this
// dock widget the current dock widget
auto AutoHideContainer = autoHideDockContainer();
if (d->Closed != !Open)
{
toggleViewInternal(Open);
}
else if (Open && d->DockArea)
else if (Open && d->DockArea && !AutoHideContainer)
{
raise();
}
if (Open && AutoHideContainer)
{
AutoHideContainer->collapseView(false);
}
}
@@ -984,14 +1055,20 @@ void CDockWidget::setClosedState(bool Closed)
//============================================================================
QSize CDockWidget::minimumSizeHint() const
{
if (d->MinimumSizeHintMode == CDockWidget::MinimumSizeHintFromDockWidget || !d->Widget)
if (!d->Widget)
{
return QSize(60, 40);
}
else
switch (d->MinimumSizeHintMode)
{
return d->Widget->minimumSizeHint();
case MinimumSizeHintFromDockWidget: return QSize(60, 40);
case MinimumSizeHintFromContent: return d->Widget->minimumSizeHint();
case MinimumSizeHintFromDockWidgetMinimumSize: return minimumSize();
case MinimumSizeHintFromContentMinimumSize: return d->Widget->minimumSize();
}
return d->Widget->minimumSizeHint();
}
@@ -1002,7 +1079,15 @@ void CDockWidget::setFloating()
{
return;
}
d->TabWidget->detachDockWidget();
if (this->isAutoHide())
{
dockAreaWidget()->setFloating();
}
else
{
d->TabWidget->detachDockWidget();
}
}
@@ -1025,6 +1110,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)
{
@@ -1171,7 +1272,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))
{
@@ -1179,20 +1280,25 @@ void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location)
}
// Do nothing if nothing changes
if (Enable == isAutoHide())
if (Enable == isAutoHide() && Location == autoHideLocation())
{
return;
}
auto DockArea = dockAreaWidget();
if (!Enable)
{
DockArea->setAutoHide(false);
}
else if (isAutoHide())
{
autoHideDockContainer()->moveToNewSideBarLocation(Location);
}
else
{
auto area = (SideBarNone == Location) ? DockArea->calculateSideTabBarArea() : Location;
dockContainer()->createAndSetupAutoHideContainer(area, this);
dockContainer()->createAndSetupAutoHideContainer(area, this, TabIndex);
}
}
@@ -1209,6 +1315,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
//---------------------------------------------------------------------------

View File

@@ -176,6 +176,12 @@ public:
StateFloating
};
enum eToolBarStyleSource
{
ToolBarStyleFromDockManager,
ToolBarStyleFromDockWidget
};
/**
* Sets the widget for the dock widget to widget.
* The InsertMode defines how the widget is inserted into the dock widget.
@@ -208,12 +214,17 @@ public:
* reimplements minimumSizeHint() function to return a very small minimum
* size hint. If you would like to adhere the minimumSizeHint() from the
* content widget, then set the minimumSizeHintMode() to
* MinimumSizeHintFromContent.
* MinimumSizeHintFromContent. If you would like to use the minimumSize()
* value of the content widget or the dock widget, then you can use the
* MinimumSizeHintFromDockWidgetMinimumSize or
* MinimumSizeHintFromContentMinimumSize modes.
*/
enum eMinimumSizeHintMode
{
MinimumSizeHintFromDockWidget,
MinimumSizeHintFromContent
MinimumSizeHintFromContent,
MinimumSizeHintFromDockWidgetMinimumSize,
MinimumSizeHintFromContentMinimumSize,
};
@@ -241,7 +252,7 @@ public:
* 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.
* 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.
* Use the layoutFlags to configure the layout of the dock widget.
*/
@@ -372,6 +383,12 @@ public:
*/
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.
* A dock widget is only floating, if it is the one and only widget inside
@@ -398,6 +415,12 @@ public:
*/
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.
* \see eToggleViewActionMode for a detailed description
@@ -411,6 +434,11 @@ public:
*/
void setMinimumSizeHintMode(eMinimumSizeHintMode Mode);
/**
* Get the minimum size hint mode configured by setMinimumSizeHintMode
*/
eMinimumSizeHintMode minimumSizeHintMode() const;
/**
* Returns true if the dock widget is set as central widget of it's dock manager
*/
@@ -429,7 +457,7 @@ public:
/**
* 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
* createDefaultToolBar() function or you need to assign your custom
* toolbar via setToolBar().
@@ -451,6 +479,17 @@ public:
*/
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.
* It is possible to switch the tool button style depending on the state.
@@ -568,10 +607,19 @@ public Q_SLOTS:
void deleteDockWidget();
/**
* Closes the dock widget
* Closes the dock widget.
* The function forces closing of the dock widget even for CustomCloseHandling.
*/
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.
* Normally this function only affects windows. To make the interface
@@ -596,7 +644,7 @@ public Q_SLOTS:
* Sets the dock widget into auto hide mode if this feature is enabled
* 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

View File

@@ -245,7 +245,14 @@ DockWidgetTabPrivate::DockWidgetTabPrivate(CDockWidgetTab* _public) :
void DockWidgetTabPrivate::createLayout()
{
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->setObjectName("dockWidgetTabLabel");
TitleLabel->setAlignment(Qt::AlignCenter);
@@ -376,6 +383,7 @@ void CDockWidgetTab::mousePressEvent(QMouseEvent* ev)
d->DragState = DraggingMousePressed;
if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
{
d->focusController()->setDockWidgetTabPressed(true);
d->focusController()->setDockWidgetTabFocused(this);
}
Q_EMIT clicked();
@@ -412,7 +420,12 @@ void CDockWidgetTab::mouseReleaseEvent(QMouseEvent* ev)
d->FloatingWidget->finishDragging();
break;
default:; // do nothing
default:
if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
{
d->focusController()->setDockWidgetTabPressed(false);
}
break; // do nothing
}
}
else if (ev->button() == Qt::MiddleButton)
@@ -493,7 +506,7 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
else if (d->DockArea->openDockWidgetsCount() > 1
&& (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
if (DraggingTab != d->DragState)
{
@@ -802,6 +815,7 @@ void CDockWidgetTab::setIconSize(const QSize& Size)
d->IconSize = Size;
d->updateIcon();
}
} // namespace ads
//---------------------------------------------------------------------------
// EOF DockWidgetTab.cpp

View File

@@ -173,7 +173,7 @@ public:
/**
* 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
*/
void setIconSize(const QSize& Size);

View File

@@ -52,7 +52,7 @@
#pragma comment(lib, "User32.lib")
#endif
#endif
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
#include "linux/FloatingWidgetTitleBar.h"
#include <xcb/xcb.h>
#endif
@@ -62,7 +62,7 @@ namespace ads
#ifdef Q_OS_WIN
#if 0 // set to 1 if you need this function for debugging
/**
* Just for debuging to convert windows message identifiers to strings
* Just for debugging to convert windows message identifiers to strings
*/
static const char* windowsMessageString(int MessageId)
{
@@ -374,10 +374,11 @@ struct FloatingDockContainerPrivate
QPoint DragStartPos;
bool Hiding = false;
bool AutoHideChildren = true;
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
QWidget* MouseEventHandler = nullptr;
CFloatingWidgetTitleBar* TitleBar = nullptr;
bool IsResizing = false;
bool MousePressed = false;
#endif
/**
@@ -424,7 +425,7 @@ struct FloatingDockContainerPrivate
void setWindowTitle(const QString &Text)
{
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
if (TitleBar)
{
TitleBar->setTitle(Text);
@@ -498,10 +499,8 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent()
return;
}
if (DockManager->dockAreaOverlay()->dropAreaUnderCursor()
!= InvalidDockWidgetArea
|| DockManager->containerOverlay()->dropAreaUnderCursor()
!= InvalidDockWidgetArea)
if (DockManager->dockAreaOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea
|| DockManager->containerOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea)
{
CDockOverlay *Overlay = DockManager->containerOverlay();
if (!Overlay->dropOverlayRect().isValid())
@@ -509,21 +508,26 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent()
Overlay = DockManager->dockAreaOverlay();
}
// Resize the floating widget to the size of the highlighted drop area
// rectangle
QRect Rect = Overlay->dropOverlayRect();
int FrameWidth = (_this->frameSize().width() - _this->rect().width())
/ 2;
int TitleBarHeight = _this->frameSize().height()
- _this->rect().height() - FrameWidth;
if (Rect.isValid())
// Do not resize if we drop into an autohide sidebar area to preserve
// the dock area size for the initial size of the auto hide area
if (!ads::internal::isSideBarArea(Overlay->dropAreaUnderCursor()))
{
QPoint TopLeft = Overlay->mapToGlobal(Rect.topLeft());
TopLeft.ry() += TitleBarHeight;
_this->setGeometry(
QRect(TopLeft,
QSize(Rect.width(), Rect.height() - TitleBarHeight)));
QApplication::processEvents();
// Resize the floating widget to the size of the highlighted drop area
// rectangle
QRect Rect = Overlay->dropOverlayRect();
int FrameWidth = (_this->frameSize().width() - _this->rect().width())
/ 2;
int TitleBarHeight = _this->frameSize().height()
- _this->rect().height() - FrameWidth;
if (Rect.isValid())
{
QPoint TopLeft = Overlay->mapToGlobal(Rect.topLeft());
TopLeft.ry() += TitleBarHeight;
_this->setGeometry(
QRect(TopLeft,
QSize(Rect.width(), Rect.height() - TitleBarHeight)));
QApplication::processEvents();
}
}
DropContainer->dropFloatingWidget(_this, QCursor::pos());
}
@@ -532,6 +536,7 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent()
DockManager->dockAreaOverlay()->hideOverlay();
}
//============================================================================
void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos)
{
@@ -540,7 +545,7 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos)
return;
}
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
// Prevent display of drop overlays and docking as long as a model dialog
// is active
if (qApp->activeModalWidget())
@@ -585,11 +590,25 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos)
}
int VisibleDockAreas = TopContainer->visibleDockAreaCount();
ContainerOverlay->setAllowedAreas(
VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas);
DockWidgetAreas AllowedContainerAreas = (VisibleDockAreas > 1) ? OuterDockAreas : AllDockAreas;
auto DockArea = TopContainer->dockAreaAt(GlobalPos);
// If the dock container contains only one single DockArea, then we need
// to respect the allowed areas - only the center area is relevant here because
// all other allowed areas are from the container
if (VisibleDockAreas == 1 && DockArea)
{
AllowedContainerAreas.setFlag(CenterDockWidgetArea, DockArea->allowedAreas().testFlag(CenterDockWidgetArea));
}
if (DockContainer->features().testFlag(CDockWidget::DockWidgetPinnable))
{
AllowedContainerAreas |= AutoHideDockAreas;
}
ContainerOverlay->setAllowedAreas(AllowedContainerAreas);
DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer);
ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea);
auto DockArea = TopContainer->dockAreaAt(GlobalPos);
if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0)
{
DockAreaOverlay->enableDropPreview(true);
@@ -641,9 +660,8 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) :
connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this,
SLOT(onDockAreasAddedOrRemoved()));
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
QDockWidget::setWidget(d->DockContainer);
QDockWidget::setFloating(true);
QDockWidget::setFeatures(QDockWidget::DockWidgetClosable
| QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
@@ -674,6 +692,17 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) :
native_window = window_manager != "KWIN";
}
if (native_window)
{
// Native windows do not work if wayland is used. Ubuntu 22.04 uses wayland by default. To use
// native windows, switch to Xorg
QString XdgSessionType = qgetenv("XDG_SESSION_TYPE").toLower();
if ("wayland" == XdgSessionType)
{
native_window = false;
}
}
if (native_window)
{
setTitleBarWidget(new QWidget());
@@ -752,18 +781,43 @@ CDockContainerWidget* CFloatingDockContainer::dockContainer() const
void CFloatingDockContainer::changeEvent(QEvent *event)
{
Super::changeEvent(event);
if ((event->type() == QEvent::ActivationChange) && isActiveWindow())
switch (event->type())
{
ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange ");
d->zOrderIndex = ++zOrderCounter;
#ifdef Q_OS_LINUX
if (d->DraggingState == DraggingFloatingWidget)
case QEvent::ActivationChange:
if (isActiveWindow())
{
d->titleMouseReleaseEvent();
d->DraggingState = DraggingInactive;
}
ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange ");
d->zOrderIndex = ++zOrderCounter;
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
if (d->DraggingState == DraggingFloatingWidget)
{
d->titleMouseReleaseEvent();
d->DraggingState = DraggingInactive;
}
#endif
}
break;
case QEvent::WindowStateChange:
// If the DockManager window is restored from minimized on Windows
// then the FloatingWidgets are not properly restored to maximized but
// to normal state.
// We simply check here, if the FloatingWidget was maximized before
// and if the DockManager is just leaving the minimized state. In this
// case, we restore the maximized state of this floating widget
if (d->DockManager->isLeavingMinimizedState())
{
QWindowStateChangeEvent* ev = static_cast<QWindowStateChangeEvent*>(event);
if (ev->oldState().testFlag(Qt::WindowMaximized))
{
this->showMaximized();
}
}
break;
default:
break; // do nothing
}
}
@@ -909,7 +963,7 @@ void CFloatingDockContainer::hideEvent(QHideEvent *event)
void CFloatingDockContainer::showEvent(QShowEvent *event)
{
Super::showEvent(event);
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
{
this->window()->activateWindow();
@@ -922,7 +976,7 @@ void CFloatingDockContainer::showEvent(QShowEvent *event)
void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos,
const QSize &Size, eDragState DragState, QWidget *MouseEventHandler)
{
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
if (!isMaximized())
{
resize(Size);
@@ -974,7 +1028,7 @@ void CFloatingDockContainer::moveFloating()
// the main window as the active window for some reason. This fixes
// that by resetting the active window to the floating widget after
// updating the overlays.
QApplication::setActiveWindow(this);
activateWindow();
#endif
break;
default:
@@ -1059,7 +1113,7 @@ bool CFloatingDockContainer::restoreState(CDockingStateReader &Stream,
return false;
}
onDockAreasAddedOrRemoved();
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
if(d->TitleBar)
{
d->TitleBar->setMaximizedIcon(windowState() == Qt::WindowMaximized);
@@ -1097,13 +1151,18 @@ void CFloatingDockContainer::hideAndDeleteLater()
d->AutoHideChildren = false;
hide();
deleteLater();
if (d->DockManager)
{
d->DockManager->removeFloatingWidget(this);
d->DockManager->removeDockContainer(this->dockContainer());
}
}
//============================================================================
void CFloatingDockContainer::finishDragging()
{
ADS_PRINT("CFloatingDockContainer::finishDragging");
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
setWindowOpacity(1);
activateWindow();
if (d->MouseEventHandler)
@@ -1207,7 +1266,7 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event)
// the main window as the active window for some reason. This fixes
// that by resetting the active window to the floating widget after
// updating the overlays.
QApplication::setActiveWindow(this);
activateWindow();
break;
default:
break;
@@ -1218,7 +1277,7 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event)
#endif
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
//============================================================================
void CFloatingDockContainer::onMaximizeRequest()
{
@@ -1287,12 +1346,12 @@ void CFloatingDockContainer::resizeEvent(QResizeEvent *event)
Super::resizeEvent(event);
}
static bool s_mousePressed = false;
//============================================================================
void CFloatingDockContainer::moveEvent(QMoveEvent *event)
{
Super::moveEvent(event);
if (!d->IsResizing && event->spontaneous() && s_mousePressed)
if (!d->IsResizing && event->spontaneous() && d->MousePressed)
{
d->setState(DraggingFloatingWidget);
d->updateDropOverlays(QCursor::pos());
@@ -1308,10 +1367,10 @@ bool CFloatingDockContainer::event(QEvent *e)
switch (e->type())
{
case QEvent::WindowActivate:
s_mousePressed = false;
d->MousePressed = false;
break;
case QEvent::WindowDeactivate:
s_mousePressed = true;
d->MousePressed = true;
break;
default:
break;

View File

@@ -33,7 +33,7 @@
#include <QRubberBand>
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
#include <QDockWidget>
#define tFloatingWidgetBase QDockWidget
#else
@@ -182,10 +182,8 @@ protected: // reimplements QWidget
#ifdef Q_OS_MACOS
virtual bool event(QEvent *e) override;
virtual void moveEvent(QMoveEvent *event) override;
#endif
#ifdef Q_OS_LINUX
virtual void moveEvent(QMoveEvent *event) override;
#elif defined(Q_OS_UNIX)
virtual void moveEvent(QMoveEvent *event) override;
virtual void resizeEvent(QResizeEvent *event) override;
virtual bool event(QEvent *e) override;
@@ -264,7 +262,7 @@ public:
*/
void hideAndDeleteLater();
#ifdef Q_OS_LINUX
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
/**
* This is a function that responds to FloatingWidgetTitleBar::maximizeRequest()
* Maximize or normalize the container size.
@@ -300,7 +298,6 @@ public:
*/
bool hasNativeTitleBar();
#endif
}; // class FloatingDockContainer
}
// namespace ads

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