Merge remote-tracking branch 'upstream/master' into forceclose

This commit is contained in:
Nicolas ELIE 2020-10-02 11:04:18 +02:00
commit b320bb17d1
33 changed files with 517 additions and 72 deletions

View File

@ -10,7 +10,7 @@ matrix:
dist: trusty
group: stable
before_install:
- sudo apt-get install libqt5x11extras5-dev
- sudo apt-get -y install libqt5x11extras5-dev
addons:
apt:
sources:
@ -21,6 +21,7 @@ matrix:
- qt55base
- qt55tools
- qt55x11extras
- libqt5x11extras5-dev
- gcc-9
- g++-9
script:
@ -39,7 +40,7 @@ matrix:
- xvfb
compiler: gcc
before_install:
- sudo apt-get install libqt5x11extras5-dev
- sudo apt-get -y install libqt5x11extras5-dev
addons:
apt:
sources:
@ -50,6 +51,7 @@ matrix:
- qt514base
- qt514tools
- qt514x11extras
- libqt5x11extras5-dev
- gcc-9
- g++-9
- libc6-i386
@ -71,9 +73,9 @@ matrix:
services:
- xvfb
compiler: gcc
addons:
before_install:
- sudo apt-get install libqt5x11extras5-dev
- sudo apt-get -y install libqt5x11extras5-dev
addons:
apt:
sources:
- ubuntu-toolchain-r-test
@ -83,6 +85,7 @@ matrix:
- qt514base
- qt514tools
- qt514x11extras
- libqt5x11extras5-dev
- gcc-9
- g++-9
- libc6-i386
@ -105,7 +108,7 @@ matrix:
- xvfb
compiler: gcc
before_install:
- sudo apt-get install libqt5x11extras5-dev
- sudo apt-get -y install libqt5x11extras5-dev
addons:
apt:
sources:
@ -116,6 +119,7 @@ matrix:
- qt514base
- qt514tools
- qt514x11extras
- libqt5x11extras5-dev
- gcc-9
- g++-9
- libc6-i386
@ -144,7 +148,7 @@ matrix:
- xvfb
compiler: gcc
before_install:
- sudo apt-get install libqt5x11extras5-dev
- sudo apt-get -y install libqt5x11extras5-dev
addons:
apt:
sources:
@ -155,6 +159,7 @@ matrix:
- qt514base
- qt514tools
- qt514x11extras
- libqt5x11extras5-dev
- gcc-9
- g++-9
- libc6-i386

View File

@ -15,6 +15,20 @@ integrated development environments (IDEs) such as Visual Studio.
## New and Noteworthy
The [release 3.6.0](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.6.0)
adds some nice new features:
- support for [central widget](doc/user-guide.md#central-widget) concept
![Central Widget](doc/central_widget.gif)
- support for [native floating widgets](doc/user-guide.md#floatingcontainerforcenativetitlebar-linux-only) on Linux
![FloatingContainerForceNativeTitleBar true](doc/cfg_flag_FloatingContainerForceNativeTitleBar_true.png)
Both features are contributions from ADS users. Read the [documentation](doc/user-guide.md)
to learn more about both new features.
The [release 3.5.0](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.5.0)
adds the new [focus highlighting](doc/user-guide.md#focushighlighting) feature.
This optional feature enables highlighting of the focused dock widget like you

View File

@ -109,7 +109,7 @@ static void appendFeaturStringToWindowTitle(ads::CDockWidget* DockWidget)
static QIcon svgIcon(const QString& File)
{
// This is a workaround, because in item views SVG icons are not
// properly scaled an look blurry or pixelate
// properly scaled and look blurry or pixelate
QIcon SvgIcon(File);
SvgIcon.addPixmap(SvgIcon.pixmap(92));
return SvgIcon;
@ -166,6 +166,7 @@ struct MainWindowPrivate
QComboBox* PerspectiveComboBox = nullptr;
ads::CDockManager* DockManager = nullptr;
ads::CDockWidget* WindowTitleTestDockWidget = nullptr;
ads::CDockWidget* LastDockedEditor = nullptr;
MainWindowPrivate(CMainWindow* _public) : _this(_public) {}
@ -719,9 +720,19 @@ void CMainWindow::createEditor()
FloatingWidget->move(QPoint(20, 20));
}
else
{
ads::CDockAreaWidget* EditorArea = d->LastDockedEditor ? d->LastDockedEditor->dockAreaWidget() : nullptr;
if (EditorArea)
{
d->DockManager->setConfigFlag(ads::CDockManager::EqualSplitOnInsertion, true);
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget, EditorArea);
}
else
{
d->DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);
}
d->LastDockedEditor = DockWidget;
}
}

View File

