Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d30fc9c3c | ||
|
|
ca1d3fcd38 | ||
|
|
b82d23e59c | ||
|
|
6d8e396e92 | ||
|
|
e4a71982d9 | ||
|
|
3b8775fd86 | ||
|
|
d5ffd8f6a7 | ||
|
|
296c7edbd0 | ||
|
|
4600af712b | ||
|
|
21d8a3dcdb | ||
|
|
0c9773ab54 | ||
|
|
65a645b2cc | ||
|
|
a61d5bd8c0 | ||
|
|
22f609cfa6 | ||
|
|
225b1ff2bb | ||
|
|
00e4dc14ba | ||
|
|
8ef696f6f2 | ||
|
|
b6d7f868ac | ||
|
|
537828ef3d | ||
|
|
6444e7424f | ||
|
|
3cd6d766f8 | ||
|
|
82c98a3f91 | ||
|
|
c11a496278 | ||
|
|
d27783e2f1 | ||
|
|
efd88565a9 | ||
|
|
f3bb1b17d0 | ||
|
|
518cee9d0a | ||
|
|
6302ab03d8 | ||
|
|
2afca346b0 |
127
README.md
127
README.md
@@ -8,13 +8,14 @@
|
||||
[](https://ci.appveyor.com/project/githubuser0xFFFF/qt-advanced-docking-system/branch/master)
|
||||
[](gnu-lgpl-v2.1.md)
|
||||
|
||||
[What's new](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/latest)
|
||||
[Documentation](doc/user-guide.md)
|
||||
|
||||
Qt Advanced Docking System lets you create customizable layouts using a full
|
||||
featured window docking system similar to what is found in many popular
|
||||
integrated development environments (IDEs) such as Visual Studio.
|
||||
|
||||
- [What's new](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/latest)
|
||||
- [Documentation](doc/user-guide.md)
|
||||
- Original Repository: https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System
|
||||
|
||||
[](https://www.youtube.com/watch?v=7pdNfafg3Qc)
|
||||
|
||||
## New and Noteworthy
|
||||
@@ -25,6 +26,7 @@ adds the following features:
|
||||
- option to close tabs with the middle mouse button
|
||||
- `DeleteContentOnClose` flag for dynamic deletion and creation of dock widget
|
||||
content
|
||||
- improved focus highlighting functionality
|
||||
|
||||
The [release 3.7](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.7.2)
|
||||
adds the following features:
|
||||
@@ -71,7 +73,9 @@ know it from Visual Studio.
|
||||
- [Tab-menu for easy handling of many tabbed dock widgets](#tab-menu-for-easy-handling-of-many-tabbed-dock-widgets)
|
||||
- [Many different ways to detach dock widgets](#many-different-ways-to-detach-dock-widgets)
|
||||
- [Supports deletion of dynamically created dock widgets](#supports-deletion-of-dynamically-created-dock-widgets)
|
||||
- [Python PyQt5 Bindings](#python-pyqt5-bindings)
|
||||
- [Python Bindings](#python-bindings)
|
||||
- [PySide6](#pyside6)
|
||||
- [PyQt5](#pyqt5)
|
||||
- [Tested Compatible Environments](#tested-compatible-environments)
|
||||
- [Supported Qt Versions](#supported-qt-versions)
|
||||
- [Windows](#windows)
|
||||
@@ -79,11 +83,7 @@ know it from Visual Studio.
|
||||
- [Linux](#linux)
|
||||
- [Build](#build)
|
||||
- [Getting started / Example](#getting-started--example)
|
||||
- [Developers](#developers)
|
||||
- [License information](#license-information)
|
||||
- [Alternative Docking System Implementations](#alternative-docking-system-implementations)
|
||||
- [KDDockWidgets](#kddockwidgets)
|
||||
- [QtitanDocking](#qtitandocking)
|
||||
- [Donation](#donation)
|
||||
- [Showcase](#showcase)
|
||||
- [Qt Creator IDE](#qt-creator-ide)
|
||||
@@ -97,6 +97,10 @@ know it from Visual Studio.
|
||||
- [Notepad Next](#notepad-next)
|
||||
- [MetGem](#metgem)
|
||||
- [PRE Workbench](#pre-workbench)
|
||||
- [Alternative Docking System Implementations](#alternative-docking-system-implementations)
|
||||
- [KDDockWidgets](#kddockwidgets)
|
||||
- [QtitanDocking](#qtitandocking)
|
||||
- [DockingPanes](#dockingpanes)
|
||||
|
||||
### Docking everywhere - no central widget
|
||||
|
||||
@@ -151,7 +155,7 @@ If this flag is cleared, the widget resizing is deferred until the mouse button
|
||||
|
||||
### Opaque and non-opaque undocking
|
||||
|
||||
By default, opaque undocking is active. That means, as soon as you drag a dock widget or a dock area with a number of dock widgets it will be undocked and moved into a floating widget and then the floating widget will be dragged around. That means undocking will take place immediatelly. You can compare this with opaque splitter resizing. If the flag `OpaqueUndocking` is cleared, then non-opaque undocking is active. In this mode, undocking is more like a standard drag and drop operation. That means, the dragged dock widget or dock area is not undocked immediatelly. Instead, a drag preview widget is created and dragged around to indicate the future position of the dock widget or dock area. The actual dock operation is only executed when the mouse button is released. That makes it possible, to cancel an active drag operation with the escape key.
|
||||
By default, opaque undocking is active. That means, as soon as you drag a dock widget or a dock area with a number of dock widgets it will be undocked and moved into a floating widget and then the floating widget will be dragged around. That means undocking will take place immediately. You can compare this with opaque splitter resizing. If the flag `OpaqueUndocking` is cleared, then non-opaque undocking is active. In this mode, undocking is more like a standard drag and drop operation. That means, the dragged dock widget or dock area is not undocked immediately. Instead, a drag preview widget is created and dragged around to indicate the future position of the dock widget or dock area. The actual dock operation is only executed when the mouse button is released. That makes it possible, to cancel an active drag operation with the escape key.
|
||||
|
||||
The drag preview widget can be configured by a number of global dock manager flags:
|
||||
- `DragPreviewIsDynamic`: if this flag is enabled, the preview will be adjusted dynamically to the drop area
|
||||
@@ -178,19 +182,45 @@ You can detach dock widgets and also dock areas in the following ways:
|
||||
|
||||
Normally clicking the close button of a dock widget will just hide the widget and the user can show it again using the toggleView() action of the dock widget. This is meant for user interfaces with a static amount of widgets. But the advanced docking system also supports dynamic dock widgets that will get deleted on close. If you set the dock widget flag `DockWidgetDeleteOnClose` for a certain dock widget, then it will be deleted as soon as you close this dock widget. This enables the implementation of user interfaces with dynamically created editors, like in word processing applications or source code development tools.
|
||||
|
||||
### Python PyQt5 Bindings
|
||||
## Python Bindings
|
||||
|
||||

|
||||
|
||||
The Advanced Docking System comes with a complete Python integration based on
|
||||
PyQt5 bindings. The package is available via [conda-forge](https://github.com/conda-forge/pyqtads-feedstock). The python integration has been contributed to this project
|
||||
by the following people:
|
||||
Thanks to the contribution of several users, the Advanced Docking System comes
|
||||
with a complete Python integration. Python bindings are available for **PyQt5** and
|
||||
**PySide6**.
|
||||
|
||||
### PySide6
|
||||
|
||||
A PySide6 ADS package is available via PyPi and can be installed on Windows,
|
||||
macOS, and Linux with:
|
||||
|
||||
```bash
|
||||
pip install PySide6-QtAds
|
||||
```
|
||||
|
||||
Sample code is available [here](https://github.com/mborgerson/Qt-Advanced-Docking-System/tree/pyside6/examples). To run the samples, you'll also need to install latest qtpy
|
||||
from source (pip install https://github.com/spyder-ide/qtpy/archive/refs/heads/master.zip).
|
||||
The PySide6 bindings were contributed by:
|
||||
|
||||
- [mborgerson](https://github.com/mborgerson)
|
||||
|
||||
For more information about the PySide6 bindings read [this](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/298) issue.
|
||||
|
||||
### PyQt5
|
||||
|
||||
A package is available via [conda-forge](https://github.com/conda-forge/pyqtads-feedstock).
|
||||
The python integration has been contributed to this project by the following people:
|
||||
|
||||
- [n-elie](https://github.com/n-elie)
|
||||
- [Hugo Slepicka](https://github.com/hhslepicka)
|
||||
- [K Lauer](https://github.com/klauer)
|
||||
|
||||
Latest working version: [3.5.2](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.5.2)
|
||||
A Python integration is also available via PyPi. You can install the
|
||||
[PyQtAds](https://pypi.org/project/PyQtAds/) package via pip. This feature has been
|
||||
contributed to this project by:
|
||||
|
||||
- [Mira Weller](https://github.com/luelista)
|
||||
|
||||
## Tested Compatible Environments
|
||||
|
||||
@@ -319,41 +349,11 @@ MainWindow::~MainWindow()
|
||||
}
|
||||
```
|
||||
|
||||
## Developers
|
||||
|
||||
- Uwe Kindler, Project Maintainer
|
||||
- Manuel Freiholz
|
||||
|
||||
This work is based on and inspired by the
|
||||
[Advanced Docking System for Qt](https://github.com/mfreiholz/Qt-Advanced-Docking-System)
|
||||
from Manuel Freiholz. I did an almost complete rewrite of his code to improve
|
||||
code quality, readibility and to fix all issues from the issue tracker
|
||||
of his docking system project.
|
||||
|
||||
## License information
|
||||
|
||||
[](gnu-lgpl-v2.1.md)
|
||||
This project uses the [LGPLv2.1 license](gnu-lgpl-v2.1.md)
|
||||
|
||||
|
||||
## Alternative Docking System Implementations
|
||||
|
||||
If this Qt Advanced Docking System does not fit to your needs you may consider some of the alternative docking system solutions for Qt.
|
||||
|
||||
### KDDockWidgets
|
||||
|
||||
This is an advanced docking framework for Qt from [KDAB](https://www.kdab.com/). The interesting thing is, that they separated GUI code from logic, so they can easily provide a QtQuick backend in the future.
|
||||
|
||||
- [Blog post about KDDockWidgets](https://www.kdab.com/kddockwidgets/)
|
||||
- [GitHub project](https://github.com/KDAB/KDDockWidgets)
|
||||
|
||||
|
||||
### QtitanDocking
|
||||
|
||||
This is a commercial component from [Developer Machines](https://www.devmachines.com/) for Qt Framework that allows to create a Microsoft like dockable user interface. They also offer a lot of other interesting and useful components for Qt.
|
||||
|
||||
- [Product page](https://www.devmachines.com/qtitandocking-overview.html)
|
||||
|
||||
## Donation
|
||||
|
||||
If this project help you reduce time to develop or if you just like it, you can give me a cup of coffee :coffee::wink:.
|
||||
@@ -379,12 +379,14 @@ Taken from the [Qt Blog](https://www.qt.io/blog/qt-design-studio-1.5-beta-releas
|
||||
|
||||
[](https://youtu.be/za9KBWcFXEw?t=84)
|
||||
|
||||
### [CETONI Elements](https://www.cetoni.com/products/qmixelements/)
|
||||
### [CETONI Elements](https://cetoni.com/cetoni-elements/)
|
||||
|
||||
The CETONI Elements software from [CETONI](https://www.cetoni.com) is a comprehensive,
|
||||
plugin-based and modular laboratory automation software for controlling CETONI devices using a joint graphical user interface. The software features a powerful script system to automate processes. The software uses the advanced docking system to give the user the freedom to arrange all the views and windows that are provided by the various plugins.
|
||||
|
||||

|
||||
[learn more...](https://cetoni.com/cetoni-elements/)
|
||||
|
||||
[](https://www.youtube.com/watch?v=7pdNfafg3Qc)
|
||||
|
||||
### [ezEditor](https://github.com/ezEngine/ezEngine)
|
||||
|
||||
@@ -400,13 +402,13 @@ D-Tect X is a X-ray inspection software for industrial radiography. It is a stat
|
||||
|
||||
[learn more...](https://www.duerr-ndt.com/products/ndt-software/d-tect-xray-inspection-software.html)
|
||||
|
||||

|
||||
[](https://youtu.be/mOor7GmmIJo?t=13)
|
||||
|
||||
### [HiveWE](https://github.com/stijnherfst/HiveWE)
|
||||
|
||||
HiveWE is a Warcraft III world editor. It focusses on speed and ease of use,
|
||||
especially for large maps where the regular World Editor is often too slow and clunky.
|
||||
It has a JASS editor with syntax hightlighting, tabs, code completion and more.
|
||||
It has a JASS editor with syntax highlighting, tabs, code completion and more.
|
||||
The JASS editor uses the Qt Advanced Docking System for the management and layout
|
||||
of the open editor windows.
|
||||
|
||||
@@ -478,3 +480,32 @@ PRE Workbench is a Python software and uses the ADS PyQt integration.
|
||||
[read more...](https://luelista.github.io/pre_workbench/)
|
||||
|
||||
[](https://youtu.be/U3op5UreV1Q)
|
||||
|
||||
## Alternative Docking System Implementations
|
||||
|
||||
If this Qt Advanced Docking System does not fit to your needs you may consider some of the alternative docking system solutions for Qt.
|
||||
|
||||
### KDDockWidgets
|
||||
|
||||
This is an advanced docking framework for Qt from [KDAB](https://www.kdab.com/). The interesting thing is, that they separated GUI code from logic, so they can easily provide a QtQuick backend in the future.
|
||||
|
||||
- [Blog post about KDDockWidgets](https://www.kdab.com/kddockwidgets/)
|
||||
- [GitHub project](https://github.com/KDAB/KDDockWidgets)
|
||||
|
||||
**License:** dual-licensed, available under both commercial and GPL license.
|
||||
|
||||
### QtitanDocking
|
||||
|
||||
This is a commercial component from [Developer Machines](https://www.devmachines.com/) for Qt Framework that allows to create a Microsoft like dockable user interface. They also offer a lot of other interesting and useful components for Qt. The library is available
|
||||
|
||||
- [Product page](https://www.devmachines.com/qtitandocking-overview.html)
|
||||
|
||||
**License:** Commercial license
|
||||
|
||||
### DockingPanes
|
||||
|
||||
DockingPanes is a library for Qt Widgets that implements docking windows that have the look and feel of Visual Studio. It provides a simple API which allows an application to make use of docking windows with a few calls.
|
||||
|
||||
- [GitHub project](https://github.com/KestrelRadarSensors/dockingpanes)
|
||||
|
||||
**License:** GPL
|
||||
|
||||
@@ -544,6 +544,14 @@ void MainWindowPrivate::createActions()
|
||||
_this->connect(a, SIGNAL(triggered()), SLOT(createEditor()));
|
||||
ui.menuTests->addAction(a);
|
||||
|
||||
a = ui.toolBar->addAction("Create Editor Tab");
|
||||
a->setProperty("Floating", false);
|
||||
a->setToolTip("Creates a editor tab and inserts it as second tab into an area");
|
||||
a->setIcon(svgIcon(":/adsdemo/images/tab.svg"));
|
||||
a->setProperty("Tabbed", true);
|
||||
_this->connect(a, SIGNAL(triggered()), SLOT(createEditor()));
|
||||
ui.menuTests->addAction(a);
|
||||
|
||||
a = ui.toolBar->addAction("Create Floating Table");
|
||||
a->setToolTip("Creates floating dynamic dockable table with millions of entries");
|
||||
a->setIcon(svgIcon(":/adsdemo/images/grid_on.svg"));
|
||||
@@ -663,11 +671,11 @@ CMainWindow::CMainWindow(QWidget *parent) :
|
||||
d->DockManager = new CDockManager(this);
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
connect(d->PerspectiveComboBox, SIGNAL(activated(const QString&)),
|
||||
d->DockManager, SLOT(openPerspective(const QString&)));
|
||||
connect(d->PerspectiveComboBox, SIGNAL(activated(QString)),
|
||||
d->DockManager, SLOT(openPerspective(QString)));
|
||||
#else
|
||||
connect(d->PerspectiveComboBox, SIGNAL(textActivated(const QString&)),
|
||||
d->DockManager, SLOT(openPerspective(const QString&)));
|
||||
connect(d->PerspectiveComboBox, SIGNAL(textActivated(QString)),
|
||||
d->DockManager, SLOT(openPerspective(QString)));
|
||||
#endif
|
||||
|
||||
d->createContent();
|
||||
@@ -769,6 +777,8 @@ void CMainWindow::createEditor()
|
||||
QObject* Sender = sender();
|
||||
QVariant vFloating = Sender->property("Floating");
|
||||
bool Floating = vFloating.isValid() ? vFloating.toBool() : true;
|
||||
QVariant vTabbed = Sender->property("Tabbed");
|
||||
bool Tabbed = vTabbed.isValid() ? vTabbed.toBool() : true;
|
||||
auto DockWidget = d->createEditorWidget();
|
||||
DockWidget->setFeature(ads::CDockWidget::DockWidgetDeleteOnClose, true);
|
||||
DockWidget->setFeature(ads::CDockWidget::DockWidgetForceCloseWithArea, true);
|
||||
@@ -780,31 +790,38 @@ void CMainWindow::createEditor()
|
||||
FloatingWidget->move(QPoint(20, 20));
|
||||
d->LastCreatedFloatingEditor = DockWidget;
|
||||
d->LastDockedEditor.clear();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ads::CDockAreaWidget* EditorArea = d->LastDockedEditor ? d->LastDockedEditor->dockAreaWidget() : nullptr;
|
||||
if (EditorArea)
|
||||
{
|
||||
std::cout << "DockAreaCount before: " << EditorArea->dockContainer()->dockAreaCount() << std::endl;
|
||||
d->DockManager->setConfigFlag(ads::CDockManager::EqualSplitOnInsertion, true);
|
||||
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget, EditorArea);
|
||||
std::cout << "DockAreaCount after: " << DockWidget->dockContainer()->dockAreaCount() << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d->LastCreatedFloatingEditor)
|
||||
{
|
||||
std::cout << "LastCreated" << std::endl;
|
||||
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget, d->LastCreatedFloatingEditor->dockAreaWidget());
|
||||
}
|
||||
else
|
||||
{
|
||||
d->DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);
|
||||
}
|
||||
}
|
||||
d->LastDockedEditor = DockWidget;
|
||||
}
|
||||
|
||||
|
||||
ads::CDockAreaWidget* EditorArea = d->LastDockedEditor ? d->LastDockedEditor->dockAreaWidget() : nullptr;
|
||||
if (EditorArea)
|
||||
{
|
||||
if (Tabbed)
|
||||
{
|
||||
// Test inserting the dock widget tab at a given position instead
|
||||
// of appending it. This function inserts the new dock widget as
|
||||
// first tab
|
||||
d->DockManager->addDockWidgetTabToArea(DockWidget, EditorArea, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
d->DockManager->setConfigFlag(ads::CDockManager::EqualSplitOnInsertion, true);
|
||||
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget, EditorArea);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d->LastCreatedFloatingEditor)
|
||||
{
|
||||
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget, d->LastCreatedFloatingEditor->dockAreaWidget());
|
||||
}
|
||||
else
|
||||
{
|
||||
d->DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);
|
||||
}
|
||||
}
|
||||
d->LastDockedEditor = DockWidget;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,5 +17,6 @@
|
||||
<file>images/create_floating_editor.svg</file>
|
||||
<file>images/create_floating_table.svg</file>
|
||||
<file>images/docked_editor.svg</file>
|
||||
<file>images/tab.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
6
demo/images/tab.svg
Normal file
6
demo/images/tab.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024">
|
||||
<desc>tab icon - Licensed under Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - Created with Iconfu.com - Derivative work of Material icons (Copyright Google Inc.)</desc>
|
||||
<g fill="#03b8e5" fill-rule="nonzero" style="mix-blend-mode: normal">
|
||||
<path d="M981.33,213.33v597.34c0,46.93 -38.4,85.33 -85.33,85.33h-768c-46.93,0 -85.33,-38.4 -85.33,-85.33v-597.34c0,-46.93 38.4,-85.33 85.33,-85.33h768c46.93,0 85.33,38.4 85.33,85.33zM896,384h-341.33v-170.67h-426.67v597.34h768z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 628 B |
BIN
doc/showcase_d-tect-x.png
Normal file
BIN
doc/showcase_d-tect-x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 489 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 539 KiB After Width: | Height: | Size: 529 KiB |
@@ -47,7 +47,7 @@
|
||||
## Configuration Flags
|
||||
|
||||
The Advanced Docking System has a number of global configuration options to
|
||||
configure the design and the functionality of the docking system. Eachs
|
||||
configure the design and the functionality of the docking system. Each
|
||||
configuration will be explained in detail in the following sections.
|
||||
|
||||
### Setting Configuration Flags
|
||||
@@ -67,9 +67,9 @@ d->DockManager = new CDockManager(this);
|
||||
If you set the configurations flags, you can set individual flags using the
|
||||
function `CDockManager::setConfigFlag` or you can set all flags using
|
||||
the function `CDockManager::setConfigFlags`. Instead of settings all
|
||||
flags individualy, it is better to pick a predefined set of configuration
|
||||
flags individually, it is better to pick a predefined set of configuration
|
||||
flags and then modify individual flags. The following predefined
|
||||
configurations are avilable
|
||||
configurations are available
|
||||
|
||||
- `DefaultNonOpaqueConfig` - uses non opaque splitter resizing and non opaque docking
|
||||
- `DefaultOpaqueConfig` - uses opaque splitter resizing and opaque docking
|
||||
@@ -160,11 +160,11 @@ constant, that means, if enabled, the tabs need more space.
|
||||
|
||||
### `OpaqueUndocking`
|
||||
|
||||
If this flag is set, opaque undocking is active. That means, as soon as you drag a dock widget or a dock area with a number of dock widgets it will be undocked and moved into a floating widget and then the floating widget will be dragged around. That means undocking will take place immediatelly. You can compare this with opaque splitter resizing.
|
||||
If this flag is set, opaque undocking is active. That means, as soon as you drag a dock widget or a dock area with a number of dock widgets it will be undocked and moved into a floating widget and then the floating widget will be dragged around. That means undocking will take place immediately. You can compare this with opaque splitter resizing.
|
||||
|
||||

|
||||
|
||||
If you would like to test opaque undocking, you should set the pedefined config
|
||||
If you would like to test opaque undocking, you should set the predefined config
|
||||
flags `CDockManager::DefaultOpaqueConfig`.
|
||||
|
||||
```c++
|
||||
@@ -287,7 +287,8 @@ current dock widget.
|
||||
|
||||

|
||||
|
||||
otherwise it displays application name as window title.
|
||||
otherwise it displays the title set with `CDockManager::setFloatingContainersTitle` or
|
||||
application name as window title.
|
||||
|
||||

|
||||
|
||||
@@ -323,7 +324,7 @@ still has a titlebar to drag it out of the main window.
|
||||
|
||||
If this is enabled, the docking system is able to highlight the tab and the
|
||||
components of a dock area with a different style (i.e. a different color).
|
||||
This option is disabled by default and needs to be enabled explicitely
|
||||
This option is disabled by default and needs to be enabled explicitly
|
||||
because it adds some overhead. The dock manager needs to react on focus
|
||||
changes and dock widget dragging to highlight the right dock widget. You should
|
||||
enable it only, if you really need it for your application.
|
||||
@@ -343,7 +344,7 @@ be set to true and you can use this property to style the focused dock
|
||||
widget differently. The picture above uses the following styling:
|
||||
|
||||
```css
|
||||
/* Color the tab with the nhighlight color */
|
||||
/* Color the tab with the highlight color */
|
||||
ads--CDockWidgetTab[focused="true"]
|
||||
{
|
||||
background: palette(highlight);
|
||||
@@ -625,3 +626,4 @@ just call the function for settings the stylesheet with an empty string.
|
||||
```c++
|
||||
DockManager->setStyleSheet("");
|
||||
```
|
||||
|
||||
|
||||
@@ -206,11 +206,15 @@ void DockInDockWidget::fillPerspectivesMenu( QMenu* menu )
|
||||
if ( !perspectiveNames.isEmpty() )
|
||||
{
|
||||
QMenu* load = menu->addMenu( "Load perspective" );
|
||||
for ( auto name : perspectiveNames )
|
||||
load->addAction( new LoadPerspectiveAction( load, name, *this ) );
|
||||
for (const auto& name : perspectiveNames)
|
||||
{
|
||||
load->addAction(new LoadPerspectiveAction( load, name, *this));
|
||||
}
|
||||
QMenu* remove = menu->addMenu( "Remove perspective" );
|
||||
for ( auto name : perspectiveNames )
|
||||
remove->addAction( new RemovePerspectiveAction( remove, name, *this ) );
|
||||
for (const auto& name : perspectiveNames)
|
||||
{
|
||||
remove->addAction( new RemovePerspectiveAction( remove, name, *this ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -219,8 +219,10 @@ void PerspectivesManager::loadPerspectives()
|
||||
|
||||
// load group info:
|
||||
mainSettings->beginGroup(GROUP_PREFIX);
|
||||
for ( auto key : mainSettings->allKeys() )
|
||||
for (const auto& key : mainSettings->allKeys())
|
||||
{
|
||||
m_perspectives[perspective].groups[key] = mainSettings->value( key ).toStringList();
|
||||
}
|
||||
mainSettings->endGroup();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(QtAdvancedDockingSystem LANGUAGES CXX VERSION ${VERSION_SHORT})
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Widgets REQUIRED)
|
||||
if (UNIX AND NOT APPLE)
|
||||
include_directories(${Qt${QT_VERSION_MAJOR}Gui_PRIVATE_INCLUDE_DIRS})
|
||||
endif()
|
||||
@@ -67,11 +67,12 @@ add_library(ads::qtadvanceddocking ALIAS qtadvanceddocking)
|
||||
target_link_libraries(qtadvanceddocking PUBLIC Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::Gui
|
||||
Qt${QT_VERSION_MAJOR}::Widgets)
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_link_libraries(qtadvanceddocking PUBLIC xcb)
|
||||
endif()
|
||||
set_target_properties(qtadvanceddocking PROPERTIES
|
||||
AUTOMOC ON
|
||||
AUTORCC ON
|
||||
CXX_STANDARD 14
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
CXX_EXTENSIONS OFF
|
||||
VERSION ${VERSION_SHORT}
|
||||
EXPORT_NAME "qtadvanceddocking"
|
||||
@@ -79,6 +80,16 @@ set_target_properties(qtadvanceddocking PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/bin"
|
||||
)
|
||||
if(QT_VERSION_MAJOR STREQUAL "5")
|
||||
set_target_properties(qtadvanceddocking PROPERTIES
|
||||
CXX_STANDARD 14
|
||||
CXX_STANDARD_REQUIRED ON)
|
||||
elseif(QT_VERSION_MAJOR STREQUAL "6")
|
||||
set_target_properties(qtadvanceddocking PROPERTIES
|
||||
CXX_STANDARD 17
|
||||
CXX_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
write_basic_package_version_file(
|
||||
"qtadvanceddockingConfigVersion.cmake"
|
||||
|
||||
@@ -203,7 +203,7 @@ void CDockAreaTabBar::insertTab(int Index, CDockWidgetTab* Tab)
|
||||
connect(Tab, SIGNAL(clicked()), this, SLOT(onTabClicked()));
|
||||
connect(Tab, SIGNAL(closeRequested()), this, SLOT(onTabCloseRequested()));
|
||||
connect(Tab, SIGNAL(closeOtherTabsRequested()), this, SLOT(onCloseOtherTabsRequested()));
|
||||
connect(Tab, SIGNAL(moved(const QPoint&)), this, SLOT(onTabWidgetMoved(const QPoint&)));
|
||||
connect(Tab, SIGNAL(moved(QPoint)), this, SLOT(onTabWidgetMoved(QPoint)));
|
||||
connect(Tab, SIGNAL(elidedChanged(bool)), this, SIGNAL(elidedChanged(bool)));
|
||||
Tab->installEventFilter(this);
|
||||
Q_EMIT tabInserted(Index);
|
||||
|
||||
@@ -390,7 +390,13 @@ void CDockAreaTitleBar::onTabsMenuActionTriggered(QAction* Action)
|
||||
//============================================================================
|
||||
void CDockAreaTitleBar::updateDockWidgetActionsButtons()
|
||||
{
|
||||
CDockWidget* DockWidget = d->TabBar->currentTab()->dockWidget();
|
||||
auto Tab = d->TabBar->currentTab();
|
||||
if (!Tab)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CDockWidget* DockWidget = Tab->dockWidget();
|
||||
if (!d->DockWidgetActionsButtons.isEmpty())
|
||||
{
|
||||
for (auto Button : d->DockWidgetActionsButtons)
|
||||
|
||||
@@ -416,6 +416,10 @@ void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget)
|
||||
void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
|
||||
bool Activate)
|
||||
{
|
||||
if (index < 0 || index > d->ContentsLayout->count())
|
||||
{
|
||||
index = d->ContentsLayout->count();
|
||||
}
|
||||
d->ContentsLayout->insertWidget(index, DockWidget);
|
||||
DockWidget->setDockArea(this);
|
||||
DockWidget->tabWidget()->setDockAreaWidget(this);
|
||||
@@ -448,6 +452,11 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
|
||||
void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
|
||||
{
|
||||
ADS_PRINT("CDockAreaWidget::removeDockWidget");
|
||||
if (!DockWidget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto CurrentDockWidget = currentDockWidget();
|
||||
auto NextOpenDockWidget = (DockWidget == CurrentDockWidget) ? nextOpenDockWidget(DockWidget) : nullptr;
|
||||
|
||||
@@ -1001,7 +1010,7 @@ bool CDockAreaWidget::isCentralWidgetArea() const
|
||||
return false;
|
||||
}
|
||||
|
||||
return dockManager()->centralWidget() == dockWidgets()[0];
|
||||
return dockManager()->centralWidget() == dockWidgets().constFirst();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
* Adds dock widget to a existing DockWidgetArea
|
||||
*/
|
||||
CDockAreaWidget* addDockWidgetToDockArea(DockWidgetArea area, CDockWidget* Dockwidget,
|
||||
CDockAreaWidget* TargetDockArea);
|
||||
CDockAreaWidget* TargetDockArea, int Index = -1);
|
||||
|
||||
/**
|
||||
* Add dock area to this container
|
||||
@@ -568,7 +568,6 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
|
||||
}
|
||||
else
|
||||
{
|
||||
QList<int> NewSplitterSizes;
|
||||
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
|
||||
int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
|
||||
bool AdjustSplitterSizes = true;
|
||||
@@ -692,7 +691,6 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg
|
||||
}
|
||||
else
|
||||
{
|
||||
auto Sizes = TargetAreaSplitter->sizes();
|
||||
int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
|
||||
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
|
||||
NewSplitter->addWidget(TargetArea);
|
||||
@@ -1228,11 +1226,11 @@ void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget)
|
||||
|
||||
//============================================================================
|
||||
CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetArea area,
|
||||
CDockWidget* Dockwidget, CDockAreaWidget* TargetDockArea)
|
||||
CDockWidget* Dockwidget, CDockAreaWidget* TargetDockArea, int Index)
|
||||
{
|
||||
if (CenterDockWidgetArea == area)
|
||||
{
|
||||
TargetDockArea->addDockWidget(Dockwidget);
|
||||
TargetDockArea->insertDockWidget(Index, Dockwidget);
|
||||
TargetDockArea->updateTitleBarVisibility();
|
||||
return TargetDockArea;
|
||||
}
|
||||
@@ -1315,7 +1313,7 @@ CDockContainerWidget::~CDockContainerWidget()
|
||||
|
||||
//============================================================================
|
||||
CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
|
||||
CDockAreaWidget* DockAreaWidget)
|
||||
CDockAreaWidget* DockAreaWidget, int Index)
|
||||
{
|
||||
CDockAreaWidget* OldDockArea = Dockwidget->dockAreaWidget();
|
||||
if (OldDockArea)
|
||||
@@ -1326,7 +1324,7 @@ CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockW
|
||||
Dockwidget->setDockManager(d->DockManager);
|
||||
if (DockAreaWidget)
|
||||
{
|
||||
return d->addDockWidgetToDockArea(area, Dockwidget, DockAreaWidget);
|
||||
return d->addDockWidgetToDockArea(area, Dockwidget, DockAreaWidget, Index);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
* \return Returns the dock area widget that contains the new DockWidget
|
||||
*/
|
||||
CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
|
||||
CDockAreaWidget* DockAreaWidget = nullptr);
|
||||
CDockAreaWidget* DockAreaWidget = nullptr, int Index = -1);
|
||||
|
||||
/**
|
||||
* Removes dockwidget
|
||||
|
||||
@@ -42,7 +42,7 @@ struct DockFocusControllerPrivate
|
||||
CDockFocusController *_this;
|
||||
QPointer<CDockWidget> FocusedDockWidget = nullptr;
|
||||
QPointer<CDockAreaWidget> FocusedArea = nullptr;
|
||||
CDockWidget* OldFocusedDockWidget = nullptr;
|
||||
QPointer<CDockWidget> OldFocusedDockWidget = nullptr;
|
||||
#ifdef Q_OS_LINUX
|
||||
QPointer<CFloatingDockContainer> FloatingWidget = nullptr;
|
||||
#endif
|
||||
@@ -264,7 +264,7 @@ void CDockFocusController::onFocusWindowChanged(QWindow *focusWindow)
|
||||
//===========================================================================
|
||||
void CDockFocusController::onApplicationFocusChanged(QWidget* focusedOld, QWidget* focusedNow)
|
||||
{
|
||||
Q_UNUSED(focusedOld);
|
||||
Q_UNUSED(focusedOld);
|
||||
|
||||
if (d->DockManager->isRestoringState())
|
||||
{
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <QSettings>
|
||||
#include <QMenu>
|
||||
#include <QApplication>
|
||||
#include <QWindow>
|
||||
|
||||
#include "FloatingDockContainer.h"
|
||||
#include "DockOverlay.h"
|
||||
@@ -91,6 +92,8 @@ enum eStateFileVersion
|
||||
|
||||
static CDockManager::ConfigFlags StaticConfigFlags = CDockManager::DefaultNonOpaqueConfig;
|
||||
|
||||
static QString FloatingContainersTitle;
|
||||
|
||||
/**
|
||||
* Private data class of CDockManager class (pimpl)
|
||||
*/
|
||||
@@ -500,6 +503,16 @@ CDockManager::CDockManager(QWidget *parent) :
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
window()->installEventFilter(this);
|
||||
|
||||
connect(qApp, &QApplication::focusWindowChanged, [](QWindow* focusWindow)
|
||||
{
|
||||
// bring modal dialogs to foreground to ensure that they are in front of any
|
||||
// floating dock widget
|
||||
if (focusWindow && focusWindow->isModal())
|
||||
{
|
||||
focusWindow->raise();
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -829,11 +842,11 @@ void CDockManager::restoreHiddenFloatingWidgets()
|
||||
|
||||
//============================================================================
|
||||
CDockAreaWidget* CDockManager::addDockWidget(DockWidgetArea area,
|
||||
CDockWidget* Dockwidget, CDockAreaWidget* DockAreaWidget)
|
||||
CDockWidget* Dockwidget, CDockAreaWidget* DockAreaWidget, int Index)
|
||||
{
|
||||
d->DockWidgetsMap.insert(Dockwidget->objectName(), Dockwidget);
|
||||
auto Container = DockAreaWidget ? DockAreaWidget->dockContainer(): this;
|
||||
auto AreaOfAddedDockWidget = Container->addDockWidget(area, Dockwidget, DockAreaWidget);
|
||||
auto AreaOfAddedDockWidget = Container->addDockWidget(area, Dockwidget, DockAreaWidget, Index);
|
||||
Q_EMIT dockWidgetAdded(Dockwidget);
|
||||
return AreaOfAddedDockWidget;
|
||||
}
|
||||
@@ -867,9 +880,9 @@ CDockAreaWidget* CDockManager::addDockWidgetTab(DockWidgetArea area,
|
||||
|
||||
//============================================================================
|
||||
CDockAreaWidget* CDockManager::addDockWidgetTabToArea(CDockWidget* Dockwidget,
|
||||
CDockAreaWidget* DockAreaWidget)
|
||||
CDockAreaWidget* DockAreaWidget, int Index)
|
||||
{
|
||||
return addDockWidget(ads::CenterDockWidgetArea, Dockwidget, DockAreaWidget);
|
||||
return addDockWidget(ads::CenterDockWidgetArea, Dockwidget, DockAreaWidget, Index);
|
||||
}
|
||||
|
||||
|
||||
@@ -915,7 +928,7 @@ void CDockManager::removePerspective(const QString& Name)
|
||||
void CDockManager::removePerspectives(const QStringList& Names)
|
||||
{
|
||||
int Count = 0;
|
||||
for (auto Name : Names)
|
||||
for (const auto& Name : Names)
|
||||
{
|
||||
Count += d->Perspectives.remove(Name);
|
||||
}
|
||||
@@ -1244,6 +1257,21 @@ CDockFocusController* CDockManager::dockFocusController() const
|
||||
return d->FocusController;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void CDockManager::setFloatingContainersTitle(const QString& Title)
|
||||
{
|
||||
FloatingContainersTitle = Title;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
QString CDockManager::floatingContainersTitle()
|
||||
{
|
||||
if (FloatingContainersTitle.isEmpty())
|
||||
return qApp->applicationDisplayName();
|
||||
|
||||
return FloatingContainersTitle;
|
||||
}
|
||||
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -186,7 +186,7 @@ public:
|
||||
DockAreaHasTabsMenuButton = 0x8000, //!< If the flag is set each dock area has a tabs menu button
|
||||
DockAreaHideDisabledButtons = 0x10000, //!< If the flag is set disabled dock area buttons will not appear on the toolbar at all (enabling them will bring them back)
|
||||
DockAreaDynamicTabsMenuButtonVisibility = 0x20000, //!< If the flag is set, the tabs menu button will be shown only when it is required - that means, if the tabs are elided. If the tabs are not elided, it is hidden
|
||||
FloatingContainerHasWidgetTitle = 0x40000, //!< If set, the Floating Widget window title reflects the title of the current dock widget otherwise it displays application name as window title
|
||||
FloatingContainerHasWidgetTitle = 0x40000, //!< If set, the Floating Widget window title reflects the title of the current dock widget otherwise it displays the title set with `CDockManager::setFloatingContainersTitle` or application name as window title
|
||||
FloatingContainerHasWidgetIcon = 0x80000, //!< If set, the Floating Widget icon reflects the icon of the current dock widget otherwise it displays application icon
|
||||
HideSingleCentralWidgetTitleBar = 0x100000, //!< If there is only one single visible dock widget in the main dock container (the dock manager) and if this flag is set, then the titlebar of this dock widget will be hidden
|
||||
//!< this only makes sense for non draggable and non floatable widgets and enables the creation of some kind of "central" widget
|
||||
@@ -281,7 +281,7 @@ public:
|
||||
* \return Returns the dock area widget that contains the new DockWidget
|
||||
*/
|
||||
CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
|
||||
CDockAreaWidget* DockAreaWidget = nullptr);
|
||||
CDockAreaWidget* DockAreaWidget = nullptr, int Index = -1);
|
||||
|
||||
/**
|
||||
* Adds dockwidget into the given container.
|
||||
@@ -304,9 +304,11 @@ public:
|
||||
/**
|
||||
* This function will add the given Dockwidget to the given DockAreaWidget
|
||||
* as a new tab.
|
||||
* If index is out of range, the tab is simply appended. Otherwise it is
|
||||
* inserted at the specified position.
|
||||
*/
|
||||
CDockAreaWidget* addDockWidgetTabToArea(CDockWidget* Dockwidget,
|
||||
CDockAreaWidget* DockAreaWidget);
|
||||
CDockAreaWidget* DockAreaWidget, int Index = -1);
|
||||
|
||||
/**
|
||||
* Adds the given DockWidget floating and returns the created
|
||||
@@ -528,6 +530,21 @@ public:
|
||||
*/
|
||||
void setSplitterSizes(CDockAreaWidget *ContainedArea, const QList<int>& sizes);
|
||||
|
||||
/**
|
||||
* Set a custom title for all FloatingContainer that does not reflect
|
||||
* the title of the current dock widget.
|
||||
*/
|
||||
static void setFloatingContainersTitle(const QString& Title);
|
||||
|
||||
/**
|
||||
* Returns the title used by all FloatingContainer that does not
|
||||
* reflect the title of the current dock widget.
|
||||
*
|
||||
* If not title was set with setFloatingContainersTitle(), it returns
|
||||
* QGuiApplication::applicationDisplayName().
|
||||
*/
|
||||
static QString floatingContainersTitle();
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* Opens the perspective with the given name.
|
||||
|
||||
@@ -431,6 +431,7 @@ DockWidgetArea CDockOverlay::showOverlay(QWidget* target)
|
||||
d->LastLocation = InvalidDockWidgetArea;
|
||||
|
||||
// Move it over the target.
|
||||
hide();
|
||||
resize(target->size());
|
||||
QPoint TopLeft = target->mapToGlobal(target->rect().topLeft());
|
||||
move(TopLeft);
|
||||
|
||||
@@ -433,7 +433,7 @@ struct FloatingDockContainerPrivate
|
||||
}
|
||||
else
|
||||
{
|
||||
setWindowTitle(qApp->applicationDisplayName());
|
||||
setWindowTitle(floatingContainersTitle());
|
||||
}
|
||||
|
||||
// reflect CurrentWidget's icon if configured to do so, otherwise display application icon as window icon
|
||||
@@ -453,6 +453,18 @@ struct FloatingDockContainerPrivate
|
||||
* Handles escape key press when dragging around the floating widget
|
||||
*/
|
||||
void handleEscapeKey();
|
||||
|
||||
/**
|
||||
* Returns the title used by all FloatingContainer that does not
|
||||
* reflect the title of the current dock widget.
|
||||
*
|
||||
* If not title was set with CDockManager::setFloatingContainersTitle(),
|
||||
* it returns QGuiApplication::applicationDisplayName().
|
||||
*/
|
||||
static QString floatingContainersTitle()
|
||||
{
|
||||
return CDockManager::floatingContainersTitle();
|
||||
}
|
||||
};
|
||||
// struct FloatingDockContainerPrivate
|
||||
|
||||
@@ -515,6 +527,15 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// Prevent display of drop overlays and docking as long as a model dialog
|
||||
// is active
|
||||
if (qApp->activeModalWidget())
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto Containers = DockManager->dockContainers();
|
||||
CDockContainerWidget *TopContainer = nullptr;
|
||||
for (auto ContainerWidget : Containers)
|
||||
@@ -976,7 +997,7 @@ void CFloatingDockContainer::onDockAreasAddedOrRemoved()
|
||||
SLOT(onDockAreaCurrentChanged(int)));
|
||||
d->SingleDockArea = nullptr;
|
||||
}
|
||||
d->setWindowTitle(qApp->applicationDisplayName());
|
||||
d->setWindowTitle(d->floatingContainersTitle());
|
||||
setWindowIcon(QApplication::windowIcon());
|
||||
}
|
||||
}
|
||||
@@ -1003,7 +1024,7 @@ void CFloatingDockContainer::updateWindowTitle()
|
||||
}
|
||||
else
|
||||
{
|
||||
d->setWindowTitle(qApp->applicationDisplayName());
|
||||
d->setWindowTitle(d->floatingContainersTitle());
|
||||
setWindowIcon(QApplication::windowIcon());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user