@ -65,7 +65,7 @@ def append_feature_string_to_window_title(dock_widget: QtAds.CDockWidget):
def svg_icon(filename: str):
'''Helper function to create an SVG icon'''
# This is a workaround, because because in item views SVG icons are not
# properly scaled an look blurry or pixelate
# properly scaled and look blurry or pixelate
icon = QIcon(filename)
icon.addPixmap(icon.pixmap(92))
return icon
@ -104,6 +104,8 @@ class MainWindow(MainWindowUI, MainWindowBase):
self.perspective_list_action = None
self.perspective_combo_box = None
self.dock_manager = None
self.window_title_test_dock_widget = None
self.last_docked_editor = None
self.setupUi(self)
self.create_actions()
@ -184,6 +186,7 @@ class MainWindow(MainWindowUI, MainWindowBase):
# special_dock_area.setAllowedAreas(QtAds.LeftDockWidgetArea | QtAds.RightDockWidgetArea) # just for testing
dock_widget = self.create_long_text_label_dock_widget()
self.window_title_test_dock_widget = dock_widget
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetFocusable, False)
self.dock_manager.addDockWidget(QtAds.LeftDockWidgetArea, dock_widget)
file_system_widget = self.create_file_system_tree_dock_widget()
@ -203,8 +206,8 @@ class MainWindow(MainWindowUI, MainWindowBase):
QtAds.CDockComponentsFactory.setFactory(CCustomComponentsFactory())
top_dock_area = self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea, file_system_widget)
# Uncomment the next line if you would like to test the
# setHideSingleWidgetTitleBar() functionality
# top_dock_area.setHideSingleWidgetTitleBar(True)
# HideSingleWidgetTitleBar functionality
# top_dock_area.setDockAreaFlag(QtAds.CDockAreaWidget.HideSingleWidgetTitleBar, True)
QtAds.CDockComponentsFactory.resetDefaultFactory()
# We create a calendar widget and clear all flags to prevent the dock area
@ -354,7 +357,6 @@ class MainWindow(MainWindowUI, MainWindowBase):
def create_editor(self):
sender = self.sender()
floating = sender.property("Floating")
print("Floating:", floating)
dock_widget = self.create_editor_widget()
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose, True)
dock_widget.closeRequested.connect(self.on_editor_close_requested)
@ -362,8 +364,14 @@ class MainWindow(MainWindowUI, MainWindowBase):
if floating:
floating_widget = self.dock_manager.addDockWidgetFloating(dock_widget)
floating_widget.move(QPoint(20, 20))
else:
editor_area = self.last_docked_editor.dockAreaWidget() if self.last_docked_editor is not None else None
if editor_area is not None:
self.dock_manager.setConfigFlag(QtAds.CDockManager.EqualSplitOnInsertion, True)
self.dock_manager.addDockWidget(QtAds.RightDockWidgetArea, dock_widget, editor_area)
else:
self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea, dock_widget)
self.last_docked_editor = dock_widget
def on_editor_close_requested(self):
dock_widget = self.sender()
@ -382,6 +390,16 @@ class MainWindow(MainWindowUI, MainWindowBase):
dialog = CStatusDialog(self.dock_manager)
dialog.exec_()
def toggle_dock_widget_window_title(self):
title = self.window_title_test_dock_widget.windowTitle()
i = title.find(" (Test) ")
if i == -1:
title += " (Test) "
else:
title = title[i]
self.window_title_test_dock_widget.setWindowTitle(title)
def save_state(self):
'''
Saves the dock manager state and the main window geometry

BIN
doc/central_widget.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@ -24,6 +24,10 @@
- [`FloatingContainerHasWidgetIcon`](#floatingcontainerhaswidgeticon)
- [`HideSingleCentralWidgetTitleBar`](#hidesinglecentralwidgettitlebar)
- [`FocusHighlighting`](#focushighlighting)
- [`EqualSplitOnInsertion`](#equalsplitoninsertion)
- [`FloatingContainerForceNativeTitleBar` (Linux only)](#floatingcontainerforcenativetitlebar-linux-only)
- [`FloatingContainerForceQWidgetTitleBar` (Linux only)](#floatingcontainerforceqwidgettitlebar-linux-only)
- [Central Widget](#central-widget)
- [Styling](#styling)
- [Disabling the Internal Style Sheet](#disabling-the-internal-style-sheet)
@ -409,6 +413,93 @@ bool CMainWindow::eventFilter(QObject *watched, QEvent *event)
}
```
### `EqualSplitOnInsertion`
This flag configures how the space is distributed if a new dock widget is
inserted into an existing dock area. The flag is disabled by default. If 3
dock widgets are inserted with the following code
```c++
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget, EditorArea);
```
then this is the result, if the flag is disabled:
![EqualSplitOnInsertion false](cfg_flag_EqualSplitOnInsertion_false.png)
If the flag is enabled, then the space is equally distributed to all widgets
in a splitter:
![EqualSplitOnInsertion true](cfg_flag_EqualSplitOnInsertion_true.png)
### `FloatingContainerForceNativeTitleBar` (Linux only)
Since release 3.6 the library supports native title bars and window decorations
for floating widgets on Linux (thanks to a user contribution).
Native title bars and window decorations are supported by most Linux window
managers, such as Compiz or Xfwm. Some window managers like KWin do not properly
support this feature. Native floating widgets look better because of the native
styling and the support all window manager features like snapping to window
borders or maximizing. The library tries to detect the window manager during
runtime and activates native window decorations if possible:
![FloatingContainerForceNativeTitleBar true](cfg_flag_FloatingContainerForceNativeTitleBar_true.png)
If you would like to overwrite this autodetection, then you can activate this
flag to force native window titlebars. You can overwrite autodetection and this
flag, if you set the environment variable `ADS_UseNativeTitle` to 0 or 1.
### `FloatingContainerForceQWidgetTitleBar` (Linux only)
If your window manager (i.e. KWin) does not properly support native floating
windows, the docking library falls back to QWidget based floating widget
title bars.
![FloatingContainerForceNativeTitleBar false](cfg_flag_FloatingContainerForceNativeTitleBar_false.png)
If you would like to overwrite autodetection, then you can activate this flag
to force QWidget based title bars. You can overwrite autodetection and this
flag, if you set the environment variable `ADS_UseNativeTitle` to 0 or 1.
## Central Widget
The Advanced Docking System has been developed to overcome the limitations of
the native Qt docking system with its central widget concept. This was the
reason that until version 3.6 of the library, there was no support for such
thing like a central widget. Thanks to the contribution of a user the library
now supports a central widget.
In the Advanced Docking System a central widget is a docking widget that is
neither closable nor movable or floatable. A central widget has no title bar
and so it is not possible for the user to hide, close or drag the central
widget. If there is a central widget, then also the distribution of the sizes
for the dock widgets around the central widget is different:
- **no central widget (default)** - on resizing the available space is
distributed to all dock widgets - the size of all dock widgets
shrinks or grows
- **with central widget** - on resizing only the central widget is resized - the
dock widgets around the central widget keep their size (see the animation below)
![Central Widget](central_widget.gif)
To set a central widget, you just need to pass your central dock widget
to the dock manager `setCentralWidget` function:
```c++
auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget);
```
See the `centralwidget` example to learn how it works.
> ##### Note
> The central widget needs to be the first dock widget that is added to the
> dock manager. The function does not work and returns a `nullptr` if there
> are already other dock widgets registered. So `setCentralWidget` should be
> the first function that you call when adding dock widgets.
## Styling
The Advanced Docking System supports styling via [Qt Style Sheets](https://doc.qt.io/qt-5/stylesheet.html). All components like splitters, tabs, buttons, titlebar and

View File

@ -0,0 +1,115 @@
import os
import sys
from PyQt5 import uic
from PyQt5.QtCore import Qt, QTimer, QDir, QSignalBlocker
from PyQt5.QtGui import QCloseEvent, QIcon
from PyQt5.QtWidgets import (QApplication, QLabel, QCalendarWidget, QFrame, QTreeView,
QTableWidget, QFileSystemModel, QPlainTextEdit, QToolBar,
QWidgetAction, QComboBox, QAction, QSizePolicy, QInputDialog)
from PyQtAds import QtAds
UI_FILE = os.path.join(os.path.dirname(__file__), 'mainwindow.ui')
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)
import demo_rc # pyrcc5 demo\demo.qrc -o examples\centralWidget\demo_rc.py
def svg_icon(filename: str):
'''Helper function to create an SVG icon'''
# This is a workaround, because because in item views SVG icons are not
# properly scaled and look blurry or pixelate
icon = QIcon(filename)
icon.addPixmap(icon.pixmap(92))
return icon
class MainWindow(MainWindowUI, MainWindowBase):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.OpaqueSplitterResize, True)
QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.XmlCompressionEnabled, False)
QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.FocusHighlighting, True)
self.dock_manager = QtAds.CDockManager(self)
# Set central widget
text_edit = QPlainTextEdit()
text_edit.setPlaceholderText("This is the central editor. Enter your text here.")
central_dock_widget = QtAds.CDockWidget("CentralWidget")
central_dock_widget.setWidget(text_edit)
central_dock_area = self.dock_manager.setCentralWidget(central_dock_widget)
central_dock_area.setAllowedAreas(QtAds.DockWidgetArea.OuterDockAreas)
# create other dock widgets
file_tree = QTreeView()
file_tree.setFrameShape(QFrame.NoFrame)
file_model = QFileSystemModel(file_tree)
file_model.setRootPath(QDir.currentPath())
file_tree.setModel(file_model)
data_dock_widget = QtAds.CDockWidget("File system")
data_dock_widget.setWidget(file_tree)
data_dock_widget.resize(150, 250)
data_dock_widget.setMinimumSize(100, 250)
file_area = self.dock_manager.addDockWidget(QtAds.DockWidgetArea.LeftDockWidgetArea, data_dock_widget, central_dock_area)
self.menuView.addAction(data_dock_widget.toggleViewAction())
table = QTableWidget()
table.setColumnCount(3)
table.setRowCount(10)
table_dock_widget = QtAds.CDockWidget("Table")
table_dock_widget.setWidget(table)
table_dock_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget)
table_dock_widget.resize(250, 150)
table_dock_widget.setMinimumSize(200, 150)
self.dock_manager.addDockWidget(QtAds.DockWidgetArea.BottomDockWidgetArea, table_dock_widget, file_area)
self.menuView.addAction(table_dock_widget.toggleViewAction())
properties_table = QTableWidget()
properties_table.setColumnCount(3)
properties_table.setRowCount(10)
properties_dock_widget = QtAds.CDockWidget("Properties")
properties_dock_widget.setWidget(properties_table)
properties_dock_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget)
properties_dock_widget.resize(250, 150)
properties_dock_widget.setMinimumSize(200,150)
self.dock_manager.addDockWidget(QtAds.DockWidgetArea.RightDockWidgetArea, properties_dock_widget, central_dock_area)
self.menuView.addAction(properties_dock_widget.toggleViewAction())
self.create_perspective_ui()
def create_perspective_ui(self):
save_perspective_action = QAction("Create Perspective", self)
save_perspective_action.setIcon(svg_icon(":/adsdemo/images/picture_in_picture.svg"))
save_perspective_action.triggered.connect(self.save_perspective)
perspective_list_action = QWidgetAction(self)
self.perspective_combobox = QComboBox(self)
self.perspective_combobox.setSizeAdjustPolicy(QComboBox.AdjustToContents)
self.perspective_combobox.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
self.perspective_combobox.activated[str].connect(self.dock_manager.openPerspective)
perspective_list_action.setDefaultWidget(self.perspective_combobox)
self.toolBar.addSeparator()
self.toolBar.addAction(perspective_list_action)
self.toolBar.addAction(save_perspective_action)
def save_perspective(self):
perspective_name, ok = QInputDialog.getText(self, "Save Perspective", "Enter Unique name:")
if not ok or not perspective_name:
return
self.dock_manager.addPerspective(perspective_name)
blocker = QSignalBlocker(self.perspective_combobox)
self.perspective_combobox.clear()
self.perspective_combobox.addItems(self.dock_manager.perspectiveNames())
self.perspective_combobox.setCurrentText(perspective_name)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()

View File

@ -15,6 +15,8 @@
#include <QFileDialog>
#include <QSettings>
#include <QMessageBox>
#include <QPlainTextEdit>
#include <QToolBar>
#include "DockAreaWidget.h"
#include "DockAreaTitleBar.h"
@ -24,6 +26,18 @@
using namespace ads;
/**
* Helper function to create an SVG icon
*/
static QIcon svgIcon(const QString& File)
{
// This is a workaround, because in item views SVG icons are not
// properly scaled and look blurry or pixelate
QIcon SvgIcon(File);
SvgIcon.addPixmap(SvgIcon.pixmap(92));
return SvgIcon;
}
CMainWindow::CMainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::CMainWindow)
@ -31,12 +45,14 @@ CMainWindow::CMainWindow(QWidget *parent)
ui->setupUi(this);
CDockManager::setConfigFlag(CDockManager::OpaqueSplitterResize, true);
CDockManager::setConfigFlag(CDockManager::XmlCompressionEnabled, false);
CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true);
DockManager = new CDockManager(this);
// Set central widget
QCalendarWidget* calendar = new QCalendarWidget();
QPlainTextEdit* w = new QPlainTextEdit();
w->setPlaceholderText("This is the central editor. Enter your text here.");
CDockWidget* CentralDockWidget = new CDockWidget("CentralWidget");
CentralDockWidget->setWidget(calendar);
CentralDockWidget->setWidget(w);
auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget);
CentralDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas);
@ -65,8 +81,8 @@ CMainWindow::CMainWindow(QWidget *parent)
ui->menuView->addAction(TableDockWidget->toggleViewAction());
QTableWidget* propertiesTable = new QTableWidget();
table->setColumnCount(3);
table->setRowCount(10);
propertiesTable->setColumnCount(3);
propertiesTable->setRowCount(10);
CDockWidget* PropertiesDockWidget = new CDockWidget("Properties");
PropertiesDockWidget->setWidget(propertiesTable);
PropertiesDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
@ -74,6 +90,8 @@ CMainWindow::CMainWindow(QWidget *parent)
PropertiesDockWidget->setMinimumSize(200,150);
DockManager->addDockWidget(DockWidgetArea::RightDockWidgetArea, PropertiesDockWidget, CentralDockArea);
ui->menuView->addAction(PropertiesDockWidget->toggleViewAction());
createPerspectiveUi();
}
CMainWindow::~CMainWindow()
@ -81,3 +99,37 @@ CMainWindow::~CMainWindow()
delete ui;
}
void CMainWindow::createPerspectiveUi()
{
SavePerspectiveAction = new QAction("Create Perspective", this);
SavePerspectiveAction->setIcon(svgIcon(":/adsdemo/images/picture_in_picture.svg"));
connect(SavePerspectiveAction, SIGNAL(triggered()), SLOT(savePerspective()));
PerspectiveListAction = new QWidgetAction(this);
PerspectiveComboBox = new QComboBox(this);
PerspectiveComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
PerspectiveComboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
connect(PerspectiveComboBox, SIGNAL(activated(const QString&)),
DockManager, SLOT(openPerspective(const QString&)));
PerspectiveListAction->setDefaultWidget(PerspectiveComboBox);
ui->toolBar->addSeparator();
ui->toolBar->addAction(PerspectiveListAction);
ui->toolBar->addAction(SavePerspectiveAction);
}
void CMainWindow::savePerspective()
{
QString PerspectiveName = QInputDialog::getText(this, "Save Perspective", "Enter unique name:");
if (PerspectiveName.isEmpty())
{
return;
}
DockManager->addPerspective(PerspectiveName);
QSignalBlocker Blocker(PerspectiveComboBox);
PerspectiveComboBox->clear();
PerspectiveComboBox->addItems(DockManager->perspectiveNames());
PerspectiveComboBox->setCurrentText(PerspectiveName);
}

View File

@ -2,6 +2,8 @@
#define MAINWINDOW_H
#include <QMainWindow>
#include <QComboBox>
#include <QWidgetAction>
#include "DockManager.h"
#include "DockAreaWidget.h"
@ -20,13 +22,19 @@ public:
~CMainWindow();
private:
static const QString kTableTopLayout;
static const QString kTableBottomLayout;
QAction* SavePerspectiveAction = nullptr;
QWidgetAction* PerspectiveListAction = nullptr;
QComboBox* PerspectiveComboBox = nullptr;
Ui::CMainWindow *ui;
ads::CDockManager* DockManager;
ads::CDockAreaWidget* StatusDockArea;
ads::CDockWidget* TimelineDockWidget;
void createPerspectiveUi();
private slots:
void savePerspective();
};
#endif // MAINWINDOW_H

View File

@ -30,6 +30,17 @@
</widget>
<addaction name="menuView"/>
</widget>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
</widget>
<resources/>
<connections/>

View File

@ -21,7 +21,7 @@ class MainWindow(MainWindowUI, MainWindowBase):
# Create the dock manager. Because the parent parameter is a QMainWindow
# the dock manager registers itself as the central widget.
self.dock_manager1 = QtAds.CDockManager(self)
self.dock_manager = QtAds.CDockManager(self)
# Create example content label - this can be any application specific
# widget
@ -35,41 +35,13 @@ class MainWindow(MainWindowUI, MainWindowBase):
dock_widget = QtAds.CDockWidget("Label 1")
dock_widget.setWidget(l)
l = QLabel()
l.setWordWrap(True)
l.setAlignment(Qt.AlignTop | Qt.AlignLeft);
l.setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ")
# Create a dock widget with the title Label 1 and set the created label
# as the dock widget content
dock_widget2 = QtAds.CDockWidget("Label 2")
dock_widget2.setWidget(l)
# Add the toggleViewAction of the dock widget to the menu to give
# the user the possibility to show the dock widget if it has been closed
self.menuView.addAction(dock_widget.toggleViewAction())
# Add the dock widget to the top dock widget area
self.dock_manager1.addDockWidget(QtAds.TopDockWidgetArea, dock_widget)
def remove_first_manager():
self.dock_manager1.removeDockWidget(dock_widget)
del self.dock_manager1
QTimer.singleShot(3000, remove_first_manager)
def add_second_manager():
self.dock_manager2 = QtAds.CDockManager(self)
self.dock_manager2.addDockWidget(QtAds.TopDockWidgetArea, dock_widget)
QTimer.singleShot(5000, add_second_manager)
def closeEvent(self, event: QCloseEvent):
super().closeEvent(event)
if hasattr(self, 'dock_manager1'):
self.dock_manager1.deleteLater()
if hasattr(self, 'dock_manager2'):
self.dock_manager2.deleteLater()
self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea, dock_widget)
if __name__ == '__main__':

View File

@ -227,7 +227,9 @@ class build_ext(sipdistutils.build_ext):
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']
extension.extra_compile_args += ['-D', 'QT_X11EXTRAS_LIB', '-std=c++11']
extension.include_dirs += [os.path.join(self.qt_include_dir, 'QtX11Extras')]
extension.libraries += ['Qt5X11Extras' + self.qt_libinfix]
return super().swig_sources(sources, extension)

View File

@ -28,6 +28,13 @@ protected slots:
void toggleView(bool Open);
public:
enum eDockAreaFlag
{
HideSingleWidgetTitleBar,
DefaultFlags
};
typedef QFlags<ads::CDockAreaWidget::eDockAreaFlag> DockAreaFlags;
CDockAreaWidget(ads::CDockManager* DockManager /TransferThis/, ads::CDockContainerWidget* parent /TransferThis/);
virtual ~CDockAreaWidget();
ads::CDockManager* dockManager() const;
@ -51,9 +58,14 @@ public:
void setAllowedAreas(DockWidgetAreas areas);
DockWidgetAreas allowedAreas() const;
void setHideSingleWidgetTitleBar(bool hide);
CDockAreaTitleBar* titleBar() const;
DockAreaFlags dockAreaFlags() const;
void setDockAreaFlags(DockAreaFlags Flags);
void setDockAreaFlag(eDockAreaFlag Flag, bool On);
bool isCentralWidgetArea() const;
public slots:
void setCurrentIndex(int index);
void closeArea();

View File

@ -32,6 +32,7 @@ protected:
ads::CDockWidget* topLevelDockWidget() const;
ads::CDockAreaWidget* topLevelDockArea() const;
QList<ads::CDockWidget*> dockWidgets() const;
void updateSplitterHandles(QSplitter* splitter);
public:
/**

View File

@ -20,6 +20,7 @@ public:
void notifyWidgetOrAreaRelocation(QWidget* RelocatedWidget);
void notifyFloatingWidgetDrop(ads::CFloatingDockContainer* FloatingWidget);
ads::CDockWidget* focusedDockWidget() const;
public slots:
void setDockWidgetFocused(ads::CDockWidget* focusedNow);

View File

@ -135,6 +135,7 @@ protected:
ads::CDockOverlay* dockAreaOverlay() const;
void notifyWidgetOrAreaRelocation(QWidget* RelocatedWidget);
void notifyFloatingWidgetDrop(ads::CFloatingDockContainer* FloatingWidget);
ads::CDockWidget* focusedDockWidget() const;
virtual void showEvent(QShowEvent *event);
@ -170,6 +171,8 @@ public:
HideSingleCentralWidgetTitleBar,
FocusHighlighting,
EqualSplitOnInsertion,
FloatingContainerForceNativeTitleBar,
FloatingContainerForceQWidgetTitleBar,
DefaultDockAreaButtons,
DefaultBaseConfig,
DefaultOpaqueConfig,
@ -206,6 +209,8 @@ public:
QStringList perspectiveNames() const;
void savePerspectives(QSettings& Settings) const;
void loadPerspectives(QSettings& Settings);
CDockWidget* centralWidget() const;
CDockAreaWidget* setCentralWidget(CDockWidget* widget /Transfer/);
QAction* addToggleViewActionToMenu(QAction* ToggleViewAction /Transfer/,
const QString& Group = QString(), const QIcon& GroupIcon = QIcon());
QMenu* viewMenu() const;
@ -226,6 +231,7 @@ signals:
void perspectiveOpened(const QString& PerspectiveName);
void floatingWidgetCreated(ads::CFloatingDockContainer*);
void dockAreaCreated(ads::CDockAreaWidget*);
void dockWidgetAdded(ads::CDockWidget* DockWidget);
void dockWidgetAboutToBeRemoved(ads::CDockWidget*);
void dockWidgetRemoved(ads::CDockWidget*);
void focusedDockWidgetChanged(ads::CDockWidget*, ads::CDockWidget*);

View File

@ -18,6 +18,7 @@ public:
bool hasVisibleContent() const;
QWidget* firstWidget() const;
QWidget* lastWidget() const;
bool isResizingWithContainer() const;
};

View File

@ -85,6 +85,7 @@ public:
QAction* toggleViewAction() const;
void setToggleViewActionMode(ads::CDockWidget::eToggleViewActionMode Mode);
void setMinimumSizeHintMode(ads::CDockWidget::eMinimumSizeHintMode Mode);
bool isCentralWidget() const;
void setIcon(const QIcon& Icon);
QIcon icon() const;
QToolBar* toolBar() const;

View File

@ -52,11 +52,20 @@ protected:
protected:
virtual void changeEvent(QEvent *event);
virtual void moveEvent(QMoveEvent *event);
virtual bool event(QEvent *e);
virtual void closeEvent(QCloseEvent *event);
virtual void hideEvent(QHideEvent *event);
virtual void showEvent(QShowEvent *event);
%If (WS_MACX)
virtual bool event(QEvent *e);
virtual void moveEvent(QMoveEvent *event);
%End
%If (WS_X11)
virtual void moveEvent(QMoveEvent *event);
virtual void resizeEvent(QResizeEvent *event);
%End
%If (WS_WIN)
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result);
%End
@ -72,6 +81,15 @@ public:
bool hasTopLevelDockWidget() const;
ads::CDockWidget* topLevelDockWidget() const;
QList<ads::CDockWidget*> dockWidgets() const;
%If (WS_X11)
void onMaximizeRequest();
void showNormal(bool fixGeometry);
void showMaximized();
bool isMaximized() const;
void show();
bool hasNativeTitleBar();
%End
};
};

View File

@ -15,15 +15,24 @@ protected:
virtual void mousePressEvent(QMouseEvent *ev);
virtual void mouseReleaseEvent(QMouseEvent *ev);
virtual void mouseMoveEvent(QMouseEvent *ev);
virtual void mouseDoubleClickEvent(QMouseEvent *event);
void setMaximizeIcon(const QIcon& Icon);
QIcon maximizeIcon() const;
void setNormalIcon(const QIcon& Icon);
QIcon normalIcon() const;
public:
explicit CFloatingWidgetTitleBar(CFloatingDockContainer *parent /TransferThis/ = 0);
virtual ~CFloatingWidgetTitleBar();
void enableCloseButton(bool Enable);
void setTitle(const QString &Text);
void updateStyle();
void setMaximizedIcon(bool maximized);
signals:
void closeRequested();
void maximizeRequested();
};
};

View File

@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 3.5)
project(QtAdvancedDockingSystem LANGUAGES CXX VERSION ${VERSION_SHORT})
find_package(Qt5 5.5 COMPONENTS Core Gui Widgets X11Extras REQUIRED)
find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED)
if (UNIX)
find_package(Qt5 5.5 COMPONENTS X11Extras REQUIRED)
endif()
set(CMAKE_INCLUDE_CURRENT_DIR ON)
if(BUILD_STATIC)
set(CMAKE_STATIC_LIBRARY_SUFFIX "_static${CMAKE_STATIC_LIBRARY_SUFFIX}")
@ -57,6 +60,9 @@ else()
target_compile_definitions(qtadvanceddocking PRIVATE ADS_SHARED_EXPORT)
endif()
target_link_libraries(qtadvanceddocking PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets)
if (UNIX)
target_link_libraries(qtadvanceddocking PUBLIC Qt5::X11Extras)
endif()
set_target_properties(qtadvanceddocking PROPERTIES
AUTOMOC ON
AUTORCC ON

View File

@ -1207,7 +1207,7 @@ void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget)
std::cout << (const char*)buf
<< (DockArea->isHidden() ? " " : "v")
<< (DockArea->openDockWidgetsCount() > 0 ? " " : "c")
<< " DockArea" << std::endl;
<< " DockArea " << "[hs: " << DockArea->sizePolicy().horizontalStretch() << ", vs: " << DockArea->sizePolicy().verticalStretch() << "]" << std::endl;
buf.fill(' ', (level + 1) * 4);
for (int i = 0; i < DockArea->dockWidgetsCount(); ++i)
{

View File

@ -381,6 +381,13 @@ void CDockFocusController::onStateRestored()
}
}
//==========================================================================
CDockWidget* CDockFocusController::focusedDockWidget() const
{
return d->FocusedDockWidget.data();
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@ -77,6 +77,12 @@ public:
*/
void notifyFloatingWidgetDrop(CFloatingDockContainer* FloatingWidget);
/**
* Returns the dock widget that has focus style in the ui or a nullptr if
* not dock widget is painted focused.
*/
CDockWidget* focusedDockWidget() const;
public slots:
/**
* Request a focus change to the given dock widget

View File

@ -279,6 +279,27 @@ bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int versi
int DockContainers = s.attributes().value("Containers").toInt();
#endif
ADS_PRINT(DockContainers);
if (CentralWidget)
{
const auto CentralWidgetAttribute = s.attributes().value("CentralWidget");
// If we have a central widget but a state without central widget, then
// something is wrong.
if (CentralWidgetAttribute.isEmpty())
{
qWarning() << "Dock manager has central widget but saved state does not have central widget.";
return false;
}
// If the object name of the central widget does not match the name of the
// saved central widget, the something is wrong
if (CentralWidget->objectName() != CentralWidgetAttribute.toString())
{
qWarning() << "Object name of central widget does not match name of central widget in saved state.";
return false;
}
}
int DockContainerCount = 0;
while (s.readNextStartElement())
{
@ -405,7 +426,6 @@ bool DockManagerPrivate::restoreState(const QByteArray& State, int version)
return false;
}
CentralWidget = nullptr;
// Hide updates of floating widgets from use
hideFloatingWidgets();
markDockWidgetsDirty();
@ -419,6 +439,7 @@ bool DockManagerPrivate::restoreState(const QByteArray& State, int version)
restoreDockWidgetsOpenState();
restoreDockAreasIndices();
emitTopLevelEvents();
_this->dumpLayout();
return true;
}
@ -636,6 +657,10 @@ QByteArray CDockManager::saveState(int version) const
s.writeAttribute("Version", QString::number(CurrentVersion));
s.writeAttribute("UserVersion", QString::number(version));
s.writeAttribute("Containers", QString::number(d->Containers.count()));
if (d->CentralWidget)
{
s.writeAttribute("CentralWidget", d->CentralWidget->objectName());
}
for (auto Container : d->Containers)
{
Container->saveState(s);
@ -706,6 +731,7 @@ CFloatingDockContainer* CDockManager::addDockWidgetFloating(CDockWidget* Dockwid
{
d->UninitializedFloatingWidgets.append(FloatingWidget);
}
emit dockWidgetAdded(Dockwidget);
return FloatingWidget;
}
@ -732,7 +758,9 @@ CDockAreaWidget* CDockManager::addDockWidget(DockWidgetArea area,
CDockWidget* Dockwidget, CDockAreaWidget* DockAreaWidget)
{
d->DockWidgetsMap.insert(Dockwidget->objectName(), Dockwidget);
return CDockContainerWidget::addDockWidget(area, Dockwidget, DockAreaWidget);
auto AreaOfAddedDockWidget = CDockContainerWidget::addDockWidget(area, Dockwidget, DockAreaWidget);
emit dockWidgetAdded(Dockwidget);
return AreaOfAddedDockWidget;
}
@ -901,10 +929,20 @@ CDockAreaWidget* CDockManager::setCentralWidget(CDockWidget* widget)
return nullptr;
}
// Setting a new central widget is now allowed if there is alread a central
// widget
// Setting a new central widget is now allowed if there is already a central
// widget or if there are already other dock widgets
if (d->CentralWidget)
{
qWarning("Setting a central widget not possible because there is already a central widget.");
return nullptr;
}
// Setting a central widget is now allowed if there are already other
// dock widgets.
if (!d->DockWidgetsMap.isEmpty())
{
qWarning("Setting a central widget not possible - the central widget need to be the first "
"dock widget that is added to the dock manager.");
return nullptr;
}
@ -1042,6 +1080,20 @@ void CDockManager::setDockWidgetFocused(CDockWidget* DockWidget)
}
//===========================================================================
CDockWidget* CDockManager::focusedDockWidget() const
{
if (!d->FocusController)
{
return nullptr;
}
else
{
return d->FocusController->focusedDockWidget();
}
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@ -398,9 +398,12 @@ public:
* movable, floatable or closable and the titlebar of the central
* dock area is not visible.
* If the given widget could be set as central widget, the function returns
* the created cok area. If the widget could not be set, because there
* the created dock area. If the widget could not be set, because there
* is already a central widget, this function returns a nullptr.
* To clear the central widget, pass a nullptr to the function.
* \note Setting a central widget is only possible if no other dock widgets
* have been registered before. That means, this function should be the
* first function that you call before you add other dock widgets.
* \retval != 0 The dock area that contains the central widget
* \retval nullptr Indicates that the given widget can not be set as central
* widget because there is already a central widget.
@ -476,6 +479,14 @@ public:
bool eventFilter(QObject *obj, QEvent *e) override;
#endif
/**
* Returns the dock widget that has focus style in the ui or a nullptr if
* not dock widget is painted focused.
* If the flag FocusHighlighting is disabled, this function always returns
* nullptr.
*/
CDockWidget* focusedDockWidget() const;
public slots:
/**
* Opens the perspective with the given name.
@ -544,6 +555,12 @@ signals:
*/
void dockAreaCreated(ads::CDockAreaWidget* DockArea);
/**
* This signal is emitted if a dock widget has been added to this
* dock manager instance.
*/
void dockWidgetAdded(ads::CDockWidget* DockWidget);
/**
* This signal is emitted just before the given dock widget is removed
* from the dock manager

View File

@ -146,6 +146,19 @@ struct DockWidgetTabPrivate
CloseButton->setVisible(DockWidgetClosable && TabHasCloseButton);
}
/**
* Update the size policy of the close button depending on the
* RetainTabSizeWhenCloseButtonHidden feature
*/
void updateCloseButtonSizePolicy()
{
auto Features = DockWidget->features();
auto SizePolicy = CloseButton->sizePolicy();
SizePolicy.setRetainSizeWhenHidden(Features.testFlag(CDockWidget::DockWidgetClosable)
&& testConfigFlag(CDockManager::RetainTabSizeWhenCloseButtonHidden));
CloseButton->setSizePolicy(SizePolicy);
}
template <typename T>
IFloatingWidget* createFloatingWidget(T* Widget, bool OpaqueUndocking)
{
@ -200,7 +213,7 @@ void DockWidgetTabPrivate::createLayout()
CloseButton->setObjectName("tabCloseButton");
internal::setButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton, TabCloseIcon);
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
_this->onDockWidgetFeaturesChanged();
updateCloseButtonSizePolicy();
internal::setToolTip(CloseButton, QObject::tr("Close Tab"));
_this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested()));
@ -656,11 +669,7 @@ bool CDockWidgetTab::event(QEvent *e)
//============================================================================
void CDockWidgetTab::onDockWidgetFeaturesChanged()
{
auto Features = d->DockWidget->features();
auto SizePolicy = d->CloseButton->sizePolicy();
SizePolicy.setRetainSizeWhenHidden(Features.testFlag(CDockWidget::DockWidgetClosable)
&& d->testConfigFlag(CDockManager::RetainTabSizeWhenCloseButtonHidden));
d->CloseButton->setSizePolicy(SizePolicy);
d->updateCloseButtonSizePolicy();
d->updateCloseButtonVisibility(isActiveTab());
}

View File

@ -752,7 +752,7 @@ bool CFloatingDockContainer::nativeEvent(const QByteArray &eventType, void *mess
case WM_NCLBUTTONDOWN:
if (msg->wParam == HTCAPTION && d->isState(DraggingInactive))
{
ADS_PRINT("CFloatingDockContainer::nativeEvent WM_NCLBUTTONDOWN" << e->type());
ADS_PRINT("CFloatingDockContainer::nativeEvent WM_NCLBUTTONDOWN");
d->DragStartPos = pos();
d->setState(DraggingMousePressed);
}
@ -765,7 +765,7 @@ bool CFloatingDockContainer::nativeEvent(const QByteArray &eventType, void *mess
case WM_ENTERSIZEMOVE:
if (d->isState(DraggingMousePressed))
{
ADS_PRINT("CFloatingDockContainer::nativeEvent WM_ENTERSIZEMOVE" << e->type());
ADS_PRINT("CFloatingDockContainer::nativeEvent WM_ENTERSIZEMOVE");
d->setState(DraggingFloatingWidget);
d->updateDropOverlays(QCursor::pos());
}
@ -774,7 +774,7 @@ bool CFloatingDockContainer::nativeEvent(const QByteArray &eventType, void *mess
case WM_EXITSIZEMOVE:
if (d->isState(DraggingFloatingWidget))
{
ADS_PRINT("CFloatingDockContainer::nativeEvent WM_EXITSIZEMOVE" << e->type());
ADS_PRINT("CFloatingDockContainer::nativeEvent WM_EXITSIZEMOVE");
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)
{
d->handleEscapeKey();

View File

@ -69,7 +69,7 @@ SOURCES += \
DockFocusController.cpp
unix {
unix:!macx {
HEADERS += linux/FloatingWidgetTitleBar.h
SOURCES += linux/FloatingWidgetTitleBar.cpp
QT += x11extras