View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0017432 | Scribus | User Interface | public | 2025-02-28 10:13 | 2026-07-08 17:19 |
| Reporter | ale | Assigned To | nitramr | ||
| Priority | normal | Severity | minor | Reproducibility | always |
| Status | resolved | Resolution | fixed | ||
| Product Version | 1.7.1.svn | ||||
| Fixed in Version | 1.7.4.svn | ||||
| Summary | 0017432: Getting Qt-Advanced-Docking-System to work correctly with tiling window managers | ||||
| Description | on my computer, with dwm, once a palette is made floating: - it does not behave well - the only way to dock it again is to remove the scribus settings. i got to test scribus with sway in x11 mode and it's somehow ok, but also not really good. one difference is that sway shows a title on top of the floating palette, dwm never add a title bar (but shows it when it's there, like in the older scribus palettes). i have to do some further tests, but it seems that we need to find a way to add the title bar and to correctly the palette as floating. my first tests with the ADS demo programs show the same issues as in scribus. | ||||
| Tags | No tags attached. | ||||
| Patch | No | ||||
|
|
I replaced the Qt-Advanced-Docking System with KDDockWidgets. Steps 1. Download KDDockWidgets from https://github.com/KDAB/KDDockWidgets 2. Put the root folder into scribus -> third_party 3. Check if the root folders name is "KDDockWidgets" 4. Apply the fix below If you want to test it under Wayland modify the main_nix.cpp in scribus folder Remove the following code: ``` #if !defined(Q_OS_MACOS) qputenv("QT_QPA_PLATFORM", "xcb"); #endif if (QApplication::platformName() == "wayland") { QString errHdr = QObject::tr("Fatal Error"); QString errMsg = QObject::tr("Scribus does not support the Wayland platform. Use XWayland to run Scribus on Wayland. Scribus will close now."); if (app.useGUI) { QMessageBox::critical(nullptr, errHdr, errMsg); } else { std::cout << errHdr.toStdString() << std::endl; std::cout << "-------------" << std::endl; std::cout << errMsg.toStdString() << std::endl; } return EXIT_FAILURE; } ``` kddock_2025-10-31_01.patch (47,965 bytes)
Index: CMakeLists_Dependencies.cmake
===================================================================
--- CMakeLists_Dependencies.cmake (Revision 27098)
+++ CMakeLists_Dependencies.cmake (Arbeitskopie)
@@ -317,7 +317,3 @@
message("Harfbuzz subset library Found OK")
set (HAVE_HARFBUZZ_SUBSET ON)
endif()
-
-#if(WANT_QTADS)
- set(HAVE_QTADS ON)
-#endif()
Index: config.h.cmake
===================================================================
--- config.h.cmake (Revision 27098)
+++ config.h.cmake (Arbeitskopie)
@@ -14,7 +14,6 @@
#cmakedefine BUILD_MAC_BUNDLE
#cmakedefine DLL_USE_NATIVE_API 1
#cmakedefine GMAGICK_FOUND 1
-#cmakedefine HAVE_QTADS 1
#cmakedefine HAVE_BOOST 1
#cmakedefine HAVE_CAIRO 1
#cmakedefine HAVE_CUPS 1
Index: scribus/CMakeLists.txt
===================================================================
--- scribus/CMakeLists.txt (Revision 27098)
+++ scribus/CMakeLists.txt (Arbeitskopie)
@@ -59,11 +59,10 @@
set_property(SOURCE third_party/fparser/file.hh PROPERTY SKIP_AUTOGEN ON)
set_property(SOURCE third_party/fparser/fparser.hh PROPERTY SKIP_AUTOGEN ON)
-#if(WANT_QTADS)
- MESSAGE(STATUS "Qt Advanced Docking System included")
- link_directories(${CMAKE_CURRENT_BINARY_DIR}/third_party/Qt-Advanced-Docking-System)
-#endif()
+MESSAGE(STATUS "KDDock System included")
+link_directories(${CMAKE_CURRENT_BINARY_DIR}/third_party/KDDockWidgets)
+
link_directories(
${CMAKE_CURRENT_BINARY_DIR}/third_party/wpg
${CMAKE_CURRENT_BINARY_DIR}/third_party/pgf
@@ -292,9 +291,7 @@
${SCRIBUS_RTF_LIB}
)
-#if(WANT_QTADS)
- target_link_libraries(${EXE_NAME} PUBLIC qt6advanceddocking)
-#endif()
+target_link_libraries(${EXE_NAME} PUBLIC KDAB::kddockwidgets)
if(WITH_TESTS)
target_link_libraries(${EXE_NAME} PRIVATE
Index: scribus/manager/dock_manager.cpp
===================================================================
--- scribus/manager/dock_manager.cpp (Revision 27098)
+++ scribus/manager/dock_manager.cpp (Arbeitskopie)
@@ -26,12 +26,12 @@
#include "dock_manager.h"
#include <QMenu>
-#include "third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.h"
#include "ui/docks/dock_centralwidget.h"
#include "iconmanager.h"
#include "prefsmanager.h"
#include "scribusapp.h"
+#include "scribus.h"
#include "ui/aligndistribute.h"
#include "ui/bookmarkpalette.h"
#include "ui/contentpalette.h"
@@ -44,7 +44,9 @@
#include "ui/symbolpalette.h"
#include "undogui.h"
+#include <kddockwidgets/LayoutSaver.h>
+
/* ********************************************************************************* *
*
* Constructor + Setup
@@ -51,31 +53,29 @@
*
* ********************************************************************************* */
-DockManager::DockManager(QWidget *parent)
- : CDockManager(parent)
+DockManager::DockManager(ScribusMainWindow *mainwindow)
+ : QObject(mainwindow)
{
- dockCenter = new DockCentralWidget();
- auto *areaCenter = CDockManager::setCentralWidget(dockCenter);
- areaCenter->setAllowedAreas(LeftDockWidgetArea | RightDockWidgetArea);
+ dockCenter = new DockCentralWidget();
+ m_mainwindow = mainwindow;
+ m_mainwindow->setPersistentCentralWidget(dockCenter);
- setStyleSheet(""); // reset style sheet to use custom icons
-
connect( ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()) );
}
void DockManager::setupDocks()
{
- pagePalette = new PagePalette((QWidget *) this->parent());
- contentPalette = new ContentPalette(this);
- propertiesPalette = new PropertiesPalette(this);
- outlinePalette = new OutlinePalette(this);
- layerPalette = new LayerPalette(this);
- inlinePalette = new InlinePalette(this);
+ pagePalette = new PagePalette();
+ contentPalette = new ContentPalette();
+ propertiesPalette = new PropertiesPalette();
+ outlinePalette = new OutlinePalette();
+ layerPalette = new LayerPalette();
+ inlinePalette = new InlinePalette();
alignDistributePalette = new AlignDistributePalette();
- scrapbookPalette = new Biblio(this);
- bookPalette = new BookPalette(this);
- undoPalette = new UndoPalette(this);
- symbolPalette = new SymbolPalette(this);
+ scrapbookPalette = new Biblio();
+ bookPalette = new BookPalette();
+ undoPalette = new UndoPalette();
+ symbolPalette = new SymbolPalette();
// Apply common configuration for each palette
configureDock(pagePalette);
@@ -111,38 +111,16 @@
void DockManager::initWorkspaces()
{
createDefaultWorkspace();
-// restoreWorkspaceFromPrefs();
}
-void DockManager::removeAllDockWidgets()
-{
- QMap<QString, CDockWidget *> map = dockWidgetsMap();
- foreach (QString key, map.keys())
- removeDockWidget(map.value(key));
-}
-void DockManager::hideAllDocks()
-{
- foreach (CDockWidget *dock, this->dockWidgets())
- {
- if(dock->isCentralWidget())
- continue;
- dock->closeDockWidget();
- }
-
- foreach (CFloatingDockContainer *dockContainer, this->floatingWidgets())
- {
- dockContainer->close();
- }
-}
-
void DockManager::toggleDocksVisibility()
{
- QString perspective = "_allpaletteshidden";
+ QString perspective = "e494294a-65b4-4ca5-a018-1fe741dbd1c3";
- if(perspectiveNames().contains(perspective))
+ if(m_perspectives.contains(perspective))
{
- openPerspective(perspective);
+ loadPerspective(perspective);
removePerspective(perspective);
m_dockTemporaryHidden = false;
}
@@ -149,11 +127,8 @@
else
{
addPerspective(perspective);
- hideAllDocks();
+ emit hideAllDocks();
m_dockTemporaryHidden = true;
-
-// qDebug() << Q_FUNC_INFO << this->dockWidgets();
-// qDebug() << Q_FUNC_INFO << this->floatingWidgets();
}
}
@@ -163,79 +138,57 @@
return m_dockTemporaryHidden;
}
-CDockAreaWidget *DockManager::addDockFromPlugin(CDockWidget *dock, bool closed)
+DockPanelBase *DockManager::addDockFromPlugin(DockPanelBase *dock, bool closed)
{
- CDockAreaWidget *a = addDockWidget(RightDockWidgetArea, dock, dockCenter->dockAreaWidget());
- dock->toggleView(!closed);
- updateIcon(dock);
configureDock(dock);
- return a;
+
+ m_mainwindow->addDockWidget(dock, KDDockWidgets::Location_OnLeft);
+
+ if (closed)
+ dock->close();
+ else
+ dock->open();
+
+ return dock;
}
void DockManager::restoreWorkspaceFromPrefs()
{
- QByteArray ba = PrefsManager::instance().appPrefs.uiPrefs.adsDockState;
+ QByteArray ba = QByteArray::fromHex(PrefsManager::instance().appPrefs.uiPrefs.adsDockState);
if(ba.isEmpty())
return;
- this->restoreState(ba);
+ KDDockWidgets::RestoreOptions options = KDDockWidgets::RestoreOption_None;
+
+ KDDockWidgets::LayoutSaver saver(options);
+ saver.restoreLayout(ba);
}
void DockManager::saveWorkspaceToPrefs()
{
- PrefsManager::instance().appPrefs.uiPrefs.adsDockState = this->saveState();
+ KDDockWidgets::LayoutSaver saver;
+ QByteArray data = saver.serializeLayout();
+
+ PrefsManager::instance().appPrefs.uiPrefs.adsDockState = data.toHex();
}
void DockManager::iconSetChange()
{
- // Update all icons of each docked CDockContainer
- updateIcons(this->dockWidgets());
- // Update all icons of each floating CFloatingDockContainer
- foreach (CFloatingDockContainer *dockContainer, this->floatingWidgets())
- updateIcons(dockContainer->dockWidgets());
}
void DockManager::restoreHiddenWorkspace()
{
- if (m_dockTemporaryHidden)
+ if (hasTemporaryHiddenDocks())
toggleDocksVisibility();
}
-void DockManager::updateIcons(QList<CDockWidget *> dockWidgets)
+void DockManager::configureDock(DockPanelBase *dock)
{
- foreach (CDockWidget *dock, dockWidgets)
- updateIcon(dock);
+ connect(this, &DockManager::hideAllDocks, dock, &DockPanelBase::close);
}
-void DockManager::updateIcon(CDockWidget *dockWidget)
-{
- IconManager &iconManager = IconManager::instance();
-
- dockWidget->dockAreaWidget()->titleBarButton(ads::TitleBarButtonClose)->setIcon(iconManager.loadIcon("close", 12));
- dockWidget->dockAreaWidget()->titleBarButton(ads::TitleBarButtonUndock)->setIcon(iconManager.loadIcon("dock-float", 16));
- dockWidget->dockAreaWidget()->titleBarButton(ads::TitleBarButtonTabsMenu)->setIcon(iconManager.loadIcon("menu-down", 16));
- dockWidget->dockAreaWidget()->titleBarButton(ads::TitleBarButtonAutoHide)->setIcon(iconManager.loadIcon("dock-auto-hide", 16));
- dockWidget->dockAreaWidget()->titleBarButton(ads::TitleBarButtonMinimize)->setIcon(iconManager.loadIcon("dock-minimize", 16));
-
- for (auto tabCloseButton : dockWidget->dockAreaWidget()->findChildren<QAbstractButton*>("tabCloseButton"))
- tabCloseButton->setIcon(iconManager.loadIcon("close", 12));
-}
-
-void DockManager::configureDock(CDockWidget *dock)
-{
- /*
- * MinimumSizeHintFromContent
- * MinimumSizeHintFromDockWidgetMinimumSize
- * MinimumSizeHintFromContentMinimumSize
- */
-
- dock->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidgetMinimumSize);
- dock->setMinimumWidth(dock->widget()->minimumSizeHint().width());
- connect( dock, &CDockWidget::viewToggled, this, &DockManager::restoreHiddenWorkspace);
-}
-
void DockManager::createDefaultWorkspace()
{
/************************************************************
@@ -257,56 +210,75 @@
*
*************************************************************/
- auto *areaCenter = dockCenter->dockAreaWidget();
+ const QSize m_preferredSize(QSize(290, 0));
+ KDDockWidgets::InitialOption hiddenPalette(KDDockWidgets::InitialVisibilityOption::StartHidden, m_preferredSize);
+ KDDockWidgets::InitialOption visiblePalette(KDDockWidgets::InitialVisibilityOption::StartVisible, m_preferredSize);
+ KDDockWidgets::InitialOption passivePalette(KDDockWidgets::InitialVisibilityOption::PreserveCurrentTab, m_preferredSize);
// Left
- auto *areaLeft = addDockWidget(LeftDockWidgetArea, pagePalette, areaCenter);
- addDockWidgetTabToArea(outlinePalette, areaLeft);
+ m_mainwindow->addDockWidget(pagePalette, KDDockWidgets::Location_OnLeft, nullptr, visiblePalette);
+ pagePalette->addDockWidgetAsTab(outlinePalette, hiddenPalette);
- // Left Center
- auto *areaCenterLeft = addDockWidget(LeftDockWidgetArea, inlinePalette, areaCenter);
- addDockWidgetTabToArea(scrapbookPalette, areaCenterLeft);
- addDockWidgetTabToArea(bookPalette, areaCenterLeft);
- addDockWidgetTabToArea(symbolPalette, areaCenterLeft);
+ // Left Center
+ // Workaround: inline palette acts as a main container for the other palettes, we have to show it so that it is docked.
+ m_mainwindow->addDockWidget(inlinePalette, KDDockWidgets::Location_OnRight, pagePalette, visiblePalette);
+ inlinePalette->addDockWidgetAsTab(scrapbookPalette, hiddenPalette);
+ inlinePalette->addDockWidgetAsTab(bookPalette, hiddenPalette);
+ inlinePalette->addDockWidgetAsTab(symbolPalette, hiddenPalette);
// Left Bottom
- auto *areaLeftBottom = addDockWidget(BottomDockWidgetArea, layerPalette, areaLeft);
- addDockWidgetTabToArea(alignDistributePalette, areaLeftBottom);
- addDockWidgetTabToArea(undoPalette, areaLeftBottom);
+ m_mainwindow->addDockWidget(alignDistributePalette, KDDockWidgets::Location_OnBottom, pagePalette, visiblePalette);
+ alignDistributePalette->addDockWidgetAsTab(layerPalette, hiddenPalette);
+ alignDistributePalette->addDockWidgetAsTab(undoPalette, hiddenPalette);
- // Right Panel
- auto *areaRight = addDockWidget(RightDockWidgetArea, propertiesPalette, areaCenter);
- addDockWidget(CenterDockWidgetArea, contentPalette, areaRight);
+ // Right
+ m_mainwindow->addDockWidget(propertiesPalette, KDDockWidgets::Location_OnRight, nullptr, visiblePalette);
+ propertiesPalette->addDockWidgetAsTab(contentPalette, passivePalette);
- // Top Panel
- // auto * areaTop = addDockWidget(TopDockWidgetArea, dockToolProperties);
- // areaTop->setAllowedAreas(NoDockWidgetArea);
- // areaTop->setDockAreaFlag(CDockAreaWidget::HideSingleWidgetTitleBar, true);
+ // Workaround: we have to hide inline palette manually.
+ inlinePalette->close();
- // Resizing area height of left and bottom-left
- int heightL = areaLeft->height();
- setSplitterSizes(areaLeft, {heightL * 3 / 4, heightL * 1 / 4});
+ // Set active palettes
+ // alignDistributePalette->setAsCurrentTab();
+ // pagePalette->setAsCurrentTab();
+ // propertiesPalette->setAsCurrentTab();
- // Resizing area width of left, center-left, center and right
- int widthCL = areaCenter->width();
- int panelWidth = 290;
- setSplitterSizes(areaCenter, {panelWidth, panelWidth, widthCL - 3 * panelWidth, panelWidth});
+ // Save Scribus Default
+ addPerspective("Default");
+ restoreWorkspaceFromPrefs();
- // hide panels that are not visible in default workspace
- inlinePalette->closeDockWidget();
- scrapbookPalette->closeDockWidget();
- bookPalette->closeDockWidget();
- symbolPalette->closeDockWidget();
- layerPalette->closeDockWidget();
- undoPalette->closeDockWidget();
- outlinePalette->closeDockWidget();
+ // Save Users Preference
+ addPerspective("Current");
- // active palettes
- areaLeft->setCurrentDockWidget(pagePalette);
- areaRight->setCurrentDockWidget(propertiesPalette);
- areaLeftBottom->setCurrentDockWidget(alignDistributePalette);
+}
- // add perspective for a later usage, like reset workspace to default.
- this->addPerspective("Default");
+
+void DockManager::addPerspective(const QString name)
+{
+ if (m_perspectives.contains(name))
+ return;
+
+ KDDockWidgets::LayoutSaver saver;
+ m_perspectives.insert(name, saver.serializeLayout());
}
+
+void DockManager::removePerspective(const QString name)
+{
+ if (m_perspectives.contains(name))
+ m_perspectives.remove(name);
+}
+
+void DockManager::loadPerspective(const QString name)
+{
+ KDDockWidgets::LayoutSaver saver;
+ saver.restoreLayout(perspectiveByName(name));
+}
+
+QByteArray DockManager::perspectiveByName(const QString name)
+{
+ if (!m_perspectives.contains(name))
+ return QByteArray();
+
+ return m_perspectives.value(name);
+}
Index: scribus/manager/dock_manager.h
===================================================================
--- scribus/manager/dock_manager.h (Revision 27098)
+++ scribus/manager/dock_manager.h (Arbeitskopie)
@@ -28,10 +28,9 @@
#include "prefscontext.h"
#include "scribusapi.h"
-#include "third_party/Qt-Advanced-Docking-System/src/DockManager.h"
+#include "ui/docks/dock_panelbase.h"
+#include <kddockwidgets/DockWidget.h>
-using namespace ads;
-
class ScribusMainWindow;
class PagePalette;
class OutlinePalette;
@@ -46,36 +45,36 @@
class SymbolPalette;
class DockCentralWidget;
-class SCRIBUS_API DockManager : public CDockManager
+class SCRIBUS_API DockManager : public QObject
{
Q_OBJECT
public:
- DockManager(QWidget *parent);
+ DockManager(ScribusMainWindow *mainwindow);
void setCentralWidget(QWidget *widget);
void setupDocks();
+
/**
* @brief Creates all preconfigured workspaces as perspectives.
*/
void initWorkspaces();
+
/**
- * @brief Removes all dock widgets including docks added by plugins.
- */
- void removeAllDockWidgets();
- /**
- * @brief Hides all docked and floating dock containers.
- */
- void hideAllDocks();
- /**
* @brief Toggles the temporary visibility of all docks.
*/
void toggleDocksVisibility();
+
+ void addPerspective(const QString name);
+ void removePerspective(const QString name);
+ void loadPerspective(const QString name);
+
/**
* @brief Returns true if all docks are temporary hidden.
* @return
*/
bool hasTemporaryHiddenDocks();
+
/**
* @brief Adds a dock widget to dock manager. Useful for docks that are not initialized by dock manager, e.g. from plugins.
* @param dock
@@ -82,7 +81,8 @@
* @param closed
* @return
*/
- CDockAreaWidget *addDockFromPlugin(CDockWidget *dock, bool closed = true);
+ DockPanelBase *addDockFromPlugin(DockPanelBase *dock, bool closed = true);
+ QByteArray perspectiveByName(const QString name);
PagePalette *pagePalette {nullptr};
OutlinePalette *outlinePalette {nullptr};
@@ -114,23 +114,20 @@
protected:
DockCentralWidget *dockCenter {nullptr};
+ ScribusMainWindow * m_mainwindow {nullptr};
bool m_dockTemporaryHidden {false};
- QMap<CDockWidget *, bool> m_temporaryHiddenDocks;
+ QMap<QString, QByteArray> m_perspectives;
- /**
- * @brief Refreshes all icons of a dock. Needed for icon set or GUI changes.
- * @param dockWidgets
- */
- void updateIcons(QList<CDockWidget *> dockWidgets);
- void updateIcon(CDockWidget * dockWidget);
+ void configureDock(DockPanelBase *dock);
- void configureDock(CDockWidget *dock);
-
/**
* @brief Creates a default workspace as perspective.
*/
void createDefaultWorkspace();
+signals:
+ void hideAllDocks();
+
};
#endif // DOCK_MANAGER_H
Index: scribus/plugins/shapes/shapepalette.cpp
===================================================================
--- scribus/plugins/shapes/shapepalette.cpp (Revision 27098)
+++ scribus/plugins/shapes/shapepalette.cpp (Arbeitskopie)
@@ -32,7 +32,6 @@
#include "scribusXml.h"
#include "selection.h"
#include "shapepalette.h"
-#include "third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.h"
#include "ui/scmessagebox.h"
#include "util.h"
#include "util_math.h"
@@ -280,7 +279,7 @@
}
}
-ShapePalette::ShapePalette(QWidget *parent) : DockPanelBase("Shap", "panel-custom-shapes", parent)
+ShapePalette::ShapePalette() : DockPanelBase("Shap", "panel-custom-shapes")
{
setMinimumSize( QSize( 220, 240 ) );
setObjectName(QString::fromLocal8Bit("Shap"));
Index: scribus/plugins/shapes/shapepalette.h
===================================================================
--- scribus/plugins/shapes/shapepalette.h (Revision 27098)
+++ scribus/plugins/shapes/shapepalette.h (Arbeitskopie)
@@ -91,7 +91,7 @@
Q_OBJECT
public:
- ShapePalette(QWidget *parent);
+ ShapePalette();
~ShapePalette() {};
void writeToPrefs();
Index: scribus/plugins/shapes/shapeplugin.cpp
===================================================================
--- scribus/plugins/shapes/shapeplugin.cpp (Revision 27098)
+++ scribus/plugins/shapes/shapeplugin.cpp (Arbeitskopie)
@@ -73,19 +73,10 @@
languageChange();
m_actions.insert("shapeShowPalette", new ScrAction(fullTrName(), QKeySequence(), this));
- // Use this if menu action is checkable
- // m_actions["shapeShowPalette"]->setToggleAction(true);
- // m_actions["shapeShowPalette"]->setChecked(false);
- // connect(m_actions["shapeShowPalette"], SIGNAL(toggled(bool)), sc_palette, SLOT(toggleView(bool)));
- // connect(sc_palette, SIGNAL(viewToggled(bool)), m_actions["shapeShowPalette"], SLOT(setChecked(bool)));
+ sc_palette->setToggleViewAction(m_actions["shapeShowPalette"]);
- // Use this if menu action is not checkable
- connect(m_actions["shapeShowPalette"], SIGNAL(triggered()), sc_palette, SLOT(toggleView()));
-
mw->scrMenuMgr->addMenuItemStringAfter("shapeShowPalette", "toolsInline", "Windows");
mw->scrMenuMgr->addMenuItemStringsToMenuBar("Windows", m_actions);
-
- // For some reason we can't call addDockWidget(...) directly. If we do so Scribus crashes.
mw->dockManager->addDockFromPlugin(sc_palette, false);
}
@@ -112,7 +103,7 @@
bool ShapePlugin::initPlugin()
{
- sc_palette = new ShapePalette(ScCore->primaryMainWindow());
+ sc_palette = new ShapePalette();
sc_palette->startup();
sc_palette->readFromPrefs();
return true;
Index: scribus/scribus.cpp
===================================================================
--- scribus/scribus.cpp (Revision 27098)
+++ scribus/scribus.cpp (Arbeitskopie)
@@ -247,8 +247,6 @@
#include "util.h"
#include "util_file.h"
#include "util_formats.h"
-#include "third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.h"
-#include "third_party/Qt-Advanced-Docking-System/src/IconProvider.h"
#ifdef HAVE_SVNVERSION
#include "svnversion.h"
@@ -268,7 +266,6 @@
#include "sclimits.h"
using namespace std;
-using namespace ads;
bool previewDinUse;
bool printDinUse;
@@ -275,6 +272,7 @@
extern bool emergencyActivated;
ScribusMainWindow::ScribusMainWindow() :
+ MainWindow("scribusmainwindow", KDDockWidgets::MainWindowOptions {KDDockWidgets::MainWindowOption_HasCentralWidget}, nullptr),
m_prefsManager(PrefsManager::instance()),
m_widgetManager(WidgetManager::instance())
{
@@ -292,37 +290,6 @@
*/
int ScribusMainWindow::initScMW(bool primaryMainWindow)
{
- // Documentation: https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/blob/master/doc/user-guide.md
- CDockManager::setConfigFlag(CDockManager::AlwaysShowTabs, false);
- CDockManager::setConfigFlag(CDockManager::FloatingContainerHasWidgetIcon, true);
- CDockManager::setConfigFlag(CDockManager::FloatingContainerHasWidgetTitle, true);
- CDockManager::setConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar, false);
- CDockManager::setConfigFlag(CDockManager::OpaqueSplitterResize, true);
- CDockManager::setConfigFlag(CDockManager::TabCloseButtonIsToolButton, true);
- CDockManager::setConfigFlag(CDockManager::AllTabsHaveCloseButton, false);
-// CDockManager::setConfigFlag(CDockManager::DockAreaDynamicTabsMenuButtonVisibility, true);
- CDockManager::setConfigFlag(CDockManager::DockAreaHasCloseButton, false);
- CDockManager::setConfigFlag(CDockManager::DockAreaHasUndockButton, false);
- CDockManager::setConfigFlag(CDockManager::DockAreaHideDisabledButtons, true);
- CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true);
- CDockManager::setConfigFlag(CDockManager::DisableTabTextEliding, true);
- CDockManager::setConfigFlag(CDockManager::ShowTabTextOnlyForActiveTab, !m_prefsManager.appPrefs.uiPrefs.showLabelsOfInactiveTabs);
-
- // Documentation: https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/blob/master/doc/user-guide.md#auto-hide-configuration-flags
- CDockManager::setAutoHideConfigFlags(CDockManager::DefaultAutoHideConfig);
-// CDockManager::setAutoHideConfigFlag(CDockManager::AutoHideShowOnMouseOver, false);
-// CDockManager::setAutoHideConfigFlag(CDockManager::AutoHideCloseButtonCollapsesDock, true);
-// CDockManager::setAutoHideConfigFlag(CDockManager::AutoHideButtonTogglesArea, true);
- CDockManager::setAutoHideConfigFlag(CDockManager::DockAreaHasAutoHideButton, true);
-
- IconManager &iconmanager = IconManager::instance();
- CDockManager::iconProvider().registerCustomIcon(TabCloseIcon, iconmanager.loadIcon("close", 12));
- CDockManager::iconProvider().registerCustomIcon(DockAreaCloseIcon, iconmanager.loadIcon("close", 12));
- CDockManager::iconProvider().registerCustomIcon(DockAreaMenuIcon, iconmanager.loadIcon("menu-down", 16));
- CDockManager::iconProvider().registerCustomIcon(DockAreaUndockIcon, iconmanager.loadIcon("dock-float", 16));
- CDockManager::iconProvider().registerCustomIcon(AutoHideIcon, iconmanager.loadIcon("dock-auto-hide", 16));
- CDockManager::iconProvider().registerCustomIcon(DockAreaMinimizeIcon, iconmanager.loadIcon("dock-minimize", 16));
-
int retVal=0;
//qsrand(1234);
QByteArray stylesheet;
@@ -607,7 +574,7 @@
stylesheet.replace("___tb_menu_arrow___", tba);
}
- dockManager->setStyleSheet(stylesheet); // style sheet should be enabled when theme manager is implemented to handle color palettes in css file.
+// dockManager->setStyleSheet(stylesheet); // style sheet should be enabled when theme manager is implemented to handle color palettes in css file.
layerMenu->setStyleSheet(stylesheet);
unitSwitcher->setStyleSheet(stylesheet);
@@ -1906,13 +1873,6 @@
// Save GUI state
dockManager->saveWorkspaceToPrefs();
- // We need to remove all docks from the DockManager to prevent a memory leak
- // in case a plugin has added a dock in the DockManager and is simply deleted
- // on cleanup before it is removed from the DockManager.
- // Removed Docks are not deleted directly.
- dockManager->removeAllDockWidgets();
-
-
// Clean up plugins, THEN save prefs to disk
ScCore->pluginManager->cleanupPlugins();
if (!m_prefsManager.appPrefs.scrapbookPrefs.persistentScrapbook)
@@ -7609,7 +7569,7 @@
{
if (!HaveDoc)
return;
- m_pagePaletteWasClosed = pagePalette->isClosed();
+ m_pagePaletteWasClosed = pagePalette->isHidden();
QString mpName;
if (temp.isEmpty())
mpName = doc->currentPage()->masterPageName();
@@ -7642,12 +7602,12 @@
view->saveViewState();
pagePalette->startMasterPageMode(mpName);
- if (pagePalette->isClosed())
+ if (pagePalette->isHidden())
{
- auto* area = pagePalette->dockAreaWidget();
- auto* dockWidget = area->currentDockWidget();
- scrActions["toolsPages"]->setChecked(true);
- area->setCurrentDockWidget(dockWidget);
+ // auto* area = pagePalette->dockAreaWidget();
+ // auto* dockWidget = area->currentDockWidget();
+ // scrActions["toolsPages"]->setChecked(true);
+ // area->setCurrentDockWidget(dockWidget);
}
appModeHelper->setMasterPageEditMode(true, doc);
}
Index: scribus/scribus.h
===================================================================
--- scribus/scribus.h (Revision 27098)
+++ scribus/scribus.h (Arbeitskopie)
@@ -61,7 +61,11 @@
#include "styleoptions.h"
#include "ui/customfdialog.h"
#include "ui/scmessagebox.h"
+//#include "third_party/KDDockWidgets/src/core/MainWindow.h"
+#include <kddockwidgets/MainWindow.h>
+#include <kddockwidgets/DockWidget.h>
+
class ActionManager;
class AlignDistributePalette;
class AppModeHelper;
@@ -126,7 +130,7 @@
* and statusbar. For the main view, an instance of class ScribusView is
* created which creates your view.
*/
-class SCRIBUS_API ScribusMainWindow : public QMainWindow, public UndoObject
+class SCRIBUS_API ScribusMainWindow : public KDDockWidgets::QtWidgets::MainWindow, public UndoObject
{
Q_OBJECT
Index: scribus/scribuscore.cpp
===================================================================
--- scribus/scribuscore.cpp (Revision 27098)
+++ scribus/scribuscore.cpp (Arbeitskopie)
@@ -51,6 +51,9 @@
//extern ScribusQApp* ScQApp;
+//#include "third_party/KDDockWidgets/src/Config.h"
+#include <kddockwidgets/Config.h>
+
ScribusCore::ScribusCore() : defaultEngine(ScColorMgmtEngineFactory::createDefaultEngine()),
m_iconManager(IconManager::instance()),
m_prefsManager(PrefsManager::instance())
@@ -94,6 +97,24 @@
int ScribusCore::startGUI(bool showSplash, bool showFontInfo, bool showProfileInfo, const QString& newGuiLanguage)
{
+
+ // Initialize GUI
+ KDDockWidgets::initFrontend(KDDockWidgets::FrontendType::QtWidgets);
+
+ // Custom Widget Factory
+ //KDDockWidgets::Config::self().setViewFactory(new CustomWidgetFactory());
+
+ // https://github.com/KDAB/KDDockWidgets/blob/2.0/src/Config.h
+ auto flags = KDDockWidgets::Config::self().flags();
+ // flags |= KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible;
+ // flags |= KDDockWidgets::Config::Flag_ShowButtonsOnTabBarIfTitleBarHidden;
+ flags |= KDDockWidgets::Config::Flag_AllowSwitchingTabsViaMenu;
+ flags |= KDDockWidgets::Config::Flag_AutoHideSupport;
+ flags |= KDDockWidgets::Config::Flag_TabsHaveCloseButton;
+ flags |= KDDockWidgets::Config::Flag_AllowReorderTabs;
+ KDDockWidgets::Config::self().setFlags(flags);
+
+
auto* scribus = new ScribusMainWindow();
Q_CHECK_PTR(scribus);
if (!scribus)
@@ -135,8 +156,8 @@
{
if (PrefsManager::instance().appPrefs.uiPrefs.showStartupDialog && usingGUI())
scribus->startUpDialog();
- else
- scribus->setFocus();
+ // else
+ // scribus->setFocus();
}
}
else if (subsRet == QMessageBox::Help)
Index: scribus/third_party/CMakeLists.txt
===================================================================
--- scribus/third_party/CMakeLists.txt (Revision 27098)
+++ scribus/third_party/CMakeLists.txt (Arbeitskopie)
@@ -1,6 +1,4 @@
-#if(WANT_QTADS)
-add_subdirectory(Qt-Advanced-Docking-System)
-#endif()
+add_subdirectory(KDDockWidgets)
if(HAVE_OSG)
add_subdirectory(prc)
Index: scribus/ui/aligndistribute.cpp
===================================================================
--- scribus/ui/aligndistribute.cpp (Revision 27098)
+++ scribus/ui/aligndistribute.cpp (Arbeitskopie)
@@ -65,10 +65,9 @@
// =============================
-AlignDistributePalette::AlignDistributePalette(QWidget* parent) : DockPanelBase("AlignDistributePalette", "panel-align-distribute", parent)
+AlignDistributePalette::AlignDistributePalette() : DockPanelBase("AlignDistributePalette", "panel-align-distribute")
{
setSizePolicy( QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
- setObjectName("AlignDistributePalette");
ad = new AlignDistribute(this);
setWidget(ad);
@@ -113,6 +112,7 @@
void AlignDistributePalette::languageChange()
{
ad->retranslateUi(this);
+ setWindowTitle( tr("Align and Distribute"));
referenceGuideTooltipTemplate = tr("Align relative to a guide%1");
Index: scribus/ui/aligndistribute.h
===================================================================
--- scribus/ui/aligndistribute.h (Revision 27098)
+++ scribus/ui/aligndistribute.h (Arbeitskopie)
@@ -67,7 +67,7 @@
Q_OBJECT
public:
- AlignDistributePalette( QWidget* parent = nullptr);
+ AlignDistributePalette();
~AlignDistributePalette() = default;
virtual void setDoc( ScribusDoc* newDoc );
Index: scribus/ui/bookmarkpalette.cpp
===================================================================
--- scribus/ui/bookmarkpalette.cpp (Revision 27098)
+++ scribus/ui/bookmarkpalette.cpp (Arbeitskopie)
@@ -25,7 +25,7 @@
#include "bookmarkpalette.h"
-BookPalette::BookPalette(QWidget* parent) : DockPanelBase( "Books", "panel-bookmarks", parent )
+BookPalette::BookPalette() : DockPanelBase( "Books", "panel-bookmarks")
{
setObjectName(QString::fromLocal8Bit("Books"));
setMinimumSize( QSize(220, 240) );
Index: scribus/ui/bookmarkpalette.h
===================================================================
--- scribus/ui/bookmarkpalette.h (Revision 27098)
+++ scribus/ui/bookmarkpalette.h (Arbeitskopie)
@@ -50,7 +50,7 @@
\param parent Parent Window
\retval None
*/
- BookPalette(QWidget* parent);
+ BookPalette();
~BookPalette() {};
BookmarkView *BView;
Index: scribus/ui/contentpalette.cpp
===================================================================
--- scribus/ui/contentpalette.cpp (Revision 27098)
+++ scribus/ui/contentpalette.cpp (Arbeitskopie)
@@ -25,8 +25,7 @@
#include "styles/paragraphstyle.h"
#include "styles/charstyle.h"
-ContentPalette::ContentPalette(QWidget *parent) :
- DockPanelBase("ContentPalette", "panel-content-properties", parent)
+ContentPalette::ContentPalette() : DockPanelBase("ContentPalette", "panel-content-properties")
{
setObjectName(QString::fromLocal8Bit("ContentPalette"));
@@ -34,7 +33,7 @@
f.setPointSize(f.pointSize()-1);
setFont(f);
- stackedWidget = new StackedContainer(this);
+ stackedWidget = new StackedContainer(this);
defaultPal = new ContentPalette_Default(this);
stackedWidget->addWidget(defaultPal);
@@ -276,7 +275,7 @@
updatePanelTitle();
}
updateGeometry();
- DockPanelBase::update();
+ DockPanelBase::update();
}
void ContentPalette::unitChange()
@@ -319,7 +318,7 @@
languageChange();
return;
}
- DockPanelBase::changeEvent(e);
+ DockPanelBase::changeEvent(e);
}
void ContentPalette::updatePanelTitle()
@@ -364,7 +363,7 @@
void ContentPalette::update(const ParagraphStyle& style)
{
- textPal->updateParagraphStyle(style);
+ textPal->updateParagraphStyle(style);
}
void ContentPalette::update(const CharStyle& style)
@@ -378,7 +377,7 @@
void ContentPalette::updateTextStyles()
{
- textPal->updateTextStyles();
+ textPal->updateTextStyles();
}
void ContentPalette::updateTextAlignment(int i)
Index: scribus/ui/contentpalette.h
===================================================================
--- scribus/ui/contentpalette.h (Revision 27098)
+++ scribus/ui/contentpalette.h (Arbeitskopie)
@@ -8,9 +8,9 @@
#define CONTENTPALETTE_H
#include "scribusapi.h"
-#include "docks/dock_panelbase.h"
+#include "docks/dock_panelbase.h"
#include "scguardedptr.h"
-#include "widgets/stacked_container.h"
+#include "widgets/stacked_container.h"
class QStackedWidget;
@@ -29,12 +29,12 @@
class ParagraphStyle;
class CharStyle;
-class SCRIBUS_API ContentPalette : public DockPanelBase
+class SCRIBUS_API ContentPalette : public DockPanelBase
{
Q_OBJECT
public:
- ContentPalette(QWidget* parent);
+ ContentPalette();
~ContentPalette() {}
void updateColorList();
@@ -75,7 +75,7 @@
double m_unitRatio {1.0};
int m_unitIndex {0};
- StackedContainer* stackedWidget {nullptr};
+ StackedContainer* stackedWidget {nullptr};
ContentPalette_Default* defaultPal {nullptr};
PropertiesPalette_Group* groupPal {nullptr};
PropertiesPalette_Image* imagePal {nullptr};
Index: scribus/ui/docks/dock_centralwidget.cpp
===================================================================
--- scribus/ui/docks/dock_centralwidget.cpp (Revision 27098)
+++ scribus/ui/docks/dock_centralwidget.cpp (Arbeitskopie)
@@ -18,11 +18,17 @@
***************************************************************************/
#include "dock_centralwidget.h"
-DockCentralWidget::DockCentralWidget(QWidget *parent)
- : ads::CDockWidget(QString(), parent)
+DockCentralWidget::DockCentralWidget() : QWidget(nullptr)
{
setObjectName(QString::fromLocal8Bit("DockCentralWidget"));
- setFeature(ads::CDockWidget::NoTab, true);
- setFeature(ads::CDockWidget::DockWidgetFloatable, false);
+ layoutWidget = new QHBoxLayout();
+ layoutWidget->setSpacing(0);
+ layoutWidget->setContentsMargins(0, 0, 0, 0);
+ setLayout(layoutWidget);
}
+
+void DockCentralWidget::setWidget(QWidget *widget)
+{
+ layoutWidget->addWidget(widget);
+}
Index: scribus/ui/docks/dock_centralwidget.h
===================================================================
--- scribus/ui/docks/dock_centralwidget.h (Revision 27098)
+++ scribus/ui/docks/dock_centralwidget.h (Arbeitskopie)
@@ -20,14 +20,20 @@
#ifndef DOCK_CENTRALWIDGET_H
#define DOCK_CENTRALWIDGET_H
-#include "third_party/Qt-Advanced-Docking-System/src/DockWidget.h"
+#include <QWidget>
+#include <QHBoxLayout>
-class DockCentralWidget : public ads::CDockWidget
+class DockCentralWidget : public QWidget
{
Q_OBJECT
public:
- explicit DockCentralWidget(QWidget *parent = nullptr);
+ explicit DockCentralWidget();
+ void setWidget(QWidget *widget);
+
+private:
+ QHBoxLayout *layoutWidget;
+
};
#endif // DOCK_CENTRALWIDGET_H
Index: scribus/ui/docks/dock_panelbase.cpp
===================================================================
--- scribus/ui/docks/dock_panelbase.cpp (Revision 27098)
+++ scribus/ui/docks/dock_panelbase.cpp (Arbeitskopie)
@@ -20,6 +20,8 @@
#include "dock_panelbase.h"
#include <QApplication>
+#include <QScrollArea>
+#include <QScrollBar>
#include "iconmanager.h"
#include "prefscontext.h"
@@ -27,25 +29,15 @@
#include "prefsmanager.h"
#include "scribusapp.h"
-DockPanelBase::DockPanelBase(const QString &title, QString iconName, QWidget *parent)
- : CDockWidget(title, parent)
+DockPanelBase::DockPanelBase(const QString &title, QString iconName, KDDockWidgets::DockWidgetOptions options)
+ : KDDockWidgets::QtWidgets::DockWidget(title, options)
{
- /*if (PrefsManager::instance().appPrefs.uiPrefs.useSmallWidgets) {
- setStyleSheet(" QToolButton { margin: 1px; padding: 0px; font-size: 10px; } \
- QToolButton:pressed { padding-top: 2px; padding-left: 2px } \
- QPushButton { margin: 1px; padding: 0px; font-size: 10px; } \
- QPushButton:pressed { padding-top: 2px; padding-left: 2px } \
- QRadioButton, QComboBox, QLineEdit \
- QListView, QLabel { margin:1px; padding: 0px; font-size: 10px; } \
- QCheckBox, QSpinBox, QDoubleSpinBox \
- { margin:1px; padding: 0px; font-size: 10px; } \
- QTabWidget, QTabBar, QTableView, QGroupBox, QTreeView \
- { font-size: 10px ; } \
- QToolBox::tab { font-size: 10px; padding: 0px; margin: 0px; } \
- ");
- }*/
-
m_iconName = iconName;
+ m_scrollArea = new QScrollArea;
+ m_scrollArea->setFrameShape(QFrame::NoFrame);
+ m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ KDDockWidgets::QtWidgets::DockWidget::setWidget(m_scrollArea);
iconSetChange();
@@ -55,8 +47,8 @@
connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
}
-DockPanelBase::DockPanelBase(const QString &title, QWidget *parent)
- : DockPanelBase(title, QString(), parent){}
+DockPanelBase::DockPanelBase(const QString &title, KDDockWidgets::DockWidgetOptions options)
+ : DockPanelBase(title, QString(), options){}
void DockPanelBase::setPrefsContext(const QString &context)
{
@@ -69,6 +61,27 @@
m_palettePrefs = nullptr;
}
+void DockPanelBase::updateScrollAreaMinSize()
+{
+ if (!widget())
+ return;
+
+ int contentWidth = widget()->minimumSizeHint().width();
+ int frameWidth = m_scrollArea->frameWidth() * 2;
+ int scrollBarWidth = m_scrollArea->verticalScrollBar()->sizeHint().width();
+
+ m_scrollArea->setMinimumWidth(contentWidth + frameWidth + scrollBarWidth);
+}
+
+bool DockPanelBase::eventFilter(QObject *watched, QEvent *event)
+{
+ if (watched == widget() && event->type() == QEvent::Resize)
+ updateScrollAreaMinSize();
+
+ return QWidget::eventFilter(watched, event);
+
+}
+
void DockPanelBase::startup()
{
setFontSize();
@@ -97,3 +110,32 @@
}
}
+
+void DockPanelBase::setToggleViewAction(ScrAction *action)
+{
+ action->setCheckable(true);
+
+ connect( action, &ScrAction::toggled, toggleAction(), &QAction::setChecked);
+ connect( toggleAction(), &QAction::toggled, action, &ScrAction::setChecked);
+}
+
+void DockPanelBase::setWindowTitle(const QString &title)
+{
+ KDDockWidgets::QtWidgets::DockWidget::setWindowTitle(title);
+ setTitle( title );
+}
+
+void DockPanelBase::setWidget(QWidget *widget)
+{
+// widget->adjustSize();
+ widget->installEventFilter(this);
+ m_scrollArea->setWidget(widget);
+ m_scrollArea->setWidgetResizable(true);
+
+ updateScrollAreaMinSize();
+}
+
+QWidget *DockPanelBase::widget() const
+{
+ return m_scrollArea->widget();
+}
Index: scribus/ui/docks/dock_panelbase.h
===================================================================
--- scribus/ui/docks/dock_panelbase.h (Revision 27098)
+++ scribus/ui/docks/dock_panelbase.h (Arbeitskopie)
@@ -21,32 +21,41 @@
#define DOCK_PANELBASE_H
#include "scribusapi.h"
-#include "third_party/Qt-Advanced-Docking-System/src/DockWidget.h"
-using namespace ads;
+#include "scraction.h"
+#include <kddockwidgets/DockWidget.h>
+#include <QScrollArea>
class PrefsContext;
-class SCRIBUS_API DockPanelBase : public CDockWidget
+class SCRIBUS_API DockPanelBase : public KDDockWidgets::QtWidgets::DockWidget
{
Q_OBJECT
public:
- DockPanelBase(const QString &title, QWidget *parent = 0);
- DockPanelBase(const QString &title, QString iconName, QWidget *parent = 0);
+ DockPanelBase(const QString &title, KDDockWidgets::DockWidgetOptions options = KDDockWidgets::DockWidgetOption_None);
+ DockPanelBase(const QString &title, QString iconName, KDDockWidgets::DockWidgetOptions options = KDDockWidgets::DockWidgetOption_None);
void startup();
+ void setWindowTitle(const QString& title) override;
+ void setWidget(QWidget *widget);
+ QWidget *widget() const;
public slots:
virtual void setFontSize();
void iconSetChange();
+ void setToggleViewAction(ScrAction *action);
protected:
/** @brief Set the Preferences context to be used for storage of startup visibility and position and size */
virtual void setPrefsContext(const QString &context);
+ void updateScrollAreaMinSize();
+ bool eventFilter(QObject *watched, QEvent *event) override;
PrefsContext *m_palettePrefs {nullptr};
QString m_prefsContextName;
QString m_iconName;
+ QScrollArea *m_scrollArea;
+
};
#endif // DOCK_PANELBASE_H
Index: scribus/ui/inlinepalette.cpp
===================================================================
--- scribus/ui/inlinepalette.cpp (Revision 27098)
+++ scribus/ui/inlinepalette.cpp (Arbeitskopie)
@@ -101,7 +101,7 @@
clearSelection();
}
-InlinePalette::InlinePalette( QWidget* parent) : DockPanelBase("Inline", "panel-inline-items", parent)
+InlinePalette::InlinePalette() : DockPanelBase("Inline", "panel-inline-items")
{
setContentsMargins(3, 3, 3, 3);
setMinimumSize( QSize( 220, 240 ) );
Index: scribus/ui/inlinepalette.h
===================================================================
--- scribus/ui/inlinepalette.h (Revision 27098)
+++ scribus/ui/inlinepalette.h (Arbeitskopie)
@@ -72,7 +72,7 @@
Q_OBJECT
public:
- InlinePalette(QWidget* parent);
+ InlinePalette();
~InlinePalette() {};
void setMainWindow(ScribusMainWindow *mw);
Index: scribus/ui/layers.cpp
===================================================================
--- scribus/ui/layers.cpp (Revision 27098)
+++ scribus/ui/layers.cpp (Arbeitskopie)
@@ -42,7 +42,7 @@
#include "docks/dock_panelbase.h"
#include "undomanager.h"
-LayerPalette::LayerPalette(QWidget* parent) : DockPanelBase("Layers", "panel-layers", parent)
+LayerPalette::LayerPalette() : DockPanelBase("Layers", "panel-layers")
{
setObjectName(QString::fromLocal8Bit("Layers"));
setMinimumSize( QSize(220, 240) );
Index: scribus/ui/layers.h
===================================================================
--- scribus/ui/layers.h (Revision 27098)
+++ scribus/ui/layers.h (Arbeitskopie)
@@ -34,7 +34,7 @@
Q_OBJECT
public:
- LayerPalette(QWidget* parent);
+ LayerPalette();
~LayerPalette() {};
void installEventFilter(QObject *);
Index: scribus/ui/outlinepalette.cpp
===================================================================
--- scribus/ui/outlinepalette.cpp (Revision 27098)
+++ scribus/ui/outlinepalette.cpp (Arbeitskopie)
@@ -431,7 +431,7 @@
return true;
}
-OutlinePalette::OutlinePalette( QWidget* parent) : DockPanelBase("Tree", "panel-outline", parent)
+OutlinePalette::OutlinePalette() : DockPanelBase("Tree", "panel-outline")
{
// resize( 220, 240 );
setMinimumSize( QSize( 220, 240 ) );
@@ -481,9 +481,9 @@
connect(filterEdit, SIGNAL(textChanged(QString)), this, SLOT(filterTree(QString)));
// connect(filterShortcut, SIGNAL(activated()), filterEdit, SLOT(setFocus()));
connect(reportDisplay, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(slotDoubleClick(QTreeWidgetItem*,int)));
- connect(this, SIGNAL(visibilityChanged(bool)), this, SLOT(rebuildTree()));
+ connect(this, SIGNAL(isOpenChanged(bool)), this, SLOT(rebuildTree(bool)));
+ connect(this, SIGNAL(isCurrentTabChanged(bool)), this, SLOT(rebuildTree(bool)));
-
}
void OutlinePalette::setMainWindow(ScribusMainWindow *mw)
@@ -509,16 +509,9 @@
clearPalette();
}
-void OutlinePalette::toggleView(bool visible)
+void OutlinePalette::rebuildTree(bool isActive)
{
- DockPanelBase::toggleView(visible);
- rebuildTree();
-}
-
-
-void OutlinePalette::rebuildTree()
-{
- if (this->isVisible() && (currDoc != nullptr))
+ if (isActive)
BuildTree();
}
Index: scribus/ui/outlinepalette.h
===================================================================
--- scribus/ui/outlinepalette.h (Revision 27098)
+++ scribus/ui/outlinepalette.h (Arbeitskopie)
@@ -60,7 +60,7 @@
Q_OBJECT
public:
- OutlinePalette( QWidget* parent );
+ OutlinePalette();
void setMainWindow(ScribusMainWindow *mw);
void setDoc(ScribusDoc *);
@@ -77,7 +77,6 @@
void iconSetChange();
void languageChange();
void slotShowSelect(int pageNr, PageItem *pageItem);
- void toggleView(bool);
void slotRightClick(QPoint point);
void setActiveLayer(int layerID);
void setLayerVisible(int layerID);
@@ -96,7 +95,7 @@
void slotMultiSelect();
void slotSelect(QTreeWidgetItem* ite, int col);
void slotDoubleClick(QTreeWidgetItem* ite, int col);
- void rebuildTree();
+ void rebuildTree(bool);
protected:
void changeEvent(QEvent *e) override;
Index: scribus/ui/pagepalette.cpp
===================================================================
--- scribus/ui/pagepalette.cpp (Revision 27098)
+++ scribus/ui/pagepalette.cpp (Arbeitskopie)
@@ -21,7 +21,7 @@
#include "scribusdoc.h"
#include "scribusview.h"
-PagePalette::PagePalette(QWidget *parent) : DockPanelBase("PagePalette", "panel-page", parent)
+PagePalette::PagePalette() : DockPanelBase("PagePalette", "panel-page")
{
m_scMW = nullptr;//(ScribusMainWindow*) parent;
m_view = nullptr;
@@ -210,7 +210,7 @@
}
// Set focus to page palette or focus may be set to wrong document window
- this->setFocus();
+ //this->setFocus();
stackedWidget->setCurrentIndex(1);
setWindowTitle( tr( "Manage Masterpages" ) );
}
@@ -220,7 +220,7 @@
if (this->stackedWidget()->currentIndex() > 0)
{
// Set focus to page palette or focus may be set to wrong document window
- this->setFocus();
+ //this->setFocus();
this->stackedWidget()->setCurrentIndex(0);
}
Index: scribus/ui/pagepalette.h
===================================================================
--- scribus/ui/pagepalette.h (Revision 27098)
+++ scribus/ui/pagepalette.h (Arbeitskopie)
@@ -37,7 +37,7 @@
Q_OBJECT
public:
- PagePalette(QWidget *parent);
+ PagePalette();
~PagePalette() {};
QWidget* currentWidget();
Index: scribus/ui/propertiespalette.cpp
===================================================================
--- scribus/ui/propertiespalette.cpp (Revision 27098)
+++ scribus/ui/propertiespalette.cpp (Arbeitskopie)
@@ -45,7 +45,7 @@
#include "selection.h"
#include "undomanager.h"
-PropertiesPalette::PropertiesPalette(QWidget *parent) : DockPanelBase("PropertiesPalette", "panel-frame-properties", parent)
+PropertiesPalette::PropertiesPalette() : DockPanelBase("PropertiesPalette", "panel-frame-properties")
{
undoManager = UndoManager::instance();
Index: scribus/ui/propertiespalette.h
===================================================================
--- scribus/ui/propertiespalette.h (Revision 27098)
+++ scribus/ui/propertiespalette.h (Arbeitskopie)
@@ -55,7 +55,7 @@
Q_OBJECT
public:
- PropertiesPalette(QWidget* parent);
+ PropertiesPalette();
~PropertiesPalette() {}
void endPatchAdd();
Index: scribus/ui/scrapbookpalette.cpp
===================================================================
--- scribus/ui/scrapbookpalette.cpp (Revision 27098)
+++ scribus/ui/scrapbookpalette.cpp (Arbeitskopie)
@@ -740,7 +740,7 @@
}
/* This is the main Dialog-Class for the Scrapbook */
-Biblio::Biblio(QWidget* parent) : DockPanelBase("Sclib", "panel-scrapbook", parent)
+Biblio::Biblio() : DockPanelBase("Sclib", "panel-scrapbook")
{
setObjectName(QString::fromLocal8Bit("Sclib"));
setMinimumSize( QSize(220, 240) );
Index: scribus/ui/scrapbookpalette.h
===================================================================
--- scribus/ui/scrapbookpalette.h (Revision 27098)
+++ scribus/ui/scrapbookpalette.h (Arbeitskopie)
@@ -73,7 +73,7 @@
Q_OBJECT
public:
- Biblio( QWidget* parent);
+ Biblio();
~Biblio() {};
void changeEvent(QEvent *e) override;
Index: scribus/ui/symbolpalette.cpp
===================================================================
--- scribus/ui/symbolpalette.cpp (Revision 27098)
+++ scribus/ui/symbolpalette.cpp (Arbeitskopie)
@@ -150,7 +150,7 @@
clearSelection();
}
-SymbolPalette::SymbolPalette( QWidget* parent) : DockPanelBase("Symb", "panel-symbols", parent)
+SymbolPalette::SymbolPalette() : DockPanelBase("Symb", "panel-symbols")
{
setContentsMargins(3, 3, 3, 3);
setMinimumSize( QSize( 220, 240 ) );
Index: scribus/ui/symbolpalette.h
===================================================================
--- scribus/ui/symbolpalette.h (Revision 27098)
+++ scribus/ui/symbolpalette.h (Arbeitskopie)
@@ -76,7 +76,7 @@
Q_OBJECT
public:
- SymbolPalette(QWidget* parent);
+ SymbolPalette();
~SymbolPalette() {};
void setMainWindow(ScribusMainWindow *mw);
Index: scribus/undogui.cpp
===================================================================
--- scribus/undogui.cpp (Revision 27098)
+++ scribus/undogui.cpp (Arbeitskopie)
@@ -38,7 +38,7 @@
#include "undogui.h"
-UndoGui::UndoGui(QWidget* parent, const char* name) : DockPanelBase(name, "panel-action-history", parent)
+UndoGui::UndoGui(QWidget* parent, const char* name) : DockPanelBase(name, "panel-action-history")
{
languageChange();
}
|
|
|
|
|
|
patch applied and it works! i can now dock and undock the windows at will and it behaves (mostly...) correctly. (sometimes the default width is a bit wild, but for a start it's more than good!) only issue, after a make install, i got bin/scribus: error while loading shared libraries: libkddockwidgets-qt6.so.3: cannot open shared object file: No such file or directory which I could solve with export LD_LIBRARY_PATH=/home/ale/bin/build/scribus-tmp/lib/ I guess that something is missing in the cmake file... |
|
|
Here's a screenshot: |
|
|
Versus: |
|
|
It works, but there's some spacing issues that means it takes up a lot more space and I don't understand that white space left of the document window. It cannot be shrunk completely and it shouldn't be there in the first place. I added these CMake options and its ok locating the lib (first one making the difference but we don't need examples, docs or other frontends: -DKDDockWidgets_STATIC=true \ -DKDDockWidgets_EXAMPLES=false \ -DKDDockWidgets_DOCS=false \ -DKDDockWidgets_FRONTENDS='qtwidgets' \ |
|
|
Thanks for the feedback. I will check how I can improve it. |
|
|
Yes, addingset(KDDockWidgets_STATIC ON) set(KDDockWidgets_EXAMPLES OFF) set(KDDockWidgets_DOCS OFF) set(KDDockWidgets_FRONTENDS "qtwidgets") in CMakeLists_Dependencies.cmake, where WANT_QTADS was, makes is runnable : - ) And this is how it looks like on my laptop, on a fresh install! Some width are a bit too much : - ) |
|
|
A few more things: - In the default setup (when creating the new configs), the tabs are not created correctly: somehow, it shows all the tab titles in the title bar. - When there are multiple tabs, the title of the current tab is repeated in the a docking are title bar (in the screenshot above it's the duplicated "Properties" title) - In the screenshot I'm attaching here, there is a gray area on the right of the left docked panes. That's the minimum I can shrink it. And I don't seem to be able to remove it. -> Ok, I discovered what it is: when hiding the last palette that was in a tabbed area, the tabbed area is not removed and there is no way to add other palettes to that area or to remove it. Until one shows again that palette in that area and instead of closing it, first makes it floating (or move it to a different area) - I have now a crash: start Scribus with fresh settings, don't create a new document, and double click on the "Custom shapes" panel that is docked on the left side: crash. (Custom shapes, should probably not be docked by default, but hidden... but that's a different issue : - ) (I can correctly double click, as an example, "Arrange pages") - If I make "Custom shapes" floating and close it, and restart Scribus, then, I have a "Custom pages" floating and one "ghost" "Custom pages" behind the panels docked to the left. But I guess that there are more issues with the "Custom pages" panel: see screenshot : - ) |
|
|
I updated the patch and fixed a couple of small issues. The UI style is controlled by custom widgets from ScKDDockViewFactory and ScribusProxyStyle. The style overrides some OS specific settings, like spaces, alignments and colors and applies only to KDDock widgets. I tested it under Ubuntu (Fusion) and MacOS. Windows is untested yet. Steps 1. Download KDDockWidgets from https://github.com/KDAB/KDDockWidgets 2. Put the root folder into scribus -> third_party 3. Check if the root folders name is "KDDockWidgets" 4. Add additional files from zip 5. Apply the fix below 6. remove ADS folder (optional) kddock_2025-11-19_01.patch (88,153 bytes)
Index: CMakeLists_Dependencies.cmake
===================================================================
--- CMakeLists_Dependencies.cmake (Revision 27132)
+++ CMakeLists_Dependencies.cmake (Arbeitskopie)
@@ -318,6 +318,9 @@
set (HAVE_HARFBUZZ_SUBSET ON)
endif()
-#if(WANT_QTADS)
- set(HAVE_QTADS ON)
-#endif()
+
+# KDDockWidget
+set(KDDockWidgets_STATIC OFF) # must be dynamic to support docks in Scribus plugins
+set(KDDockWidgets_EXAMPLES OFF)
+set(KDDockWidgets_DOCS OFF)
+set(KDDockWidgets_FRONTENDS "qtwidgets")
Index: config.h.cmake
===================================================================
--- config.h.cmake (Revision 27132)
+++ config.h.cmake (Arbeitskopie)
@@ -14,7 +14,6 @@
#cmakedefine BUILD_MAC_BUNDLE
#cmakedefine DLL_USE_NATIVE_API 1
#cmakedefine GMAGICK_FOUND 1
-#cmakedefine HAVE_QTADS 1
#cmakedefine HAVE_BOOST 1
#cmakedefine HAVE_CAIRO 1
#cmakedefine HAVE_CUPS 1
Index: resources/iconsets/1_7_0/1_7_0.xml
===================================================================
--- resources/iconsets/1_7_0/1_7_0.xml (Revision 27132)
+++ resources/iconsets/1_7_0/1_7_0.xml (Arbeitskopie)
@@ -595,7 +595,9 @@
<icon id="close" file="16/action-close.svg" />
<icon id="dock-auto-hide" file="16/action-pin.svg" />
<icon id="dock-float" file="16/action-window-float.svg" />
+ <icon id="dock-maximize" file="16/action-maximize.svg" />
<icon id="dock-minimize" file="16/action-minimize.svg" />
+ <icon id="dock-unauto-hide" file="16/action-unpin.svg" />
<icon id="menu-down" file="16/action-menu-down.svg" />
<!-- Panels -->
Index: scribus/CMakeLists.txt
===================================================================
--- scribus/CMakeLists.txt (Revision 27132)
+++ scribus/CMakeLists.txt (Arbeitskopie)
@@ -59,11 +59,10 @@
set_property(SOURCE third_party/fparser/file.hh PROPERTY SKIP_AUTOGEN ON)
set_property(SOURCE third_party/fparser/fparser.hh PROPERTY SKIP_AUTOGEN ON)
-#if(WANT_QTADS)
- MESSAGE(STATUS "Qt Advanced Docking System included")
- link_directories(${CMAKE_CURRENT_BINARY_DIR}/third_party/Qt-Advanced-Docking-System)
-#endif()
+MESSAGE(STATUS "KDDock System included")
+link_directories(${CMAKE_CURRENT_BINARY_DIR}/third_party/KDDockWidgets)
+
link_directories(
${CMAKE_CURRENT_BINARY_DIR}/third_party/wpg
${CMAKE_CURRENT_BINARY_DIR}/third_party/pgf
@@ -292,9 +291,7 @@
${SCRIBUS_RTF_LIB}
)
-#if(WANT_QTADS)
- target_link_libraries(${EXE_NAME} PUBLIC qt6advanceddocking)
-#endif()
+target_link_libraries(${EXE_NAME} PUBLIC KDAB::kddockwidgets)
if(WITH_TESTS)
target_link_libraries(${EXE_NAME} PRIVATE
Index: scribus/CMakeLists_Sources.txt
===================================================================
--- scribus/CMakeLists_Sources.txt (Revision 27132)
+++ scribus/CMakeLists_Sources.txt (Arbeitskopie)
@@ -565,6 +565,8 @@
ui/delegates/sclistitemdelegate.cpp
ui/docks/dock_centralwidget.cpp
ui/docks/dock_panelbase.cpp
+ ui/factories/sckddockviewfactory.cpp
+ ui/factories/scribusproxystyle.cpp
ui/widgets/color_button.cpp
ui/widgets/combo_blendmode.cpp
ui/widgets/combo_linestyle.cpp
Index: scribus/manager/dock_manager.cpp
===================================================================
--- scribus/manager/dock_manager.cpp (Revision 27132)
+++ scribus/manager/dock_manager.cpp (Arbeitskopie)
@@ -26,15 +26,16 @@
#include "dock_manager.h"
#include <QMenu>
-#include "third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.h"
-#include "ui/docks/dock_centralwidget.h"
#include "iconmanager.h"
#include "prefsmanager.h"
+#include "scribus.h"
#include "scribusapp.h"
+#include "scribuscore.h"
#include "ui/aligndistribute.h"
#include "ui/bookmarkpalette.h"
#include "ui/contentpalette.h"
+#include "ui/docks/dock_centralwidget.h"
#include "ui/inlinepalette.h"
#include "ui/layers.h"
#include "ui/outlinepalette.h"
@@ -44,6 +45,8 @@
#include "ui/symbolpalette.h"
#include "undogui.h"
+#include <kddockwidgets/DockWidget.h>
+#include <kddockwidgets/LayoutSaver.h>
/* ********************************************************************************* *
*
@@ -51,38 +54,45 @@
*
* ********************************************************************************* */
-DockManager::DockManager(QWidget *parent)
- : CDockManager(parent)
+DockManager* DockManager::m_instance = nullptr;
+
+DockManager &DockManager::instance()
{
- dockCenter = new DockCentralWidget();
- auto *areaCenter = CDockManager::setCentralWidget(dockCenter);
- areaCenter->setAllowedAreas(LeftDockWidgetArea | RightDockWidgetArea);
+ static DockManager m_instance;
+ return m_instance;
+}
- setStyleSheet(""); // reset style sheet to use custom icons
+void DockManager::setMainWindow(ScribusMainWindow *mainwindow)
+{
+ m_mainwindow = mainwindow;
+ m_mainwindow->setPersistentCentralWidget(dockCenter);
+}
- connect( ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()) );
+DockManager::DockManager(QObject *parent) : QObject(parent)
+{
+ dockCenter = new DockCentralWidget();
}
void DockManager::setupDocks()
{
- pagePalette = new PagePalette((QWidget *) this->parent());
- contentPalette = new ContentPalette(this);
- propertiesPalette = new PropertiesPalette(this);
- outlinePalette = new OutlinePalette(this);
- layerPalette = new LayerPalette(this);
- inlinePalette = new InlinePalette(this);
+ pagePalette = new PagePalette();
+ contentPalette = new ContentPalette();
+ propertiesPalette = new PropertiesPalette();
+ outlinePalette = new OutlinePalette();
+ layerPalette = new LayerPalette();
+ inlinePalette = new InlinePalette();
alignDistributePalette = new AlignDistributePalette();
- scrapbookPalette = new Biblio(this);
- bookPalette = new BookPalette(this);
- undoPalette = new UndoPalette(this);
- symbolPalette = new SymbolPalette(this);
+ scrapbookPalette = new Biblio();
+ bookPalette = new BookPalette();
+ undoPalette = new UndoPalette();
+ symbolPalette = new SymbolPalette();
// Apply common configuration for each palette
configureDock(pagePalette);
configureDock(contentPalette);
configureDock(propertiesPalette);
+ configureDock(outlinePalette);
configureDock(layerPalette);
- configureDock(pagePalette);
configureDock(inlinePalette);
configureDock(alignDistributePalette);
configureDock(scrapbookPalette);
@@ -90,11 +100,6 @@
configureDock(undoPalette);
configureDock(symbolPalette);
- // Panel ToolProperties
- // PanelToolProperties * panelTest = new PanelToolProperties();
- // dockToolProperties->setWidget(panelTest);
- // dockToolProperties->setFeature(ads::CDockWidget::NoTab, true);
-
}
void DockManager::setCentralWidget(QWidget *widget)
@@ -111,38 +116,16 @@
void DockManager::initWorkspaces()
{
createDefaultWorkspace();
-// restoreWorkspaceFromPrefs();
}
-void DockManager::removeAllDockWidgets()
-{
- QMap<QString, CDockWidget *> map = dockWidgetsMap();
- foreach (QString key, map.keys())
- removeDockWidget(map.value(key));
-}
-void DockManager::hideAllDocks()
-{
- foreach (CDockWidget *dock, this->dockWidgets())
- {
- if(dock->isCentralWidget())
- continue;
- dock->closeDockWidget();
- }
-
- foreach (CFloatingDockContainer *dockContainer, this->floatingWidgets())
- {
- dockContainer->close();
- }
-}
-
void DockManager::toggleDocksVisibility()
{
- QString perspective = "_allpaletteshidden";
+ QString perspective = "e494294a-65b4-4ca5-a018-1fe741dbd1c3";
- if(perspectiveNames().contains(perspective))
+ if(m_perspectives.contains(perspective))
{
- openPerspective(perspective);
+ loadPerspective(perspective);
removePerspective(perspective);
m_dockTemporaryHidden = false;
}
@@ -149,93 +132,66 @@
else
{
addPerspective(perspective);
- hideAllDocks();
+ emit hideAllDocks();
m_dockTemporaryHidden = true;
-
-// qDebug() << Q_FUNC_INFO << this->dockWidgets();
-// qDebug() << Q_FUNC_INFO << this->floatingWidgets();
}
}
+void DockManager::refreshAllDocks()
+{
+ QListIterator<DockPanelBase*> iter(m_docks);
+ while(iter.hasNext()){
+ DockPanelBase *dock = iter.next();
+ // Update label visibility
+ dock->setLabelVis();
+ }
+}
+
bool DockManager::hasTemporaryHiddenDocks()
{
return m_dockTemporaryHidden;
}
-CDockAreaWidget *DockManager::addDockFromPlugin(CDockWidget *dock, bool closed)
+void DockManager::addDockFromPlugin(DockPanelBase *dock, bool closed)
{
- CDockAreaWidget *a = addDockWidget(RightDockWidgetArea, dock, dockCenter->dockAreaWidget());
- dock->toggleView(!closed);
- updateIcon(dock);
+ if (!m_mainwindow)
+ return;
+
+ const QSize m_preferredSize(QSize(290, 0));
+ KDDockWidgets::InitialOption option = closed ?
+ KDDockWidgets::InitialOption(KDDockWidgets::InitialVisibilityOption::StartHidden, m_preferredSize) :
+ KDDockWidgets::InitialOption(KDDockWidgets::InitialVisibilityOption::PreserveCurrentTab, m_preferredSize);
+
+ m_mainwindow->addDockWidget(dock, KDDockWidgets::Location_OnLeft, nullptr, option);
+
configureDock(dock);
- return a;
}
void DockManager::restoreWorkspaceFromPrefs()
{
- QByteArray ba = PrefsManager::instance().appPrefs.uiPrefs.adsDockState;
-
- if(ba.isEmpty())
- return;
-
- this->restoreState(ba);
+ loadPerspective(QByteArray::fromHex(PrefsManager::instance().appPrefs.uiPrefs.mainWinState));
}
void DockManager::saveWorkspaceToPrefs()
{
- PrefsManager::instance().appPrefs.uiPrefs.adsDockState = this->saveState();
+ PrefsManager::instance().appPrefs.uiPrefs.mainWinState = perspectiveFromUi().toHex();
}
-void DockManager::iconSetChange()
-{
- // Update all icons of each docked CDockContainer
- updateIcons(this->dockWidgets());
-
- // Update all icons of each floating CFloatingDockContainer
- foreach (CFloatingDockContainer *dockContainer, this->floatingWidgets())
- updateIcons(dockContainer->dockWidgets());
-}
-
void DockManager::restoreHiddenWorkspace()
{
- if (m_dockTemporaryHidden)
+ if (hasTemporaryHiddenDocks())
toggleDocksVisibility();
}
-void DockManager::updateIcons(QList<CDockWidget *> dockWidgets)
+void DockManager::configureDock(DockPanelBase *dock)
{
- foreach (CDockWidget *dock, dockWidgets)
- updateIcon(dock);
-}
+ if(!m_docks.contains(dock))
+ m_docks.append(dock);
-void DockManager::updateIcon(CDockWidget *dockWidget)
-{
- IconManager &iconManager = IconManager::instance();
-
- dockWidget->dockAreaWidget()->titleBarButton(ads::TitleBarButtonClose)->setIcon(iconManager.loadIcon("close", 12));
- dockWidget->dockAreaWidget()->titleBarButton(ads::TitleBarButtonUndock)->setIcon(iconManager.loadIcon("dock-float", 16));
- dockWidget->dockAreaWidget()->titleBarButton(ads::TitleBarButtonTabsMenu)->setIcon(iconManager.loadIcon("menu-down", 16));
- dockWidget->dockAreaWidget()->titleBarButton(ads::TitleBarButtonAutoHide)->setIcon(iconManager.loadIcon("dock-auto-hide", 16));
- dockWidget->dockAreaWidget()->titleBarButton(ads::TitleBarButtonMinimize)->setIcon(iconManager.loadIcon("dock-minimize", 16));
-
- for (auto tabCloseButton : dockWidget->dockAreaWidget()->findChildren<QAbstractButton*>("tabCloseButton"))
- tabCloseButton->setIcon(iconManager.loadIcon("close", 12));
+ connect(this, &DockManager::hideAllDocks, dock, &DockPanelBase::close);
}
-void DockManager::configureDock(CDockWidget *dock)
-{
- /*
- * MinimumSizeHintFromContent
- * MinimumSizeHintFromDockWidgetMinimumSize
- * MinimumSizeHintFromContentMinimumSize
- */
-
- dock->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidgetMinimumSize);
- dock->setMinimumWidth(dock->widget()->minimumSizeHint().width());
- connect( dock, &CDockWidget::viewToggled, this, &DockManager::restoreHiddenWorkspace);
-}
-
void DockManager::createDefaultWorkspace()
{
/************************************************************
@@ -257,56 +213,92 @@
*
*************************************************************/
- auto *areaCenter = dockCenter->dockAreaWidget();
+ if (!m_mainwindow)
+ return;
+ const QSize m_preferredSize(QSize(290, 0));
+ KDDockWidgets::InitialOption hiddenPalette(KDDockWidgets::InitialVisibilityOption::StartHidden, m_preferredSize);
+ KDDockWidgets::InitialOption visiblePalette(KDDockWidgets::InitialVisibilityOption::StartVisible, m_preferredSize);
+ KDDockWidgets::InitialOption unfocussedPalette(KDDockWidgets::InitialVisibilityOption::PreserveCurrentTab, m_preferredSize);
+
// Left
- auto *areaLeft = addDockWidget(LeftDockWidgetArea, pagePalette, areaCenter);
- addDockWidgetTabToArea(outlinePalette, areaLeft);
+ m_mainwindow->addDockWidget(pagePalette, KDDockWidgets::Location_OnLeft, nullptr, visiblePalette);
+ pagePalette->addDockWidgetAsTab(outlinePalette, hiddenPalette);
- // Left Center
- auto *areaCenterLeft = addDockWidget(LeftDockWidgetArea, inlinePalette, areaCenter);
- addDockWidgetTabToArea(scrapbookPalette, areaCenterLeft);
- addDockWidgetTabToArea(bookPalette, areaCenterLeft);
- addDockWidgetTabToArea(symbolPalette, areaCenterLeft);
+ // Left Center
+ // Workaround: inline palette acts as a main container for the other palettes, we have to show it so that it is docked.
+ m_mainwindow->addDockWidget(inlinePalette, KDDockWidgets::Location_OnRight, pagePalette, visiblePalette);
+ inlinePalette->addDockWidgetAsTab(scrapbookPalette, hiddenPalette);
+ inlinePalette->addDockWidgetAsTab(bookPalette, hiddenPalette);
+ inlinePalette->addDockWidgetAsTab(symbolPalette, hiddenPalette);
+ // Workaround: we have to hide inline palette manually.
+ inlinePalette->close();
// Left Bottom
- auto *areaLeftBottom = addDockWidget(BottomDockWidgetArea, layerPalette, areaLeft);
- addDockWidgetTabToArea(alignDistributePalette, areaLeftBottom);
- addDockWidgetTabToArea(undoPalette, areaLeftBottom);
+ m_mainwindow->addDockWidget(alignDistributePalette, KDDockWidgets::Location_OnBottom, pagePalette, visiblePalette);
+ alignDistributePalette->addDockWidgetAsTab(layerPalette, hiddenPalette);
+ alignDistributePalette->addDockWidgetAsTab(undoPalette, hiddenPalette);
- // Right Panel
- auto *areaRight = addDockWidget(RightDockWidgetArea, propertiesPalette, areaCenter);
- addDockWidget(CenterDockWidgetArea, contentPalette, areaRight);
+ // Right
+ m_mainwindow->addDockWidget(propertiesPalette, KDDockWidgets::Location_OnRight, nullptr, visiblePalette);
+ propertiesPalette->addDockWidgetAsTab(contentPalette, unfocussedPalette);
- // Top Panel
- // auto * areaTop = addDockWidget(TopDockWidgetArea, dockToolProperties);
- // areaTop->setAllowedAreas(NoDockWidgetArea);
- // areaTop->setDockAreaFlag(CDockAreaWidget::HideSingleWidgetTitleBar, true);
- // Resizing area height of left and bottom-left
- int heightL = areaLeft->height();
- setSplitterSizes(areaLeft, {heightL * 3 / 4, heightL * 1 / 4});
+ // Set active palettes
+ // alignDistributePalette->setAsCurrentTab();
+ // pagePalette->setAsCurrentTab();
+ // propertiesPalette->setAsCurrentTab();
- // Resizing area width of left, center-left, center and right
- int widthCL = areaCenter->width();
- int panelWidth = 290;
- setSplitterSizes(areaCenter, {panelWidth, panelWidth, widthCL - 3 * panelWidth, panelWidth});
+ // Save Scribus Default
+ addPerspective("Default");
+ restoreWorkspaceFromPrefs();
- // hide panels that are not visible in default workspace
- inlinePalette->closeDockWidget();
- scrapbookPalette->closeDockWidget();
- bookPalette->closeDockWidget();
- symbolPalette->closeDockWidget();
- layerPalette->closeDockWidget();
- undoPalette->closeDockWidget();
- outlinePalette->closeDockWidget();
+ // Save Users Preference
+ addPerspective("Current");
- // active palettes
- areaLeft->setCurrentDockWidget(pagePalette);
- areaRight->setCurrentDockWidget(propertiesPalette);
- areaLeftBottom->setCurrentDockWidget(alignDistributePalette);
+}
- // add perspective for a later usage, like reset workspace to default.
- this->addPerspective("Default");
+void DockManager::addPerspective(const QString name)
+{
+ if (m_perspectives.contains(name))
+ return;
+
+ m_perspectives.insert(name, perspectiveFromUi());
}
+
+void DockManager::removePerspective(const QString name)
+{
+ if (m_perspectives.contains(name))
+ m_perspectives.remove(name);
+}
+
+void DockManager::loadPerspective(const QString name)
+{
+ loadPerspective(perspectiveByName(name));
+}
+
+void DockManager::loadPerspective(const QByteArray byte)
+{
+ if(byte.isEmpty())
+ return;
+
+ KDDockWidgets::RestoreOptions options = KDDockWidgets::RestoreOption_None;
+ KDDockWidgets::LayoutSaver saver(options);
+ saver.restoreLayout(byte);
+}
+
+QByteArray DockManager::perspectiveByName(const QString name)
+{
+ if (!m_perspectives.contains(name))
+ return QByteArray();
+
+ return m_perspectives.value(name);
+}
+
+QByteArray DockManager::perspectiveFromUi()
+{
+ KDDockWidgets::RestoreOptions options = KDDockWidgets::RestoreOption_None;
+ KDDockWidgets::LayoutSaver saver(options);
+ return saver.serializeLayout();
+}
Index: scribus/manager/dock_manager.h
===================================================================
--- scribus/manager/dock_manager.h (Revision 27132)
+++ scribus/manager/dock_manager.h (Arbeitskopie)
@@ -28,10 +28,8 @@
#include "prefscontext.h"
#include "scribusapi.h"
-#include "third_party/Qt-Advanced-Docking-System/src/DockManager.h"
+#include "ui/docks/dock_panelbase.h"
-using namespace ads;
-
class ScribusMainWindow;
class PagePalette;
class OutlinePalette;
@@ -46,36 +44,43 @@
class SymbolPalette;
class DockCentralWidget;
-class SCRIBUS_API DockManager : public CDockManager
+class SCRIBUS_API DockManager : public QObject
{
Q_OBJECT
public:
- DockManager(QWidget *parent);
+ DockManager(DockManager const&) = delete;
+ void operator=(DockManager const&) = delete;
+ static DockManager &instance();
+ void setMainWindow(ScribusMainWindow *mainwindow);
void setCentralWidget(QWidget *widget);
void setupDocks();
+
/**
* @brief Creates all preconfigured workspaces as perspectives.
*/
void initWorkspaces();
+
/**
- * @brief Removes all dock widgets including docks added by plugins.
- */
- void removeAllDockWidgets();
- /**
- * @brief Hides all docked and floating dock containers.
- */
- void hideAllDocks();
- /**
* @brief Toggles the temporary visibility of all docks.
*/
void toggleDocksVisibility();
+
+ void refreshAllDocks();
+
+ void addPerspective(const QString name);
+ void removePerspective(const QString name);
+ void loadPerspective(const QString name);
+ void loadPerspective(const QByteArray byte);
+
+
/**
* @brief Returns true if all docks are temporary hidden.
* @return
*/
bool hasTemporaryHiddenDocks();
+
/**
* @brief Adds a dock widget to dock manager. Useful for docks that are not initialized by dock manager, e.g. from plugins.
* @param dock
@@ -82,7 +87,7 @@
* @param closed
* @return
*/
- CDockAreaWidget *addDockFromPlugin(CDockWidget *dock, bool closed = true);
+ void addDockFromPlugin(DockPanelBase *dock, bool closed = true);
PagePalette *pagePalette {nullptr};
OutlinePalette *outlinePalette {nullptr};
@@ -101,12 +106,12 @@
* @brief Restore current workspace from local preferences file
*/
void restoreWorkspaceFromPrefs();
+
/**
* @brief Save current workspace to local preferences file
*/
void saveWorkspaceToPrefs();
- void iconSetChange();
/**
* @brief Show all hidden dock palettes if temporary hidden.
*/
@@ -113,18 +118,20 @@
void restoreHiddenWorkspace();
protected:
+ DockManager(QObject *parent = nullptr);
+ ~DockManager() = default;
+
DockCentralWidget *dockCenter {nullptr};
+ ScribusMainWindow * m_mainwindow {nullptr};
bool m_dockTemporaryHidden {false};
- QMap<CDockWidget *, bool> m_temporaryHiddenDocks;
+ QMap<QString, QByteArray> m_perspectives;
+ static DockManager* m_instance;
+ QList<DockPanelBase*> m_docks;
- /**
- * @brief Refreshes all icons of a dock. Needed for icon set or GUI changes.
- * @param dockWidgets
- */
- void updateIcons(QList<CDockWidget *> dockWidgets);
- void updateIcon(CDockWidget * dockWidget);
+ QByteArray perspectiveByName(const QString name);
+ QByteArray perspectiveFromUi();
- void configureDock(CDockWidget *dock);
+ void configureDock(DockPanelBase *dock);
/**
* @brief Creates a default workspace as perspective.
@@ -131,6 +138,9 @@
*/
void createDefaultWorkspace();
+signals:
+ void hideAllDocks();
+
};
#endif // DOCK_MANAGER_H
Index: scribus/plugins/shapes/shapepalette.cpp
===================================================================
--- scribus/plugins/shapes/shapepalette.cpp (Revision 27132)
+++ scribus/plugins/shapes/shapepalette.cpp (Arbeitskopie)
@@ -32,7 +32,6 @@
#include "scribusXml.h"
#include "selection.h"
#include "shapepalette.h"
-#include "third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.h"
#include "ui/scmessagebox.h"
#include "util.h"
#include "util_math.h"
@@ -280,13 +279,14 @@
}
}
-ShapePalette::ShapePalette(QWidget *parent) : DockPanelBase("Shap", "panel-custom-shapes", parent)
+ShapePalette::ShapePalette() : DockPanelBase("Shap", "panel-custom-shapes")
{
setMinimumSize( QSize( 220, 240 ) );
- setObjectName(QString::fromLocal8Bit("Shap"));
+
+ //setObjectName(QString::fromLocal8Bit("Shap"));
setSizePolicy( QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
- containerWidget = new QWidget(this);
- vLayout = new QVBoxLayout( containerWidget );
+
+ vLayout = new QVBoxLayout();
vLayout->setSpacing(3);
vLayout->setContentsMargins(3, 3, 3, 3);
buttonLayout = new QHBoxLayout;
@@ -293,7 +293,7 @@
buttonLayout->setSpacing(6);
buttonLayout->setContentsMargins(0, 0, 0, 0);
- importButton = new QToolButton(this);
+ importButton = new QToolButton();
importButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
importButton->setIcon(IconManager::instance().loadIcon("document-open"));
importButton->setIconSize(QSize(16, 16));
@@ -302,7 +302,7 @@
QSpacerItem* spacer = new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum );
buttonLayout->addItem( spacer );
- closeButton = new QToolButton(this);
+ closeButton = new QToolButton();
closeButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
closeButton->setIcon(IconManager::instance().loadIcon("close"));
closeButton->setIconSize(QSize(16, 16));
@@ -309,8 +309,12 @@
buttonLayout->addWidget( closeButton );
vLayout->addLayout( buttonLayout );
- Frame3 = new QToolBox( this );
+ Frame3 = new QToolBox();
vLayout->addWidget(Frame3);
+
+ containerWidget = new QWidget();
+ containerWidget->setLayout(vLayout);
+
setWidget(containerWidget);
unsetDoc();
Index: scribus/plugins/shapes/shapepalette.h
===================================================================
--- scribus/plugins/shapes/shapepalette.h (Revision 27132)
+++ scribus/plugins/shapes/shapepalette.h (Arbeitskopie)
@@ -40,7 +40,6 @@
#include "pluginapi.h"
-//#include "ui/scdockpalette.h"
#include "ui/docks/dock_panelbase.h"
#include "ui/sclistwidgetdelegate.h"
#include "fpointarray.h"
@@ -91,7 +90,7 @@
Q_OBJECT
public:
- ShapePalette(QWidget *parent);
+ ShapePalette();
~ShapePalette() {};
void writeToPrefs();
Index: scribus/plugins/shapes/shapeplugin.cpp
===================================================================
--- scribus/plugins/shapes/shapeplugin.cpp (Revision 27132)
+++ scribus/plugins/shapes/shapeplugin.cpp (Arbeitskopie)
@@ -25,13 +25,14 @@
#include <QWidget>
#include <QString>
+#include "scraction.h"
+#include "scribus.h"
+#include "scribusapp.h"
#include "scribuscore.h"
-#include "scribusapp.h"
+#include "shapepalette.h"
#include "shapeplugin.h"
-#include "scraction.h"
#include "ui/scmwmenumanager.h"
-
int shapeplugin_getPluginAPIVersion()
{
return PLUGIN_API_VERSION;
@@ -51,13 +52,6 @@
delete plug;
}
-ShapePlugin::ShapePlugin()
-{
- sc_palette = nullptr;
-}
-
-ShapePlugin::~ShapePlugin() {};
-
void ShapePlugin::languageChange()
{
if (sc_palette)
@@ -69,25 +63,15 @@
if (!sc_palette)
return;
- sc_palette->setMainWindow(mw);
+ sc_palette->setMainWindow(mw);
languageChange();
m_actions.insert("shapeShowPalette", new ScrAction(fullTrName(), QKeySequence(), this));
+ sc_palette->setToggleViewAction(m_actions["shapeShowPalette"]);
- // Use this if menu action is checkable
- // m_actions["shapeShowPalette"]->setToggleAction(true);
- // m_actions["shapeShowPalette"]->setChecked(false);
- // connect(m_actions["shapeShowPalette"], SIGNAL(toggled(bool)), sc_palette, SLOT(toggleView(bool)));
- // connect(sc_palette, SIGNAL(viewToggled(bool)), m_actions["shapeShowPalette"], SLOT(setChecked(bool)));
-
- // Use this if menu action is not checkable
- connect(m_actions["shapeShowPalette"], SIGNAL(triggered()), sc_palette, SLOT(toggleView()));
-
mw->scrMenuMgr->addMenuItemStringAfter("shapeShowPalette", "toolsInline", "Windows");
mw->scrMenuMgr->addMenuItemStringsToMenuBar("Windows", m_actions);
- // For some reason we can't call addDockWidget(...) directly. If we do so Scribus crashes.
- mw->dockManager->addDockFromPlugin(sc_palette, false);
-
+ DockManager::instance().addDockFromPlugin(sc_palette, false);
}
QString ShapePlugin::fullTrName() const
@@ -112,7 +96,7 @@
bool ShapePlugin::initPlugin()
{
- sc_palette = new ShapePalette(ScCore->primaryMainWindow());
+ sc_palette = new ShapePalette();
sc_palette->startup();
sc_palette->readFromPrefs();
return true;
Index: scribus/plugins/shapes/shapeplugin.h
===================================================================
--- scribus/plugins/shapes/shapeplugin.h (Revision 27132)
+++ scribus/plugins/shapes/shapeplugin.h (Arbeitskopie)
@@ -24,8 +24,8 @@
public:
// Standard plugin implementation
- ShapePlugin();
- virtual ~ShapePlugin();
+ ShapePlugin() {};
+ virtual ~ShapePlugin() {};
bool initPlugin() override;
bool cleanupPlugin() override;
QString fullTrName() const override;
Index: scribus/prefsmanager.cpp
===================================================================
--- scribus/prefsmanager.cpp (Revision 27132)
+++ scribus/prefsmanager.cpp (Arbeitskopie)
@@ -169,11 +169,11 @@
#endif
/** Set Default window position and size to sane default values which should work on every screen */
const QScreen* s = QGuiApplication::primaryScreen();
- appPrefs.uiPrefs.mainWinSettings.width = s->availableGeometry().width() * (4.0 / 5.0);
- appPrefs.uiPrefs.mainWinSettings.height = s->availableGeometry().height() * (4.0 / 5.0);
- appPrefs.uiPrefs.mainWinSettings.xPosition = (s->availableGeometry().width() - appPrefs.uiPrefs.mainWinSettings.width) / 2;
- appPrefs.uiPrefs.mainWinSettings.yPosition = (s->availableGeometry().height() - appPrefs.uiPrefs.mainWinSettings.height) / 2;
- appPrefs.uiPrefs.mainWinSettings.maximized = false;
+ // appPrefs.uiPrefs.mainWinSettings.width = s->availableGeometry().width() * (4.0 / 5.0);
+ // appPrefs.uiPrefs.mainWinSettings.height = s->availableGeometry().height() * (4.0 / 5.0);
+ // appPrefs.uiPrefs.mainWinSettings.xPosition = (s->availableGeometry().width() - appPrefs.uiPrefs.mainWinSettings.width) / 2;
+ // appPrefs.uiPrefs.mainWinSettings.yPosition = (s->availableGeometry().height() - appPrefs.uiPrefs.mainWinSettings.height) / 2;
+ // appPrefs.uiPrefs.mainWinSettings.maximized = false;
appPrefs.uiPrefs.mainWinState = QByteArray();
appPrefs.uiPrefs.RecentDocs.clear();
appPrefs.uiPrefs.recentDocCount = 5;
@@ -963,7 +963,6 @@
appPrefs.uiPrefs.language = "en_GB"; // If we get here, Houston, we have a problem!
}
appPrefs.uiPrefs.mainWinState = QByteArray::fromBase64(userprefsContext->get("mainwinstate", "").toLatin1());
- appPrefs.uiPrefs.adsDockState = QByteArray::fromBase64(userprefsContext->get("ads_dockstate", "").toLatin1());
//continue here...
//Prefs."blah blah" =...
}
@@ -984,17 +983,17 @@
// The caller is responsible for ensuring we aren't called under those
// conditions.
Q_ASSERT(!emergencyActivated);
- int currentScreen = ScCore->primaryMainWindow()->getScreenNumber();
- int currentScreenXPos = 0;
- int currentScreenYPos = 0;
- ScCore->primaryMainWindow()->getScreenPosition(currentScreenXPos, currentScreenYPos);
- appPrefs.uiPrefs.mainWinSettings.xPosition = ScCore->primaryMainWindow()->pos().x() - currentScreenXPos;
- appPrefs.uiPrefs.mainWinSettings.yPosition = ScCore->primaryMainWindow()->pos().y() - currentScreenYPos;
- appPrefs.uiPrefs.mainWinSettings.width = ScCore->primaryMainWindow()->size().width();
- appPrefs.uiPrefs.mainWinSettings.height = ScCore->primaryMainWindow()->size().height();
- appPrefs.uiPrefs.mainWinSettings.maximized = ScCore->primaryMainWindow()->isMaximized();
- appPrefs.uiPrefs.mainWinSettings.screenNumber = currentScreen;
- appPrefs.uiPrefs.mainWinState = ScCore->primaryMainWindow()->saveState();
+ // int currentScreen = ScCore->primaryMainWindow()->getScreenNumber();
+ // int currentScreenXPos = 0;
+ // int currentScreenYPos = 0;
+ // ScCore->primaryMainWindow()->getScreenPosition(currentScreenXPos, currentScreenYPos);
+ // appPrefs.uiPrefs.mainWinSettings.xPosition = ScCore->primaryMainWindow()->pos().x() - currentScreenXPos;
+ // appPrefs.uiPrefs.mainWinSettings.yPosition = ScCore->primaryMainWindow()->pos().y() - currentScreenYPos;
+ // appPrefs.uiPrefs.mainWinSettings.width = ScCore->primaryMainWindow()->size().width();
+ // appPrefs.uiPrefs.mainWinSettings.height = ScCore->primaryMainWindow()->size().height();
+ // appPrefs.uiPrefs.mainWinSettings.maximized = ScCore->primaryMainWindow()->isMaximized();
+ // appPrefs.uiPrefs.mainWinSettings.screenNumber = currentScreen;
+ // appPrefs.uiPrefs.mainWinState = ScCore->primaryMainWindow()->saveState();
appPrefs.uiPrefs.RecentDocs.clear();
uint max = qMin(appPrefs.uiPrefs.recentDocCount, ScCore->primaryMainWindow()->m_recentDocsList.count());
for (uint m = 0; m < max; ++m)
@@ -1018,7 +1017,6 @@
{
userprefsContext->set("gui_language", appPrefs.uiPrefs.language);
userprefsContext->set("mainwinstate", QString::fromLatin1(appPrefs.uiPrefs.mainWinState.toBase64()));
- userprefsContext->set("ads_dockstate", QString::fromLatin1(appPrefs.uiPrefs.adsDockState.toBase64()));
//continue here...
//Prefs."blah blah" =...
}
@@ -1606,14 +1604,14 @@
dcOperatorTools.setAttribute("RotationConstrainAngle", ScCLocale::toQStringC(appPrefs.opToolPrefs.constrain));
elem.appendChild(dcOperatorTools);
- QDomElement dcMainWindow = docu.createElement("MainWindow");
- dcMainWindow.setAttribute("XPosition", appPrefs.uiPrefs.mainWinSettings.xPosition);
- dcMainWindow.setAttribute("YPosition", appPrefs.uiPrefs.mainWinSettings.yPosition);
- dcMainWindow.setAttribute("Width", appPrefs.uiPrefs.mainWinSettings.width);
- dcMainWindow.setAttribute("Height", appPrefs.uiPrefs.mainWinSettings.height);
- dcMainWindow.setAttribute("Maximized", static_cast<int>(appPrefs.uiPrefs.mainWinSettings.maximized));
- dcMainWindow.setAttribute("ScreenNumber", appPrefs.uiPrefs.mainWinSettings.screenNumber);
- elem.appendChild(dcMainWindow);
+ // QDomElement dcMainWindow = docu.createElement("MainWindow");
+ // dcMainWindow.setAttribute("XPosition", appPrefs.uiPrefs.mainWinSettings.xPosition);
+ // dcMainWindow.setAttribute("YPosition", appPrefs.uiPrefs.mainWinSettings.yPosition);
+ // dcMainWindow.setAttribute("Width", appPrefs.uiPrefs.mainWinSettings.width);
+ // dcMainWindow.setAttribute("Height", appPrefs.uiPrefs.mainWinSettings.height);
+ // dcMainWindow.setAttribute("Maximized", static_cast<int>(appPrefs.uiPrefs.mainWinSettings.maximized));
+ // dcMainWindow.setAttribute("ScreenNumber", appPrefs.uiPrefs.mainWinSettings.screenNumber);
+ // elem.appendChild(dcMainWindow);
QDomElement dcScrapbook = docu.createElement("ScrapBook");
dcScrapbook.setAttribute("CopyToScrapbook", static_cast<int>(appPrefs.scrapbookPrefs.doCopyToScrapbook));
@@ -2329,47 +2327,47 @@
appPrefs.opToolPrefs.constrain = ScCLocale::toDoubleC(dc.attribute("RotationConstrainAngle"), 15.0);
}
- if (dc.tagName() == "MainWindow")
- {
- appPrefs.uiPrefs.mainWinSettings.xPosition = dc.attribute("XPosition", "0").toInt();
- appPrefs.uiPrefs.mainWinSettings.yPosition = dc.attribute("YPosition", "0").toInt();
- appPrefs.uiPrefs.mainWinSettings.width = dc.attribute("Width", "640").toInt();
- appPrefs.uiPrefs.mainWinSettings.height = dc.attribute("Height", "480").toInt();
- appPrefs.uiPrefs.mainWinSettings.maximized = static_cast<bool>(dc.attribute("Maximized", "0").toInt());
- appPrefs.uiPrefs.mainWinSettings.screenNumber = dc.attribute("ScreenNumber", "0").toInt();
- int minX = 0;
- int minY = 0;
-#ifdef Q_OS_MACOS
- // on Mac you're dead if the titlebar is not on screen
- minY = 22;
-#endif
- if (QGuiApplication::screens().count() == 1)
- {
- if (appPrefs.uiPrefs.mainWinSettings.xPosition < minX )
- appPrefs.uiPrefs.mainWinSettings.xPosition = minX;
- if (appPrefs.uiPrefs.mainWinSettings.yPosition < minY)
- appPrefs.uiPrefs.mainWinSettings.yPosition = minY;
- }
- int minWidth = 0;
- int minHeight = 0;
- const QScreen* s = QGuiApplication::screens().at(qMin(appPrefs.uiPrefs.mainWinSettings.screenNumber, QGuiApplication::screens().count() - 1));
- int maxWidth = s->availableSize().width();
- int maxHeight = s->availableSize().height();
- if (appPrefs.uiPrefs.mainWinSettings.width > maxWidth)
- appPrefs.uiPrefs.mainWinSettings.width = maxWidth;
- if (appPrefs.uiPrefs.mainWinSettings.width < minWidth)
- appPrefs.uiPrefs.mainWinSettings.width = minWidth;
- if (appPrefs.uiPrefs.mainWinSettings.height > maxHeight)
- appPrefs.uiPrefs.mainWinSettings.height = maxHeight;
- if (appPrefs.uiPrefs.mainWinSettings.height < minHeight)
- appPrefs.uiPrefs.mainWinSettings.height = minHeight;
- int maxX = s->availableSize().width() - minWidth;
- int maxY = s->availableSize().height() - minHeight;
- if (appPrefs.uiPrefs.mainWinSettings.xPosition >= maxX)
- appPrefs.uiPrefs.mainWinSettings.xPosition = maxX;
- if (appPrefs.uiPrefs.mainWinSettings.yPosition >= maxY)
- appPrefs.uiPrefs.mainWinSettings.yPosition = maxY;
- }
+// if (dc.tagName() == "MainWindow")
+// {
+// appPrefs.uiPrefs.mainWinSettings.xPosition = dc.attribute("XPosition", "0").toInt();
+// appPrefs.uiPrefs.mainWinSettings.yPosition = dc.attribute("YPosition", "0").toInt();
+// appPrefs.uiPrefs.mainWinSettings.width = dc.attribute("Width", "640").toInt();
+// appPrefs.uiPrefs.mainWinSettings.height = dc.attribute("Height", "480").toInt();
+// appPrefs.uiPrefs.mainWinSettings.maximized = static_cast<bool>(dc.attribute("Maximized", "0").toInt());
+// appPrefs.uiPrefs.mainWinSettings.screenNumber = dc.attribute("ScreenNumber", "0").toInt();
+// int minX = 0;
+// int minY = 0;
+// #ifdef Q_OS_MACOS
+// // on Mac you're dead if the titlebar is not on screen
+// minY = 22;
+// #endif
+// if (QGuiApplication::screens().count() == 1)
+// {
+// if (appPrefs.uiPrefs.mainWinSettings.xPosition < minX )
+// appPrefs.uiPrefs.mainWinSettings.xPosition = minX;
+// if (appPrefs.uiPrefs.mainWinSettings.yPosition < minY)
+// appPrefs.uiPrefs.mainWinSettings.yPosition = minY;
+// }
+// int minWidth = 0;
+// int minHeight = 0;
+// const QScreen* s = QGuiApplication::screens().at(qMin(appPrefs.uiPrefs.mainWinSettings.screenNumber, QGuiApplication::screens().count() - 1));
+// int maxWidth = s->availableSize().width();
+// int maxHeight = s->availableSize().height();
+// if (appPrefs.uiPrefs.mainWinSettings.width > maxWidth)
+// appPrefs.uiPrefs.mainWinSettings.width = maxWidth;
+// if (appPrefs.uiPrefs.mainWinSettings.width < minWidth)
+// appPrefs.uiPrefs.mainWinSettings.width = minWidth;
+// if (appPrefs.uiPrefs.mainWinSettings.height > maxHeight)
+// appPrefs.uiPrefs.mainWinSettings.height = maxHeight;
+// if (appPrefs.uiPrefs.mainWinSettings.height < minHeight)
+// appPrefs.uiPrefs.mainWinSettings.height = minHeight;
+// int maxX = s->availableSize().width() - minWidth;
+// int maxY = s->availableSize().height() - minHeight;
+// if (appPrefs.uiPrefs.mainWinSettings.xPosition >= maxX)
+// appPrefs.uiPrefs.mainWinSettings.xPosition = maxX;
+// if (appPrefs.uiPrefs.mainWinSettings.yPosition >= maxY)
+// appPrefs.uiPrefs.mainWinSettings.yPosition = maxY;
+// }
if (dc.tagName() == "ScrapBook")
{
Index: scribus/prefsstructs.h
===================================================================
--- scribus/prefsstructs.h (Revision 27132)
+++ scribus/prefsstructs.h (Arbeitskopie)
@@ -94,17 +94,17 @@
}
};
-struct WindowPrefs
-{
- int xPosition {0};
- int yPosition {0};
- int width {800};
- int height {600};
- bool visible {true};
- bool docked {false};
- bool maximized {false};
- int screenNumber {0};
-};
+// struct WindowPrefs
+// {
+// int xPosition {0};
+// int yPosition {0};
+// int width {800};
+// int height {600};
+// bool visible {true};
+// bool docked {false};
+// bool maximized {false};
+// int screenNumber {0};
+// };
struct tabPrefs
{
@@ -134,9 +134,8 @@
bool stickyTools {false}; //! Whether a user's tool section remains after use or the normal tool is reselected
bool grayscaleIcons {false}; //! Show icons in toolbars as grayscale
QString iconSet; //! Icon set name
- WindowPrefs mainWinSettings;
+ // WindowPrefs mainWinSettings;
QByteArray mainWinState;
- QByteArray adsDockState;
};
//Paths
Index: scribus/scribus.cpp
===================================================================
--- scribus/scribus.cpp (Revision 27132)
+++ scribus/scribus.cpp (Arbeitskopie)
@@ -239,6 +239,7 @@
#include "ui/tabmanager.h"
#include "ui/transformdialog.h"
#include "ui/viewtoolbar.h"
+#include "ui/factories/scribusproxystyle.h"
#include "undogui.h"
#include "undomanager.h"
#include "undostate.h"
@@ -247,8 +248,6 @@
#include "util.h"
#include "util_file.h"
#include "util_formats.h"
-#include "third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.h"
-#include "third_party/Qt-Advanced-Docking-System/src/IconProvider.h"
#ifdef HAVE_SVNVERSION
#include "svnversion.h"
@@ -268,13 +267,18 @@
#include "sclimits.h"
using namespace std;
-using namespace ads;
bool previewDinUse;
bool printDinUse;
extern bool emergencyActivated;
-ScribusMainWindow::ScribusMainWindow() :
+// MainWindowOptions see: https://github.com/KDAB/KDDockWidgets/blob/main/src/KDDockWidgets.h
+
+ScribusMainWindow::ScribusMainWindow() : MainWindow("scribusmainwindow",
+ KDDockWidgets::MainWindowOptions {
+ KDDockWidgets::MainWindowOption_HasCentralWidget |
+ KDDockWidgets::MainWindowOption_CentralWidgetGetsAllExtraSpace
+ }, nullptr),
m_prefsManager(PrefsManager::instance()),
m_widgetManager(WidgetManager::instance())
{
@@ -292,37 +296,6 @@
*/
int ScribusMainWindow::initScMW(bool primaryMainWindow)
{
- // Documentation: https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/blob/master/doc/user-guide.md
- CDockManager::setConfigFlag(CDockManager::AlwaysShowTabs, false);
- CDockManager::setConfigFlag(CDockManager::FloatingContainerHasWidgetIcon, true);
- CDockManager::setConfigFlag(CDockManager::FloatingContainerHasWidgetTitle, true);
- CDockManager::setConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar, false);
- CDockManager::setConfigFlag(CDockManager::OpaqueSplitterResize, true);
- CDockManager::setConfigFlag(CDockManager::TabCloseButtonIsToolButton, true);
- CDockManager::setConfigFlag(CDockManager::AllTabsHaveCloseButton, false);
-// CDockManager::setConfigFlag(CDockManager::DockAreaDynamicTabsMenuButtonVisibility, true);
- CDockManager::setConfigFlag(CDockManager::DockAreaHasCloseButton, false);
- CDockManager::setConfigFlag(CDockManager::DockAreaHasUndockButton, false);
- CDockManager::setConfigFlag(CDockManager::DockAreaHideDisabledButtons, true);
- CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true);
- CDockManager::setConfigFlag(CDockManager::DisableTabTextEliding, true);
- CDockManager::setConfigFlag(CDockManager::ShowTabTextOnlyForActiveTab, !m_prefsManager.appPrefs.uiPrefs.showLabelsOfInactiveTabs);
-
- // Documentation: https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/blob/master/doc/user-guide.md#auto-hide-configuration-flags
- CDockManager::setAutoHideConfigFlags(CDockManager::DefaultAutoHideConfig);
-// CDockManager::setAutoHideConfigFlag(CDockManager::AutoHideShowOnMouseOver, false);
-// CDockManager::setAutoHideConfigFlag(CDockManager::AutoHideCloseButtonCollapsesDock, true);
-// CDockManager::setAutoHideConfigFlag(CDockManager::AutoHideButtonTogglesArea, true);
- CDockManager::setAutoHideConfigFlag(CDockManager::DockAreaHasAutoHideButton, true);
-
- IconManager &iconmanager = IconManager::instance();
- CDockManager::iconProvider().registerCustomIcon(TabCloseIcon, iconmanager.loadIcon("close", 12));
- CDockManager::iconProvider().registerCustomIcon(DockAreaCloseIcon, iconmanager.loadIcon("close", 12));
- CDockManager::iconProvider().registerCustomIcon(DockAreaMenuIcon, iconmanager.loadIcon("menu-down", 16));
- CDockManager::iconProvider().registerCustomIcon(DockAreaUndockIcon, iconmanager.loadIcon("dock-float", 16));
- CDockManager::iconProvider().registerCustomIcon(AutoHideIcon, iconmanager.loadIcon("dock-auto-hide", 16));
- CDockManager::iconProvider().registerCustomIcon(DockAreaMinimizeIcon, iconmanager.loadIcon("dock-minimize", 16));
-
int retVal=0;
//qsrand(1234);
QByteArray stylesheet;
@@ -362,7 +335,7 @@
appModeHelper = new AppModeHelper();
appModeHelper->setup(actionManager, &scrActions, &scrRecentFileActions, &scrWindowsActions, &scrScrapActions, &scrLayersActions, &scrRecentPasteActions);
scrMenuMgr = new ScMWMenuManager(menuBar(), actionManager);
- dockManager = new DockManager(this);
+ DockManager::instance().setMainWindow(this);
m_formatsManager = FormatsManager::instance();
m_objectSpecificUndo = false;
@@ -399,7 +372,7 @@
if (primaryMainWindow)
ScCore->setSplashStatus( tr("Initializing Workspaces") );
initPalettes();
- dockManager->initWorkspaces();
+ // dockManager->initWorkspaces();
viewToolBar->previewQualitySwitcher->setCurrentIndex(m_prefsManager.appPrefs.itemToolPrefs.imageLowResType);
if (primaryMainWindow)
@@ -455,19 +428,20 @@
appModeHelper->setStartupActionsEnabled(false);
ScQApp->changeLabelVisibility(m_prefsManager.appPrefs.uiPrefs.showLabels);
+ DockManager::instance().refreshAllDocks();
setStyleSheet();
-#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
- connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, [this]()
- {
- emit ScQApp->iconSetChanged();
- // THIS IS A WORKAROUND!
- // It seems like once a widget has a custom style it doesn't redraw automatically with dark or light theme.
- // If we set the style sheet again it forces a redrawing with the current theme.
- setStyleSheet();
- });
-#endif
+// #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
+// connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, [this]()
+// {
+// emit ScQApp->iconSetChanged();
+// // THIS IS A WORKAROUND!
+// // It seems like once a widget has a custom style it doesn't redraw automatically with dark or light theme.
+// // If we set the style sheet again it forces a redrawing with the current theme.
+// setStyleSheet();
+// });
+// #endif
return retVal;
}
@@ -496,28 +470,9 @@
m_prefsManager.appPrefs.verifierPrefs.curCheckProfile = CommonStrings::PDF_1_4;
}
- const WindowPrefs& mainWinSettings = m_prefsManager.appPrefs.uiPrefs.mainWinSettings;
- QWindow* w = windowHandle();
- QList<QScreen*> screens = QGuiApplication::screens();
- QScreen* s = nullptr;
- if (w != nullptr)
- {
- s = screens.at(qMin(mainWinSettings.screenNumber, QGuiApplication::screens().count() - 1));
- windowHandle()->setScreen(s);
- }
- else
- s = QGuiApplication::primaryScreen();
- QRect r(0, 0, 0, 0);
- if (s != nullptr)
- r = s->geometry();
- move(r.left() + abs(mainWinSettings.xPosition), r.top() + abs(mainWinSettings.yPosition));
- resize(mainWinSettings.width, mainWinSettings.height);
+ // We have to load the workspace after the MainWindow is shown
+ DockManager::instance().initWorkspaces();
- if (mainWinSettings.maximized)
- this->setWindowState((this->windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen)) | Qt::WindowMaximized);
-
- if (!m_prefsManager.appPrefs.uiPrefs.mainWinState.isEmpty())
- restoreState(m_prefsManager.appPrefs.uiPrefs.mainWinState);
}
int ScribusMainWindow::getScreenNumber() const
@@ -607,8 +562,6 @@
stylesheet.replace("___tb_menu_arrow___", tba);
}
- dockManager->setStyleSheet(stylesheet); // style sheet should be enabled when theme manager is implemented to handle color palettes in css file.
-
layerMenu->setStyleSheet(stylesheet);
unitSwitcher->setStyleSheet(stylesheet);
zoomDefaultToolbarButton->setStyleSheet(stylesheet);
@@ -694,15 +647,15 @@
//CB TODO hide the publicly available members of some palettes
// these must be filtered too as they take control of the palettes events
- dockManager->setupDocks();
+ DockManager::instance().setupDocks();
// Outliner
- outlinePalette = dockManager->outlinePalette;
+ outlinePalette = DockManager::instance().outlinePalette;
outlinePalette->setMainWindow(this);
outlinePalette->setToggleViewAction(scrActions["toolsOutline"]);
// Frame Properties
- propertiesPalette = dockManager->propertiesPalette;
+ propertiesPalette = DockManager::instance().propertiesPalette;
propertiesPalette->setMainWindow(this);
propertiesPalette->setToggleViewAction(scrActions["toolsProperties"]);
emit UpdateRequest(reqDefFontListUpdate);
@@ -709,7 +662,7 @@
propertiesPalette->installEventFilter(this);
// Content Properties
- contentPalette = dockManager->contentPalette;
+ contentPalette = DockManager::instance().contentPalette;
contentPalette->setMainWindow(this);
contentPalette->setToggleViewAction(scrActions["toolsContent"]);
contentPalette->installEventFilter(this);
@@ -725,12 +678,12 @@
charPalette = new CharSelect(this);
// Layer
- layerPalette = dockManager->layerPalette;
+ layerPalette = DockManager::instance().layerPalette;
layerPalette->setToggleViewAction(scrActions["toolsLayers"]);
layerPalette->installEventFilter(this);
// Scrapbook
- scrapbookPalette = dockManager->scrapbookPalette;
+ scrapbookPalette = DockManager::instance().scrapbookPalette;
scrapbookPalette->setToggleViewAction(scrActions["toolsScrapbook"]);
connect( scrapbookPalette, SIGNAL(pasteToActualPage(QString)), this, SLOT(pasteFromScrapbook(QString)));
connect( scrapbookPalette, SIGNAL(scrapbookListChanged()), this, SLOT(rebuildScrapbookMenu()));
@@ -737,13 +690,13 @@
scrapbookPalette->installEventFilter(this);
// Pages
- pagePalette = dockManager->pagePalette;
+ pagePalette = DockManager::instance().pagePalette;
pagePalette->setMainWindow(this);
pagePalette->setToggleViewAction(scrActions["toolsPages"]);
pagePalette->installEventFilter(this);
// Bookmark
- bookmarkPalette = dockManager->bookPalette;
+ bookmarkPalette = DockManager::instance().bookPalette;
bookmarkPalette->setToggleViewAction(scrActions["toolsBookmarks"]);
bookmarkPalette->installEventFilter(this);
@@ -772,13 +725,13 @@
documentLogViewer->hide();
// Align & Distribute
- alignDistributePalette = dockManager->alignDistributePalette;
+ alignDistributePalette = DockManager::instance().alignDistributePalette;
alignDistributePalette->setToggleViewAction(scrActions["toolsAlignDistribute"]);
connect( alignDistributePalette, SIGNAL(documentChanged()), this, SLOT(slotDocCh()));
alignDistributePalette->installEventFilter(this);
// Symbols
- symbolPalette = dockManager->symbolPalette;
+ symbolPalette = DockManager::instance().symbolPalette;
symbolPalette->setMainWindow(this);
symbolPalette->setToggleViewAction(scrActions["toolsSymbols"]);
connect(symbolPalette, SIGNAL(startEdit(QString)), this, SLOT(editSymbolStart(QString)));
@@ -787,7 +740,7 @@
symbolPalette->installEventFilter(this);
// Inline Elements
- inlinePalette = dockManager->inlinePalette;
+ inlinePalette = DockManager::instance().inlinePalette;
inlinePalette->setMainWindow(this);
inlinePalette->setToggleViewAction(scrActions["toolsInline"]);
connect(inlinePalette, SIGNAL(startEdit(int)), this, SLOT(editInlineStart(int)));
@@ -796,7 +749,7 @@
inlinePalette->installEventFilter(this);
// Undo
- undoPalette = dockManager->undoPalette;
+ undoPalette = DockManager::instance().undoPalette;
undoPalette->setToggleViewAction(scrActions["toolsActionHistory"]);
undoPalette->installEventFilter(this);
m_undoManager->registerGui(undoPalette);
@@ -905,8 +858,8 @@
}
else
mdiArea->setViewMode(QMdiArea::SubWindowView);
- //setCentralWidget(mdiArea);
- dockManager->setCentralWidget(mdiArea);
+
+ DockManager::instance().setCentralWidget(mdiArea);
}
void ScribusMainWindow::initMenuBar()
@@ -1901,18 +1854,11 @@
pdfToolBar->connectPrefsSlot(false);
// if palettes are temporary hidden restore them before saving the workspace
- dockManager->restoreHiddenWorkspace();
+ DockManager::instance().restoreHiddenWorkspace();
// Save GUI state
- dockManager->saveWorkspaceToPrefs();
+ DockManager::instance().saveWorkspaceToPrefs();
- // We need to remove all docks from the DockManager to prevent a memory leak
- // in case a plugin has added a dock in the DockManager and is simply deleted
- // on cleanup before it is removed from the DockManager.
- // Removed Docks are not deleted directly.
- dockManager->removeAllDockWidgets();
-
-
// Clean up plugins, THEN save prefs to disk
ScCore->pluginManager->cleanupPlugins();
if (!m_prefsManager.appPrefs.scrapbookPrefs.persistentScrapbook)
@@ -5471,7 +5417,7 @@
void ScribusMainWindow::ToggleAllPalettes()
{
- dockManager->toggleDocksVisibility();
+ DockManager::instance().toggleDocksVisibility();
if (m_palettesStatus[PAL_ALL])
{
@@ -6489,37 +6435,19 @@
QString newUIStylePalette = m_prefsManager.appPrefs.uiPrefs.stylePalette;
if (oldPrefs.uiPrefs.stylePalette != newUIStylePalette)
{
- forceStyleUpdate = true;
if (newUIStylePalette == "dark")
- {
- QApplication::styleHints()->setColorScheme(Qt::ColorScheme::Dark);
-#if (defined Q_OS_LINUX)
- QPalette pal(QColor(49, 49, 49));
- QApplication::setPalette(pal);
-#endif
- }
+ ScribusProxyStyle::instance()->setApplicationTheme(ScribusProxyStyle::ApplicationTheme::Dark);
else if (newUIStylePalette == "light")
- {
- QApplication::styleHints()->setColorScheme(Qt::ColorScheme::Light);
-#if (defined Q_OS_LINUX)
- QPalette pal(QColor(239, 239, 239));
- QApplication::setPalette(pal);
-#endif
- }
+ ScribusProxyStyle::instance()->setApplicationTheme(ScribusProxyStyle::ApplicationTheme::Light);
else
- {
- QApplication::styleHints()->unsetColorScheme();
-#if (defined Q_OS_LINUX)
- QApplication::setPalette(this->style()->standardPalette());
-#endif
+ ScribusProxyStyle::instance()->setApplicationTheme(ScribusProxyStyle::ApplicationTheme::System);
}
- }
#endif
bool forceIconUpdate = false;
QString newUIStyle = m_prefsManager.guiStyle();
- if (oldPrefs.uiPrefs.style != newUIStyle || forceStyleUpdate == true)
+ if (oldPrefs.uiPrefs.style != newUIStyle)
{
forceIconUpdate = true;
@@ -6527,11 +6455,11 @@
if (!newUIStyle.isEmpty())
styleName = newUIStyle;
- QStyle * newStyle = QStyleFactory::create(styleName);
- if (newStyle)
- QApplication::setStyle(newStyle);
- else
- m_prefsManager.appPrefs.uiPrefs.style = oldPrefs.uiPrefs.style;
+ ScribusProxyStyle::instance()->setBaseStyleName(styleName);
+ // if (scStyle)
+ // ScQApp->setStyle(scStyle);
+ // else
+ // m_prefsManager.appPrefs.uiPrefs.style = oldPrefs.uiPrefs.style;
}
if (useDefaultScratchColor)
@@ -6543,6 +6471,7 @@
ScQApp->changeIconSet(newIconSet);
ScQApp->changeLabelVisibility(m_prefsManager.appPrefs.uiPrefs.showLabels);
+ DockManager::instance().refreshAllDocks();
int newUIFontSize = m_prefsManager.guiFontSize();
if (oldPrefs.uiPrefs.applicationFontSize != newUIFontSize)
@@ -6712,9 +6641,6 @@
nsEditor->startup();
symbolPalette->startup();
- // try to load custom layout from preferences
- dockManager->restoreWorkspaceFromPrefs();
-
// init the toolbars
fileToolBar->initVisibility();
editToolBar->initVisibility();
@@ -7609,7 +7535,7 @@
{
if (!HaveDoc)
return;
- m_pagePaletteWasClosed = pagePalette->isClosed();
+ m_pagePaletteWasClosed = pagePalette->isHidden();
QString mpName;
if (temp.isEmpty())
mpName = doc->currentPage()->masterPageName();
@@ -7642,13 +7568,9 @@
view->saveViewState();
pagePalette->startMasterPageMode(mpName);
- if (pagePalette->isClosed())
- {
- auto* area = pagePalette->dockAreaWidget();
- auto* dockWidget = area->currentDockWidget();
- scrActions["toolsPages"]->setChecked(true);
- area->setCurrentDockWidget(dockWidget);
- }
+ if (pagePalette->isHidden())
+ scrActions["toolsPages"]->triggered(true);
+
appModeHelper->setMasterPageEditMode(true, doc);
}
Index: scribus/scribus.css
===================================================================
--- scribus/scribus.css (Revision 27132)
+++ scribus/scribus.css (Arbeitskopie)
@@ -45,184 +45,3 @@
QComboBox#unitSwitcher::drop-down { subcontrol-origin: padding; subcontrol-position: top right; width: 15px; border-left-width: 1px; border-left-color: darkgray; border-left-style: solid; border-top-right-radius: 3px; border-bottom-right-radius: 3px; }
ScToolBar QToolButton::menu-indicator { image: url(___tb_menu_arrow___); }
-
-
-/*
- * Dock Container
- */
-ads--CDockContainerWidget {
- background: palette(mid);
-}
-ads--CDockContainerWidget > QSplitter{
- padding: 1 0 1 0;
-}
-
-ads--CDockContainerWidget ads--CDockSplitter::handle {
- background: none;
- height: 2px;
-}
-
-/*
-* Dock Area
-*/
-
-ads--CDockAreaWidget {
- background: none;
- border: none;
- /*border: 1px solid white;*/
-}
-
-ads--CDockAreaWidget #tabsMenuButton::menu-indicator {
- image: none;
-}
-
-/*
-* Dock Area Title bar
-*/
-
-ads--CDockAreaTitleBar
-{
- background: palette(mid);
- min-height: 24px;
- /* border-bottom: 1px solid palette(window); */
-}
-
-/* Container of all tabs */
-ads--CDockAreaTabBar #tabsContainerWidget
-{
- background: palette(mid);
- /* border-bottom: 1px solid palette(window); */
-}
-
-/*
-* Tab
-*/
-ads--CDockWidgetTab {
- background: none;
- /*border-color: palette(light);
- border-style: solid;
- border-width: 0 1px 0 0;*/
- padding: 0px;
- border:none;
-}
-
-ads--CDockWidgetTab[activeTab="false"]
-{
- background: none;
- border-right: 1px solid palette(window);
- /* border-bottom: 1px solid palette(window); */
-}
-
-ads--CDockWidgetTab[activeTab="true"] {
- background: palette(window);
-}
-
-ads--CDockWidgetTab QLabel {
- color: palette(foreground);
-}
-
-ads--CDockWidgetTab[activeTab="true"] QLabel {
- color: palette(foreground);
-}
-
-ads--CDockWidgetTab[activeTab="false"] QLabel {
- color: palette(foreground)
-}
-
-
-/*
-* Dock Widget
-*/
-
-ads--CDockWidget {
- background: none;
- border: none;
- /*border-color: palette(light);
- border-style: solid;
- border-width: 1px 0 0 0;*/
-}
-
-ads--CTitleBarButton {
- padding: 0px 0px;
-}
-
-QScrollArea#dockWidgetScrollArea {
- padding: 0px;
- border: none;
-}
-
-/*
-* Buttons
-*/
-
-#tabCloseButton {
-
- margin-top: 2px;
- padding:0px;
- background: none;
- border: none;
- border-radius: 2px;
-/* qproperty-icon: url(:/ads/images/close-button.svg),
- url(:/ads/images/close-button-disabled.svg) disabled;*/
- qproperty-iconSize: 16px;
- width: 16px;
- height: 16px;
-}
-
-#tabCloseButton:hover {
- border: 1px solid rgba(0, 0, 0, 32);
- background: rgba(0, 0, 0, 16);
-}
-
-#tabCloseButton:pressed {
- background: rgba(0, 0, 0, 32);
-}
-
-#tabsMenuButton {
- /*qproperty-icon: url(:/ads/images/tabs-menu-button.svg);
- qproperty-iconSize: 16px;*/
-}
-
-#dockAreaCloseButton {
- /*qproperty-icon: url(:/ads/images/close-button.svg),
- url(:/ads/images/close-button-disabled.svg) disabled;*/
- qproperty-iconSize: 16px;
-}
-
-#detachGroupButton {
- /*qproperty-icon: url(:/ads/images/detach-button.svg),
- url(:/ads/images/detach-button-disabled.svg) disabled;*/
- qproperty-iconSize: 16px;
-}
-
-/*
-* Floating Widget
-*/
-
-ads--CFloatingWidgetTitleBar {
- background: palette(midlight);
- /*qproperty-maximizeIcon: url(:/ads/images/maximize-button.svg);
- qproperty-normalIcon: url(:/ads/images/restore-button.svg);*/
-}
-
-
-#floatingTitleCloseButton, #floatingTitleMaximizeButton {
- qproperty-iconSize: 16px;
- border: none;
- margin: 3px;
-}
-
-
-#floatingTitleCloseButton {
- /*qproperty-icon: url(:/ads/images/close-button.svg);*/
- qproperty-iconSize: 16px;
-}
-
-#floatingTitleCloseButton:hover {
- background: rgba(0, 0, 0, 24);
- border: none;
-}
-
-#floatingTitleCloseButton:pressed {
- background: rgba(0, 0, 0, 48);
-}
Index: scribus/scribus.h
===================================================================
--- scribus/scribus.h (Revision 27132)
+++ scribus/scribus.h (Arbeitskopie)
@@ -61,7 +61,11 @@
#include "styleoptions.h"
#include "ui/customfdialog.h"
#include "ui/scmessagebox.h"
+//#include "third_party/KDDockWidgets/src/core/MainWindow.h"
+#include <kddockwidgets/MainWindow.h>
+#include <kddockwidgets/DockWidget.h>
+
class ActionManager;
class AlignDistributePalette;
class AppModeHelper;
@@ -72,7 +76,6 @@
class CheckDocument;
class ColorCombo;
class ContentPalette;
-class DockManager;
class DocumentLogManager;
class DocumentLogViewer;
class DownloadsPalette;
@@ -126,7 +129,7 @@
* and statusbar. For the main view, an instance of class ScribusView is
* created which creates your view.
*/
-class SCRIBUS_API ScribusMainWindow : public QMainWindow, public UndoObject
+class SCRIBUS_API ScribusMainWindow : public KDDockWidgets::QtWidgets::MainWindow, public UndoObject
{
Q_OBJECT
@@ -230,8 +233,6 @@
/** \brief private doc for managing default patterns. */
ScribusDoc* m_doc {nullptr};
- DockManager * dockManager {nullptr};
-
QProgressBar* mainWindowProgressBar {nullptr};
ScrSpinBox* zoomSpinBox {nullptr}; //zoom spinbox at bottom of view
PageSelector* pageSelector {nullptr}; //Page selector at bottom of view
Index: scribus/scribusapp.cpp
===================================================================
--- scribus/scribusapp.cpp (Revision 27132)
+++ scribus/scribusapp.cpp (Arbeitskopie)
@@ -693,23 +693,32 @@
bool ScribusQApp::event(QEvent *event)
{
- switch (event->type())
+ switch (event->type())
{
case QEvent::FileOpen:
+ {
+ QString filename = static_cast<QFileOpenEvent*>(event)->file();
+ if(m_ScCore && m_ScCore->initialized())
{
- QString filename = static_cast<QFileOpenEvent*>(event)->file();
- if(m_ScCore && m_ScCore->initialized())
- {
- ScribusMainWindow* mw = m_ScCore->primaryMainWindow();
- mw->loadDoc(filename);
- }
- else
- {
- m_filesToLoad.append(filename);
- }
- return true;
+ ScribusMainWindow* mw = m_ScCore->primaryMainWindow();
+ mw->loadDoc(filename);
}
+ else
+ {
+ m_filesToLoad.append(filename);
+ }
+ return true;
+ }
+ case QEvent::ApplicationPaletteChange:
+ {
+ IconManager &im = IconManager::instance();
+ im.rebuildCache();
+ emit iconSetChanged();
+ }
+ break;
default:
- return QApplication::event(event);
+ break;
}
+
+ return QApplication::event(event);
}
Index: scribus/scribuscore.cpp
===================================================================
--- scribus/scribuscore.cpp (Revision 27132)
+++ scribus/scribuscore.cpp (Arbeitskopie)
@@ -48,9 +48,14 @@
#include "undomanager.h"
#include "util_debug.h"
#include "util_ghostscript.h"
+#include "ui/factories/scribusproxystyle.h"
+#include "ui/factories/sckddockviewfactory.h"
//extern ScribusQApp* ScQApp;
+//#include "third_party/KDDockWidgets/src/Config.h"
+#include <kddockwidgets/Config.h>
+
ScribusCore::ScribusCore() : defaultEngine(ScColorMgmtEngineFactory::createDefaultEngine()),
m_iconManager(IconManager::instance()),
m_prefsManager(PrefsManager::instance())
@@ -94,6 +99,24 @@
int ScribusCore::startGUI(bool showSplash, bool showFontInfo, bool showProfileInfo, const QString& newGuiLanguage)
{
+
+ // Initialize GUI
+ KDDockWidgets::initFrontend(KDDockWidgets::FrontendType::QtWidgets);
+
+ // https://github.com/KDAB/KDDockWidgets/blob/2.0/src/Config.h
+ auto flags = KDDockWidgets::Config::self().flags();
+ // flags |= KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible;
+ // flags |= KDDockWidgets::Config::Flag_ShowButtonsOnTabBarIfTitleBarHidden;
+ // flags |= KDDockWidgets::Config::Flag_AllowSwitchingTabsViaMenu;
+ flags |= KDDockWidgets::Config::Flag_AutoHideSupport;
+ flags |= KDDockWidgets::Config::Flag_AllowReorderTabs;
+
+ // flags |= KDDockWidgets::Config::Flag_TabsHaveCloseButton;
+ flags |= KDDockWidgets::Config::Flag_CloseOnlyCurrentTab;
+
+ KDDockWidgets::Config::self().setFlags(flags);
+
+
auto* scribus = new ScribusMainWindow();
Q_CHECK_PTR(scribus);
if (!scribus)
@@ -135,8 +158,8 @@
{
if (PrefsManager::instance().appPrefs.uiPrefs.showStartupDialog && usingGUI())
scribus->startUpDialog();
- else
- scribus->setFocus();
+ // else
+ // scribus->setFocus();
}
}
else if (subsRet == QMessageBox::Help)
@@ -179,45 +202,43 @@
// This is a very basic implemenation of the UI theme palette.
// If necessary implement platform specific theme configurations here.
+ // Custom Widget Factory for KDDockWidgets
+ KDDockWidgets::Config::self().setViewFactory(new ScKDDockViewFactory());
+
+ // Configure GUI
+ const QString& prefsUiStyle = m_prefsManager.appPrefs.uiPrefs.style;
+ QString qtStyle = nullptr;
+ if (prefsUiStyle.length() > 0)
+ {
+ QStringList availableStyles = QStyleFactory::keys();
+ if (availableStyles.contains(prefsUiStyle))
+ qtStyle = prefsUiStyle;
+ else
+ m_prefsManager.appPrefs.uiPrefs.style.clear();
+ }
+
+ ScribusProxyStyle* scStyle = new ScribusProxyStyle(qtStyle);
+ scStyle->setParent(qApp);
+
// Apply different palette only if the system UI palette is different.
#if (QT_VERSION >= QT_VERSION_CHECK(6, 8, 0))
if (m_prefsManager.appPrefs.uiPrefs.stylePalette == "dark" && QApplication::styleHints()->colorScheme() == Qt::ColorScheme::Light)
{
- QApplication::styleHints()->setColorScheme(Qt::ColorScheme::Dark);
-
- // https://bugreports.qt.io/browse/QTBUG-132929
-#if (defined Q_OS_LINUX)
- QPalette pal(QColor(49, 49, 49));
- QApplication::setPalette(pal);
-#endif
+ scStyle->setApplicationTheme(ScribusProxyStyle::ApplicationTheme::Dark);
m_SplashScreen->setPixmap(m_iconManager.splashScreen());
}
else if (m_prefsManager.appPrefs.uiPrefs.stylePalette == "light" && QApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark)
{
- QApplication::styleHints()->setColorScheme(Qt::ColorScheme::Light);
-
- // https://bugreports.qt.io/browse/QTBUG-132929
-#if (defined Q_OS_LINUX)
- QPalette pal(QColor(239, 239, 239));
- QApplication::setPalette(pal);
-#endif
+ scStyle->setApplicationTheme(ScribusProxyStyle::ApplicationTheme::Light);
m_SplashScreen->setPixmap(m_iconManager.splashScreen());
}
+ else
+ scStyle->setApplicationTheme(ScribusProxyStyle::ApplicationTheme::System);
#endif
- // Configure GUI
- const QString& prefsUiStyle = m_prefsManager.appPrefs.uiPrefs.style;
- if (prefsUiStyle.length() > 0)
- {
- QStyle* qtStyle = nullptr;
- QStringList availableStyles = QStyleFactory::keys();
- if (availableStyles.contains(prefsUiStyle))
- qtStyle = QStyleFactory::create(prefsUiStyle);
- if (qtStyle)
- QApplication::setStyle(qtStyle);
- else
- m_prefsManager.appPrefs.uiPrefs.style.clear();
- }
+ qApp->setStyle(scStyle);
+ qApp->installEventFilter(scStyle);
+
QFont apf = QApplication::font();
apf.setPointSize(m_prefsManager.appPrefs.uiPrefs.applicationFontSize);
QApplication::setFont(apf);
Index: scribus/third_party/CMakeLists.txt
===================================================================
--- scribus/third_party/CMakeLists.txt (Revision 27132)
+++ scribus/third_party/CMakeLists.txt (Arbeitskopie)
@@ -1,6 +1,4 @@
-#if(WANT_QTADS)
-add_subdirectory(Qt-Advanced-Docking-System)
-#endif()
+add_subdirectory(KDDockWidgets)
if(HAVE_OSG)
add_subdirectory(prc)
Index: scribus/ui/aligndistribute.cpp
===================================================================
--- scribus/ui/aligndistribute.cpp (Revision 27132)
+++ scribus/ui/aligndistribute.cpp (Arbeitskopie)
@@ -65,10 +65,9 @@
// =============================
-AlignDistributePalette::AlignDistributePalette(QWidget* parent) : DockPanelBase("AlignDistributePalette", "panel-align-distribute", parent)
+AlignDistributePalette::AlignDistributePalette() : DockPanelBase("AlignDistributePalette", "panel-align-distribute")
{
setSizePolicy( QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
- setObjectName("AlignDistributePalette");
ad = new AlignDistribute(this);
setWidget(ad);
@@ -92,7 +91,7 @@
resize( QSize(100, 100).expandedTo(minimumSizeHint()) );
languageChange();
- init();
+ setup();
setDoc(nullptr);
connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
@@ -113,6 +112,7 @@
void AlignDistributePalette::languageChange()
{
ad->retranslateUi(this);
+ setWindowTitle( tr("Align and Distribute"));
referenceGuideTooltipTemplate = tr("Align relative to a guide%1");
@@ -173,7 +173,7 @@
ad->distributeByDistanceLabel->setLabelVisibility(v);
}
-void AlignDistributePalette::init()
+void AlignDistributePalette::setup()
{
undoManager = UndoManager::instance();
Index: scribus/ui/aligndistribute.h
===================================================================
--- scribus/ui/aligndistribute.h (Revision 27132)
+++ scribus/ui/aligndistribute.h (Arbeitskopie)
@@ -67,7 +67,7 @@
Q_OBJECT
public:
- AlignDistributePalette( QWidget* parent = nullptr);
+ AlignDistributePalette();
~AlignDistributePalette() = default;
virtual void setDoc( ScribusDoc* newDoc );
@@ -121,7 +121,7 @@
void alignMethodChanged(int);
private:
- void init();
+ void setup();
void enableGuideButtons();
UndoManager *undoManager { nullptr };
Index: scribus/ui/bookmarkpalette.cpp
===================================================================
--- scribus/ui/bookmarkpalette.cpp (Revision 27132)
+++ scribus/ui/bookmarkpalette.cpp (Arbeitskopie)
@@ -25,7 +25,7 @@
#include "bookmarkpalette.h"
-BookPalette::BookPalette(QWidget* parent) : DockPanelBase( "Books", "panel-bookmarks", parent )
+BookPalette::BookPalette() : DockPanelBase( "Books", "panel-bookmarks")
{
setObjectName(QString::fromLocal8Bit("Books"));
setMinimumSize( QSize(220, 240) );
Index: scribus/ui/bookmarkpalette.h
===================================================================
--- scribus/ui/bookmarkpalette.h (Revision 27132)
+++ scribus/ui/bookmarkpalette.h (Arbeitskopie)
@@ -50,7 +50,7 @@
\param parent Parent Window
\retval None
*/
- BookPalette(QWidget* parent);
+ BookPalette();
~BookPalette() {};
BookmarkView *BView;
Index: scribus/ui/contentpalette.cpp
===================================================================
--- scribus/ui/contentpalette.cpp (Revision 27132)
+++ scribus/ui/contentpalette.cpp (Arbeitskopie)
@@ -25,8 +25,7 @@
#include "styles/paragraphstyle.h"
#include "styles/charstyle.h"
-ContentPalette::ContentPalette(QWidget *parent) :
- DockPanelBase("ContentPalette", "panel-content-properties", parent)
+ContentPalette::ContentPalette() : DockPanelBase("ContentPalette", "panel-content-properties")
{
setObjectName(QString::fromLocal8Bit("ContentPalette"));
@@ -34,7 +33,7 @@
f.setPointSize(f.pointSize()-1);
setFont(f);
- stackedWidget = new StackedContainer(this);
+ stackedWidget = new StackedContainer(this);
defaultPal = new ContentPalette_Default(this);
stackedWidget->addWidget(defaultPal);
@@ -276,7 +275,7 @@
updatePanelTitle();
}
updateGeometry();
- DockPanelBase::update();
+ DockPanelBase::update();
}
void ContentPalette::unitChange()
@@ -319,7 +318,7 @@
languageChange();
return;
}
- DockPanelBase::changeEvent(e);
+ DockPanelBase::changeEvent(e);
}
void ContentPalette::updatePanelTitle()
@@ -364,7 +363,7 @@
void ContentPalette::update(const ParagraphStyle& style)
{
- textPal->updateParagraphStyle(style);
+ textPal->updateParagraphStyle(style);
}
void ContentPalette::update(const CharStyle& style)
@@ -378,7 +377,7 @@
void ContentPalette::updateTextStyles()
{
- textPal->updateTextStyles();
+ textPal->updateTextStyles();
}
void ContentPalette::updateTextAlignment(int i)
Index: scribus/ui/contentpalette.h
===================================================================
--- scribus/ui/contentpalette.h (Revision 27132)
+++ scribus/ui/contentpalette.h (Arbeitskopie)
@@ -8,9 +8,9 @@
#define CONTENTPALETTE_H
#include "scribusapi.h"
-#include "docks/dock_panelbase.h"
+#include "docks/dock_panelbase.h"
#include "scguardedptr.h"
-#include "widgets/stacked_container.h"
+#include "widgets/stacked_container.h"
class QStackedWidget;
@@ -29,12 +29,12 @@
class ParagraphStyle;
class CharStyle;
-class SCRIBUS_API ContentPalette : public DockPanelBase
+class SCRIBUS_API ContentPalette : public DockPanelBase
{
Q_OBJECT
public:
- ContentPalette(QWidget* parent);
+ ContentPalette();
~ContentPalette() {}
void updateColorList();
@@ -75,7 +75,7 @@
double m_unitRatio {1.0};
int m_unitIndex {0};
- StackedContainer* stackedWidget {nullptr};
+ StackedContainer* stackedWidget {nullptr};
ContentPalette_Default* defaultPal {nullptr};
PropertiesPalette_Group* groupPal {nullptr};
PropertiesPalette_Image* imagePal {nullptr};
Index: scribus/ui/docks/dock_centralwidget.cpp
===================================================================
--- scribus/ui/docks/dock_centralwidget.cpp (Revision 27132)
+++ scribus/ui/docks/dock_centralwidget.cpp (Arbeitskopie)
@@ -18,11 +18,17 @@
***************************************************************************/
#include "dock_centralwidget.h"
-DockCentralWidget::DockCentralWidget(QWidget *parent)
- : ads::CDockWidget(QString(), parent)
+DockCentralWidget::DockCentralWidget() : QWidget(nullptr)
{
setObjectName(QString::fromLocal8Bit("DockCentralWidget"));
- setFeature(ads::CDockWidget::NoTab, true);
- setFeature(ads::CDockWidget::DockWidgetFloatable, false);
+ layoutWidget = new QHBoxLayout();
+ layoutWidget->setSpacing(0);
+ layoutWidget->setContentsMargins(0, 0, 0, 0);
+ setLayout(layoutWidget);
}
+
+void DockCentralWidget::setWidget(QWidget *widget)
+{
+ layoutWidget->addWidget(widget);
+}
Index: scribus/ui/docks/dock_centralwidget.h
===================================================================
--- scribus/ui/docks/dock_centralwidget.h (Revision 27132)
+++ scribus/ui/docks/dock_centralwidget.h (Arbeitskopie)
@@ -20,14 +20,20 @@
#ifndef DOCK_CENTRALWIDGET_H
#define DOCK_CENTRALWIDGET_H
-#include "third_party/Qt-Advanced-Docking-System/src/DockWidget.h"
+#include <QWidget>
+#include <QHBoxLayout>
-class DockCentralWidget : public ads::CDockWidget
+class DockCentralWidget : public QWidget
{
Q_OBJECT
public:
- explicit DockCentralWidget(QWidget *parent = nullptr);
+ explicit DockCentralWidget();
+ void setWidget(QWidget *widget);
+
+private:
+ QHBoxLayout *layoutWidget;
+
};
#endif // DOCK_CENTRALWIDGET_H
Index: scribus/ui/docks/dock_panelbase.cpp
===================================================================
--- scribus/ui/docks/dock_panelbase.cpp (Revision 27132)
+++ scribus/ui/docks/dock_panelbase.cpp (Arbeitskopie)
@@ -20,6 +20,8 @@
#include "dock_panelbase.h"
#include <QApplication>
+#include <QScrollBar>
+#include <QTabBar>
#include "iconmanager.h"
#include "prefscontext.h"
@@ -26,26 +28,22 @@
#include "prefsfile.h"
#include "prefsmanager.h"
#include "scribusapp.h"
+#include "scribuscore.h"
+#include "scribus.h"
-DockPanelBase::DockPanelBase(const QString &title, QString iconName, QWidget *parent)
- : CDockWidget(title, parent)
+#include <kddockwidgets/core/Stack.h>
+
+// LayoutSaverOption see: https://github.com/KDAB/KDDockWidgets/blob/main/src/KDDockWidgets.h
+
+DockPanelBase::DockPanelBase(const QString &title, QString iconName, KDDockWidgets::DockWidgetOptions options)
+ : KDDockWidgets::QtWidgets::DockWidget(title, options, {KDDockWidgets::LayoutSaverOption::None})
{
- /*if (PrefsManager::instance().appPrefs.uiPrefs.useSmallWidgets) {
- setStyleSheet(" QToolButton { margin: 1px; padding: 0px; font-size: 10px; } \
- QToolButton:pressed { padding-top: 2px; padding-left: 2px } \
- QPushButton { margin: 1px; padding: 0px; font-size: 10px; } \
- QPushButton:pressed { padding-top: 2px; padding-left: 2px } \
- QRadioButton, QComboBox, QLineEdit \
- QListView, QLabel { margin:1px; padding: 0px; font-size: 10px; } \
- QCheckBox, QSpinBox, QDoubleSpinBox \
- { margin:1px; padding: 0px; font-size: 10px; } \
- QTabWidget, QTabBar, QTableView, QGroupBox, QTreeView \
- { font-size: 10px ; } \
- QToolBox::tab { font-size: 10px; padding: 0px; margin: 0px; } \
- ");
- }*/
-
m_iconName = iconName;
+ m_scrollArea = new QScrollArea;
+ m_scrollArea->setFrameShape(QFrame::NoFrame);
+ m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ KDDockWidgets::QtWidgets::DockWidget::setWidget(m_scrollArea);
iconSetChange();
@@ -53,10 +51,14 @@
setObjectName(title);
connect(&PrefsManager::instance(), SIGNAL(prefsChanged()), this, SLOT(setFontSize()));
connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
+ // We need all 3 signals to change the visibility of the palette title
+ connect(this, &KDDockWidgets::QtWidgets::DockWidget::isCurrentTabChanged, this, &DockPanelBase::setLabelVisibility);
+ connect(this, &KDDockWidgets::QtWidgets::DockWidget::isOpenChanged, this, &DockPanelBase::setLabelVis);
+ connect(this, &KDDockWidgets::QtWidgets::DockWidget::isFloatingChanged, this, &DockPanelBase::setLabelVis);
}
-DockPanelBase::DockPanelBase(const QString &title, QWidget *parent)
- : DockPanelBase(title, QString(), parent){}
+DockPanelBase::DockPanelBase(const QString &title, KDDockWidgets::DockWidgetOptions options)
+ : DockPanelBase(title, QString(), options){}
void DockPanelBase::setPrefsContext(const QString &context)
{
@@ -69,6 +71,27 @@
m_palettePrefs = nullptr;
}
+void DockPanelBase::updateScrollAreaMinSize()
+{
+ if (!widget())
+ return;
+
+ int contentWidth = widget()->minimumSizeHint().width();
+ int frameWidth = m_scrollArea->frameWidth() * 2;
+ int scrollBarWidth = m_scrollArea->verticalScrollBar()->sizeHint().width();
+
+ m_scrollArea->setMinimumWidth(contentWidth + frameWidth + scrollBarWidth);
+}
+
+bool DockPanelBase::eventFilter(QObject *watched, QEvent *event)
+{
+ if (watched == widget() && event->type() == QEvent::Resize)
+ updateScrollAreaMinSize();
+
+ return QWidget::eventFilter(watched, event);
+
+}
+
void DockPanelBase::startup()
{
setFontSize();
@@ -87,13 +110,89 @@
if(m_iconName.isEmpty())
{
- setWindowIcon(iconManager.loadPixmap("app-icon"));
+ setWindowIcon(iconManager.loadIcon("app-icon"));
setIcon(QIcon());
}
else
{
- setWindowIcon(iconManager.loadPixmap(m_iconName));
- setIcon(iconManager.loadPixmap(m_iconName));
+ setWindowIcon(iconManager.loadIcon(m_iconName));
+ setIcon(iconManager.loadIcon(m_iconName));
}
}
+
+void DockPanelBase::setToggleViewAction(ScrAction *action)
+{
+ // # Classic toggle behavior
+ // action->setCheckable(true);
+ // connect( action, &ScrAction::toggled, toggleAction(), &QAction::setChecked);
+ // connect( toggleAction(), &QAction::toggled, action, &ScrAction::setChecked);
+
+
+ // # Activate dock behavior
+ action->setCheckable(false);
+ connect(action, &QAction::triggered, this, [action, this]()
+ {
+ // restore hidden workspace
+ DockManager::instance().restoreHiddenWorkspace();
+ open();
+ setAsCurrentTab();
+
+ });
+}
+
+void DockPanelBase::setLabelVisibility(bool visible)
+{
+ KDDockWidgets::Core::DockWidget *dock = this->asDockWidgetController();
+
+ if (!dock)
+ return;
+
+ bool noLabel = !PrefsManager::instance().appPrefs.uiPrefs.showLabelsOfInactiveTabs;
+
+ // inactive Tab in tabbed group
+ if (noLabel && dock->isTabbed() && !visible)
+ setTitle( QString() );
+ else
+ setTitle( m_title );
+}
+
+void DockPanelBase::setLabelVis()
+{
+ KDDockWidgets::Core::DockWidget *dock = this->asDockWidgetController();
+
+ if (!dock)
+ return;
+
+ bool noLabel = !PrefsManager::instance().appPrefs.uiPrefs.showLabelsOfInactiveTabs;
+
+ // inactive Tab in tabbed group
+ if (noLabel && dock->isTabbed() && !dock->isCurrentTab())
+ setTitle( QString() );
+ else
+ setTitle( m_title );
+
+}
+
+void DockPanelBase::setWindowTitle(const QString &title)
+{
+ KDDockWidgets::QtWidgets::DockWidget::setWindowTitle(title);
+ m_title = title;
+ if (!this->title().isEmpty())
+ setTitle( title );
+}
+
+void DockPanelBase::setWidget(QWidget *widget)
+{
+ widget->adjustSize();
+ widget->installEventFilter(this);
+ m_scrollArea->setWidget(widget);
+ m_scrollArea->setWidgetResizable(true);
+
+ updateScrollAreaMinSize();
+}
+
+QWidget *DockPanelBase::widget() const
+{
+ return m_scrollArea->widget();
+}
Index: scribus/ui/docks/dock_panelbase.h
===================================================================
--- scribus/ui/docks/dock_panelbase.h (Revision 27132)
+++ scribus/ui/docks/dock_panelbase.h (Arbeitskopie)
@@ -21,32 +21,44 @@
#define DOCK_PANELBASE_H
#include "scribusapi.h"
-#include "third_party/Qt-Advanced-Docking-System/src/DockWidget.h"
-using namespace ads;
+#include "scraction.h"
+#include <kddockwidgets/DockWidget.h>
+#include <QScrollArea>
class PrefsContext;
-class SCRIBUS_API DockPanelBase : public CDockWidget
+class SCRIBUS_API DockPanelBase : public KDDockWidgets::QtWidgets::DockWidget
{
Q_OBJECT
public:
- DockPanelBase(const QString &title, QWidget *parent = 0);
- DockPanelBase(const QString &title, QString iconName, QWidget *parent = 0);
+ DockPanelBase(const QString &title, KDDockWidgets::DockWidgetOptions options = KDDockWidgets::DockWidgetOption_None);
+ DockPanelBase(const QString &title, QString iconName, KDDockWidgets::DockWidgetOptions options = KDDockWidgets::DockWidgetOption_None);
void startup();
+ void setWindowTitle(const QString& title) override;
+ void setWidget(QWidget *widget);
+ QWidget *widget() const;
public slots:
virtual void setFontSize();
void iconSetChange();
+ void setToggleViewAction(ScrAction *action);
+ void setLabelVisibility(bool visible);
+ void setLabelVis();
protected:
/** @brief Set the Preferences context to be used for storage of startup visibility and position and size */
virtual void setPrefsContext(const QString &context);
+ void updateScrollAreaMinSize();
+ bool eventFilter(QObject *watched, QEvent *event) override;
PrefsContext *m_palettePrefs {nullptr};
QString m_prefsContextName;
QString m_iconName;
+ QScrollArea *m_scrollArea;
+ QString m_title;
+
};
#endif // DOCK_PANELBASE_H
Index: scribus/ui/inlinepalette.cpp
===================================================================
--- scribus/ui/inlinepalette.cpp (Revision 27132)
+++ scribus/ui/inlinepalette.cpp (Arbeitskopie)
@@ -101,7 +101,7 @@
clearSelection();
}
-InlinePalette::InlinePalette( QWidget* parent) : DockPanelBase("Inline", "panel-inline-items", parent)
+InlinePalette::InlinePalette() : DockPanelBase("Inline", "panel-inline-items")
{
setContentsMargins(3, 3, 3, 3);
setMinimumSize( QSize( 220, 240 ) );
Index: scribus/ui/inlinepalette.h
===================================================================
--- scribus/ui/inlinepalette.h (Revision 27132)
+++ scribus/ui/inlinepalette.h (Arbeitskopie)
@@ -72,7 +72,7 @@
Q_OBJECT
public:
- InlinePalette(QWidget* parent);
+ InlinePalette();
~InlinePalette() {};
void setMainWindow(ScribusMainWindow *mw);
Index: scribus/ui/layers.cpp
===================================================================
--- scribus/ui/layers.cpp (Revision 27132)
+++ scribus/ui/layers.cpp (Arbeitskopie)
@@ -42,7 +42,7 @@
#include "docks/dock_panelbase.h"
#include "undomanager.h"
-LayerPalette::LayerPalette(QWidget* parent) : DockPanelBase("Layers", "panel-layers", parent)
+LayerPalette::LayerPalette() : DockPanelBase("Layers", "panel-layers")
{
setObjectName(QString::fromLocal8Bit("Layers"));
setMinimumSize( QSize(220, 240) );
Index: scribus/ui/layers.h
===================================================================
--- scribus/ui/layers.h (Revision 27132)
+++ scribus/ui/layers.h (Arbeitskopie)
@@ -34,7 +34,7 @@
Q_OBJECT
public:
- LayerPalette(QWidget* parent);
+ LayerPalette();
~LayerPalette() {};
void installEventFilter(QObject *);
Index: scribus/ui/outlinepalette.cpp
===================================================================
--- scribus/ui/outlinepalette.cpp (Revision 27132)
+++ scribus/ui/outlinepalette.cpp (Arbeitskopie)
@@ -431,7 +431,7 @@
return true;
}
-OutlinePalette::OutlinePalette( QWidget* parent) : DockPanelBase("Tree", "panel-outline", parent)
+OutlinePalette::OutlinePalette() : DockPanelBase("Tree", "panel-outline")
{
// resize( 220, 240 );
setMinimumSize( QSize( 220, 240 ) );
@@ -481,9 +481,9 @@
connect(filterEdit, SIGNAL(textChanged(QString)), this, SLOT(filterTree(QString)));
// connect(filterShortcut, SIGNAL(activated()), filterEdit, SLOT(setFocus()));
connect(reportDisplay, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(slotDoubleClick(QTreeWidgetItem*,int)));
- connect(this, SIGNAL(visibilityChanged(bool)), this, SLOT(rebuildTree()));
+ connect(this, SIGNAL(isOpenChanged(bool)), this, SLOT(rebuildTree(bool)));
+ connect(this, SIGNAL(isCurrentTabChanged(bool)), this, SLOT(rebuildTree(bool)));
-
}
void OutlinePalette::setMainWindow(ScribusMainWindow *mw)
@@ -509,16 +509,9 @@
clearPalette();
}
-void OutlinePalette::toggleView(bool visible)
+void OutlinePalette::rebuildTree(bool isActive)
{
- DockPanelBase::toggleView(visible);
- rebuildTree();
-}
-
-
-void OutlinePalette::rebuildTree()
-{
- if (this->isVisible() && (currDoc != nullptr))
+ if (isActive)
BuildTree();
}
Index: scribus/ui/outlinepalette.h
===================================================================
--- scribus/ui/outlinepalette.h (Revision 27132)
+++ scribus/ui/outlinepalette.h (Arbeitskopie)
@@ -60,7 +60,7 @@
Q_OBJECT
public:
- OutlinePalette( QWidget* parent );
+ OutlinePalette();
void setMainWindow(ScribusMainWindow *mw);
void setDoc(ScribusDoc *);
@@ -77,7 +77,6 @@
void iconSetChange();
void languageChange();
void slotShowSelect(int pageNr, PageItem *pageItem);
- void toggleView(bool);
void slotRightClick(QPoint point);
void setActiveLayer(int layerID);
void setLayerVisible(int layerID);
@@ -96,7 +95,7 @@
void slotMultiSelect();
void slotSelect(QTreeWidgetItem* ite, int col);
void slotDoubleClick(QTreeWidgetItem* ite, int col);
- void rebuildTree();
+ void rebuildTree(bool);
protected:
void changeEvent(QEvent *e) override;
Index: scribus/ui/pagepalette.cpp
===================================================================
--- scribus/ui/pagepalette.cpp (Revision 27132)
+++ scribus/ui/pagepalette.cpp (Arbeitskopie)
@@ -21,7 +21,7 @@
#include "scribusdoc.h"
#include "scribusview.h"
-PagePalette::PagePalette(QWidget *parent) : DockPanelBase("PagePalette", "panel-page", parent)
+PagePalette::PagePalette() : DockPanelBase("PagePalette", "panel-page")
{
m_scMW = nullptr;//(ScribusMainWindow*) parent;
m_view = nullptr;
@@ -210,7 +210,7 @@
}
// Set focus to page palette or focus may be set to wrong document window
- this->setFocus();
+ //this->setFocus();
stackedWidget->setCurrentIndex(1);
setWindowTitle( tr( "Manage Masterpages" ) );
}
@@ -220,7 +220,7 @@
if (this->stackedWidget()->currentIndex() > 0)
{
// Set focus to page palette or focus may be set to wrong document window
- this->setFocus();
+ //this->setFocus();
this->stackedWidget()->setCurrentIndex(0);
}
Index: scribus/ui/pagepalette.h
===================================================================
--- scribus/ui/pagepalette.h (Revision 27132)
+++ scribus/ui/pagepalette.h (Arbeitskopie)
@@ -37,7 +37,7 @@
Q_OBJECT
public:
- PagePalette(QWidget *parent);
+ PagePalette();
~PagePalette() {};
QWidget* currentWidget();
Index: scribus/ui/propertiespalette.cpp
===================================================================
--- scribus/ui/propertiespalette.cpp (Revision 27132)
+++ scribus/ui/propertiespalette.cpp (Arbeitskopie)
@@ -45,11 +45,11 @@
#include "selection.h"
#include "undomanager.h"
-PropertiesPalette::PropertiesPalette(QWidget *parent) : DockPanelBase("PropertiesPalette", "panel-frame-properties", parent)
+PropertiesPalette::PropertiesPalette() : DockPanelBase("PropertiesPalette", "panel-frame-properties")
{
undoManager = UndoManager::instance();
- setObjectName(QString::fromLocal8Bit("PropertiesPalette"));
+ // setObjectName(QString::fromLocal8Bit("PropertiesPalette"));
setSizePolicy( QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
// XZY
Index: scribus/ui/propertiespalette.h
===================================================================
--- scribus/ui/propertiespalette.h (Revision 27132)
+++ scribus/ui/propertiespalette.h (Arbeitskopie)
@@ -55,7 +55,7 @@
Q_OBJECT
public:
- PropertiesPalette(QWidget* parent);
+ PropertiesPalette();
~PropertiesPalette() {}
void endPatchAdd();
Index: scribus/ui/scrapbookpalette.cpp
===================================================================
--- scribus/ui/scrapbookpalette.cpp (Revision 27132)
+++ scribus/ui/scrapbookpalette.cpp (Arbeitskopie)
@@ -740,7 +740,7 @@
}
/* This is the main Dialog-Class for the Scrapbook */
-Biblio::Biblio(QWidget* parent) : DockPanelBase("Sclib", "panel-scrapbook", parent)
+Biblio::Biblio() : DockPanelBase("Sclib", "panel-scrapbook")
{
setObjectName(QString::fromLocal8Bit("Sclib"));
setMinimumSize( QSize(220, 240) );
Index: scribus/ui/scrapbookpalette.h
===================================================================
--- scribus/ui/scrapbookpalette.h (Revision 27132)
+++ scribus/ui/scrapbookpalette.h (Arbeitskopie)
@@ -73,7 +73,7 @@
Q_OBJECT
public:
- Biblio( QWidget* parent);
+ Biblio();
~Biblio() {};
void changeEvent(QEvent *e) override;
Index: scribus/ui/symbolpalette.cpp
===================================================================
--- scribus/ui/symbolpalette.cpp (Revision 27132)
+++ scribus/ui/symbolpalette.cpp (Arbeitskopie)
@@ -150,7 +150,7 @@
clearSelection();
}
-SymbolPalette::SymbolPalette( QWidget* parent) : DockPanelBase("Symb", "panel-symbols", parent)
+SymbolPalette::SymbolPalette() : DockPanelBase("Symb", "panel-symbols")
{
setContentsMargins(3, 3, 3, 3);
setMinimumSize( QSize( 220, 240 ) );
Index: scribus/ui/symbolpalette.h
===================================================================
--- scribus/ui/symbolpalette.h (Revision 27132)
+++ scribus/ui/symbolpalette.h (Arbeitskopie)
@@ -76,7 +76,7 @@
Q_OBJECT
public:
- SymbolPalette(QWidget* parent);
+ SymbolPalette();
~SymbolPalette() {};
void setMainWindow(ScribusMainWindow *mw);
Index: scribus/undogui.cpp
===================================================================
--- scribus/undogui.cpp (Revision 27132)
+++ scribus/undogui.cpp (Arbeitskopie)
@@ -38,7 +38,7 @@
#include "undogui.h"
-UndoGui::UndoGui(QWidget* parent, const char* name) : DockPanelBase(name, "panel-action-history", parent)
+UndoGui::UndoGui(QWidget* parent, const char* name) : DockPanelBase(name, "panel-action-history")
{
languageChange();
}
|
|
|
Few more notes. KDDockWidgets MainWindow already saves the window geometry and position together with the dock panel workspace in "mainwinstate" in the prefs file. So I commented out all previous code to save this information. If you want to reset the dock panel layout, you can delete the "mainwinstate" in prefs file. Next, "Show Labels on Inactive Palette Tabs" in preferences has no function anymore, because I decided to remove the label of grouped docks. I kept the setting in case we want to have back the labels. At the moment, it is possible to group all panels into one dock. Good for small screens. :) And I could not find the reason why the docks from plugins are broken. The only solution for now is to link KDDock as dynamic library. |
|
|
On my computer it still does not run "correctly" with the dynamic library. I need to set `export LD_LIBRARY_PATH=~/bin/build/scribus-tmp/lib/` to get Scribus to launch. (oops, I see that I wrote the same when testing the previous version : - ) |
|
|
Now "Custom Shapes" seem to be working correctly! Thanks. From the points mentioned above, the properties palette still has a "useless" top title that shows the current active tab... And now the tabs are not left aligned... But it |
|
|
@ale something is wrong with the tab style. The tabs are centered by purpose, but they should look like in my screenshot. It is possible to hide the additional title bar via configuration. I thought it could be nice to have a title bar that relates to the selected tab. The pin and close button relates to the selected tab, too. Please, can you just remove a line of code to see if the style applies correctly? In my tests, it was enough to override the proxy style in the custom title bar widget only. third_party/KDDockWidgets/src/qtwidgets/view/TabBar.cpp
TabBar::TabBar(Core::TabBar *controller, QWidget *parent)
: View(controller, Core::ViewType::TabBar, parent)
, TabBarViewInterface(controller)
, d(new Private(controller))
{
setShape(Config::self().tabsAtBottom() ? QTabBar::RoundedSouth : QTabBar::RoundedNorth);
// setStyle(proxyStyle()); <-- this line
}
|
|
|
On the one side, I think I prefer having left aligned tabs. If I'm correct, on Mac there are widgets that are centered, but on my system and in "my" Scribus everything is left aligned. Removing the setStyle() mentioned above indeed shows the tabs as icons only, like in your screenshots. Personally, I would suggest adding two options for hiding the title bar and displaying the tabs as icons, when there are multiple tabs in a panel. But, as far as I understand it, the pin and close buttons are only available in the title bar... This might be an issue if the user hides the title bar. Not sure what KDDock provides there. And the user On the other side, I don't really like how the existing option "Show labels of inactive palette tabs" works, when it's not enabled. Too much "Unruhe" for little to none (or even negative) gain. (If I need more information about the tab, it's when I'm selecting one, among the inactive ones, I normally recognize the active one by its content...) I would suggest to remove that option. Two cosmetics things: - When first starting Scribus (with new configs), the "Custom Shapes" window is attached to the right of the of the left stack of panels. Way too slim. I'm not sure that it should be shown at all by default. And it should probably not be attached (there) by default. - The View toolbar gets "automatically" reactivated when restarting Scribus. (I hide it, restart Scribus, it's there again) All this having been said, working with this tab system feels smooth, once I got used to the incredible amount of choices for the docking areas : - ) Good work! |
|
|
@cbradney I updated the ads library to version 5 and enabled wayland in Scribus. Works so far on Ubuntu 26.04 There are two patches. A full version that includes ADS 5 and a small version with only scribus relevant changes (but you have to download the v5 release candidate from GitHub). ads5_2026-07-02_01.diff (948,690 bytes)
diff --git a/scribus/CMakeLists.txt b/scribus/CMakeLists.txt
index 8308fc4af..1dafac139 100644
--- a/scribus/CMakeLists.txt
+++ b/scribus/CMakeLists.txt
@@ -294,7 +294,7 @@ target_link_libraries(${EXE_NAME} PRIVATE
)
#if(WANT_QTADS)
- target_link_libraries(${EXE_NAME} PUBLIC qt6advanceddocking)
+target_link_libraries(${EXE_NAME} PUBLIC qtadvanceddocking-qt${QT_VERSION_MAJOR})
#endif()
if(WITH_TESTS)
diff --git a/scribus/main_nix.cpp b/scribus/main_nix.cpp
index 94566fd86..7ae10366e 100644
--- a/scribus/main_nix.cpp
+++ b/scribus/main_nix.cpp
@@ -67,8 +67,9 @@ int mainApp(int argc, char **argv)
{
emergencyActivated = false;
+// Fallback if the Linux OS doesn't support wayland
#if !defined(Q_OS_MACOS)
- qputenv("QT_QPA_PLATFORM", "xcb");
+ qputenv("QT_QPA_PLATFORM", "wayland;xcb");
#endif
QImageReader::setAllocationLimit(1024);
@@ -78,24 +79,7 @@ int mainApp(int argc, char **argv)
app.parseCommandLine();
FcInit();
-
- if (QApplication::platformName() == "wayland")
- {
- QString errHdr = QObject::tr("Fatal Error");
- QString errMsg = QObject::tr("Scribus does not support the Wayland platform. Use XWayland to run Scribus on Wayland. Scribus will close now.");
- if (app.useGUI)
- {
- QMessageBox::critical(nullptr, errHdr, errMsg);
- }
- else
- {
- std::cout << errHdr.toStdString() << std::endl;
- std::cout << "-------------" << std::endl;
- std::cout << errMsg.toStdString() << std::endl;
- }
- return EXIT_FAILURE;
- }
-
+
int appRetVal = app.init();
if (appRetVal == EXIT_FAILURE)
return(EXIT_FAILURE);
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/.appveyor.yml b/scribus/third_party/Qt-Advanced-Docking-System/.appveyor.yml
deleted file mode 100644
index 9771255f3..000000000
--- a/scribus/third_party/Qt-Advanced-Docking-System/.appveyor.yml
+++ /dev/null
@@ -1,151 +0,0 @@
-version: '{build}'
-branches:
- only:
- - master
-
-image: Visual Studio 2017
-
-environment:
- global:
- # Appveyor doesn't have Qt 12 yet
- LatestQtVersion: 5.13
- matrix:
-# 32 bit builds
-# MSVC 2015 builds
-# Dynamic Library builds
- # LTS version of Qt, dll, 32bit, MSVC 2015, qmake
- - QT5: C:\Qt\%LatestQtVersion%\msvc2017
- COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
- targetPlatform: x86
- use_mingw: "false"
- use_static: "false"
- use_cmake: "false"
- # LTS version of Qt, dll, 32bit, MSVC 2015, cmake
- - QT5: C:\Qt\%LatestQtVersion%\msvc2017
- COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
- targetPlatform: x86
- use_mingw: "false"
- use_static: "false"
- use_cmake: "true"
-# end Dynamic Library builds
-# Static Library builds
- # LTS version of Qt, static, 32bit, MSVC 2015, qmake
- - QT5: C:\Qt\%LatestQtVersion%\msvc2017
- COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
- targetPlatform: x86
- use_mingw: "false"
- use_static: "true"
- use_cmake: "false"
- # LTS version of Qt, static, 32bit, MSVC 2015, cmake
- - QT5: C:\Qt\%LatestQtVersion%\msvc2017
- COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
- targetPlatform: x86
- use_mingw: "false"
- use_static: "true"
- use_cmake: "true"
-# end Static Library builds
-# end MSVC 2015 builds
-# MinGW builds
-# Dynamic Library builds
- # LTS version of Qt, dll, 32bit, MinGW, qmake
- - QT5: C:\Qt\%LatestQtVersion%\mingw73_32
- COMPILER: C:\Qt\Tools\mingw730_32
- targetPlatform: x86
- use_mingw: "true"
- use_static: "false"
- use_cmake: "false"
- # LTS version of Qt, dll, 32bit, MinGW, cmake
- - QT5: C:\Qt\%LatestQtVersion%\mingw73_32
- COMPILER: C:\Qt\Tools\mingw730_32
- targetPlatform: x86
- use_mingw: "true"
- use_static: "false"
- use_cmake: "true"
-# end Dynamic Library builds
-# Static Library builds
- # LTS version of Qt, static, 32bit, MinGW, qmake
- - QT5: C:\Qt\%LatestQtVersion%\mingw73_32
- COMPILER: C:\Qt\Tools\mingw730_32
- targetPlatform: x86
- use_mingw: "true"
- use_static: "true"
- use_cmake: "false"
- # LTS version of Qt, static, 32bit, MinGW, cmake
- - QT5: C:\Qt\%LatestQtVersion%\mingw73_32
- COMPILER: C:\Qt\Tools\mingw730_32
- targetPlatform: x86
- use_mingw: "true"
- use_static: "true"
- use_cmake: "true"
-# end Static Library builds
-# end MinGW builds
-# end 32 bit builds
-# 64 bit builds
-# MSVC 2015 builds
-# Dynamic Library builds
- # LTS version of Qt, dll, 64bit, MSVC 2015, qmake
- - QT5: C:\Qt\%LatestQtVersion%\msvc2017_64
- COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
- targetPlatform: amd64
- use_mingw: "false"
- use_static: "false"
- use_cmake: "false"
- # LTS version of Qt, dll, 64bit, MSVC 2015, cmake
- - QT5: C:\Qt\%LatestQtVersion%\msvc2017_64
- COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
- targetPlatform: amd64
- use_mingw: "false"
- use_static: "false"
- use_cmake: "true"
-# end Dynamic Library builds
-# Static Library builds
- # LTS version of Qt, static, 64bit, MSVC 2015, qmake
- - QT5: C:\Qt\%LatestQtVersion%\msvc2017_64
- COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
- targetPlatform: amd64
- use_mingw: "false"
- use_static: "true"
- use_cmake: "false"
- # LTS version of Qt, static, 64bit, MSVC 2015, cmake
- - QT5: C:\Qt\%LatestQtVersion%\msvc2017_64
- COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
- targetPlatform: amd64
- use_mingw: "false"
- use_static: "true"
- use_cmake: "true"
-# end Static Library builds
-# end MSVC 2015 builds
-# end 64 bit builds
-
-matrix:
- fast_finish: true
-
-before_build:
-- set originalWD=%CD%
-- call "%QT5%\bin\qtenv2.bat"
-- cd /D %originalWD%
-- if %use_mingw%==false call "%COMPILER%\vcvarsall.bat" %targetPlatform%
-- if %use_static%==true (set USESTATIC=ON) else (set USESTATIC=OFF)
-- if %use_mingw%==true (set CMAKEGENERATOR="MinGW Makefiles") else (set CMAKEGENERATOR="NMake Makefiles")
-- if %use_mingw%==true (set MAKEENGINE=mingw32-make) else (set MAKEENGINE=nmake)
-- if %use_mingw%==true set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
-
-build_script:
-- if %use_cmake%==true mkdir build
-- if %use_cmake%==true cd build
-- if %use_cmake%==true cmake --version
-- if %use_cmake%==true cmake -G %CMAKEGENERATOR% -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_EXAMPLES=ON -DCMAKE_DEBUG_POSTFIX=d -DBUILD_STATIC=%USESTATIC% -DCMAKE_INSTALL_PREFIX="./installed" ../
-- if %use_cmake%==true cmake --build .
-- if %use_cmake%==true cmake --build . --target install
-- if %use_cmake%==true cmake -G %CMAKEGENERATOR% -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_EXAMPLES=ON -DBUILD_STATIC=%USESTATIC% -DCMAKE_INSTALL_PREFIX="./installed" ../
-- if %use_cmake%==true cmake --build .
-- if %use_cmake%==true cmake --build . --target install
-- if %use_cmake%==false if %use_static%==true qmake "CONFIG+=adsBuildStatic"
-- if %use_cmake%==false if %use_static%==false qmake
-- if %use_cmake%==false %MAKEENGINE% debug
-- if %use_cmake%==false %MAKEENGINE% install
-- if %use_cmake%==false %MAKEENGINE% release
-- if %use_cmake%==false %MAKEENGINE% install
-
-after_build:
-- if %use_mingw%==true set PATH=C:\Program Files\Git\usr\bin;%PATH%
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/.clang-format b/scribus/third_party/Qt-Advanced-Docking-System/.clang-format
new file mode 100644
index 000000000..f044fe5d7
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/.clang-format
@@ -0,0 +1,146 @@
+---
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AlignConsecutiveMacros: None
+AlignConsecutiveAssignments: None
+AlignConsecutiveDeclarations: None
+AlignEscapedNewlines: Right
+AlignOperands: Align
+AlignTrailingComments: true
+
+AllowAllArgumentsOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: Never
+AllowShortCaseLabelsOnASingleLine: true
+AllowShortFunctionsOnASingleLine: InlineOnly
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLambdasOnASingleLine: Inline
+AllowShortLoopsOnASingleLine: false
+
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: Yes
+
+BinPackArguments: true
+BinPackParameters: true
+
+BraceWrapping:
+ AfterCaseLabel: true
+ AfterClass: true
+ AfterControlStatement: Always
+ AfterEnum: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterStruct: true
+ AfterUnion: true
+ AfterExternBlock: true
+ BeforeCatch: true
+ BeforeElse: true
+ BeforeLambdaBody: false
+ IndentBraces: false
+ SplitEmptyFunction: false
+ SplitEmptyRecord: false
+ SplitEmptyNamespace: false
+
+BreakBeforeBinaryOperators: NonAssignment
+BreakBeforeBraces: Custom
+BreakBeforeTernaryOperators: false
+BreakConstructorInitializers: BeforeColon
+BreakInheritanceList: AfterColon
+BreakStringLiterals: true
+
+ColumnLimit: 82
+CommentPragmas: '^(!.*|@c)'
+
+CompactNamespaces: false
+
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+
+FixNamespaceComments: true
+
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: '^<windows(\.h)?>' # windows headers
+ Priority: -1
+ - Regex: '^<labbcan[[:alnum:]._/]+' # labbcan headers
+ Priority: 1
+ - Regex: '^<diag[[:alnum:]._/]+' # usl headers
+ Priority: 1
+ - Regex: '^<usl[[:alnum:]._/]+' # usl headers
+ Priority: 1
+ - Regex: '^<qt5compat[[:alnum:]._/]+' # qtlabb headers
+ Priority: 2
+ - Regex: '^<qtcoreaddons[[:alnum:]._/]+' # qtlabb headers
+ Priority: 2
+ - Regex: '^<qtlabb[[:alnum:]._/]+' # qtlabb headers
+ Priority: 2
+ - Regex: '<Q[[:alnum:].]+>' # Qt headers
+ Priority: 3
+ - Regex: '^<sila_cpp[[:alnum:]._/]+' # sila_cpp headers
+ Priority: 4
+ - Regex: '<[[:alnum:]._/]+\.h>' # other headers
+ Priority: 5
+ - Regex: '<[[:alnum:]._/]+>' # system headers
+ Priority: 6
+ - Regex: '.*'
+ Priority: 7
+
+IncludeIsMainRegex: '(_p)?$'
+
+IndentCaseBlocks: false
+IndentCaseLabels: false
+IndentPPDirectives: AfterHash
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+
+KeepEmptyLinesAtTheStartOfBlocks: false
+MaxEmptyLinesToKeep: 1
+
+NamespaceIndentation: None
+
+PenaltyBreakAssignment: 20
+PenaltyBreakBeforeFirstCallParameter: 15
+PenaltyBreakComment: 10
+PenaltyBreakFirstLessLess: 5
+# PenaltyBreakOpenParenthesis: 30
+PenaltyBreakString: 150
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 100
+PenaltyIndentedWhitespace: 0
+PenaltyReturnTypeOnItsOwnLine: 150
+
+PointerAlignment: Left
+ReflowComments: true
+
+SortIncludes: CaseSensitive
+SortUsingDeclarations: true
+
+SpaceAfterCStyleCast: false
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: false
+
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatements
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceBeforeSquareBrackets: false
+SpaceInEmptyBlock: false
+SpaceInEmptyParentheses: false
+
+SpacesBeforeTrailingComments: 2
+SpacesInAngles: Never
+SpacesInCStyleCastParentheses: false
+SpacesInConditionalStatement: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+
+Standard: c++17
+
+StatementMacros: [ 'Q_UNUSED', 'PIMPL_D', 'PIMPL_Q', 'OD_ENTRY', 'OD_ENTRY_PROCIMG' ]
+
+TabWidth: 4
+UseTab: Never
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/.gitattributes b/scribus/third_party/Qt-Advanced-Docking-System/.gitattributes
new file mode 100644
index 000000000..f75bc5b72
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/.gitattributes
@@ -0,0 +1 @@
+PyQtAds/_version.py export-subst
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/.gitignore b/scribus/third_party/Qt-Advanced-Docking-System/.gitignore
new file mode 100644
index 000000000..2a7ed562d
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/.gitignore
@@ -0,0 +1,389 @@
+*.pro.user*
+/build
+*.o
+*.dylib
+*.app
+qrc_*
+moc_*
+ui_*
+Makefile
+*.dll
+*.a
+build*
+
+# IDEs
+.idea
+
+# Python
+.eggs
+*.pyc
+*.pyd
+__pycache__
+PyQtAds/rc.py
+/.cproject
+
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+/ build
+/Settings.ini
+.vscode/settings.json
+/.settings
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/.project b/scribus/third_party/Qt-Advanced-Docking-System/.project
deleted file mode 100644
index 9c7157bd5..000000000
--- a/scribus/third_party/Qt-Advanced-Docking-System/.project
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>QtAdvancedDockingSystem</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
- <triggers>clean,full,incremental,</triggers>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
- <triggers>full,incremental,</triggers>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.cdt.core.cnature</nature>
- <nature>org.eclipse.cdt.core.ccnature</nature>
- <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
- <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
- </natures>
-</projectDescription>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/.travis.yml b/scribus/third_party/Qt-Advanced-Docking-System/.travis.yml
deleted file mode 100644
index 38db61fc9..000000000
--- a/scribus/third_party/Qt-Advanced-Docking-System/.travis.yml
+++ /dev/null
@@ -1,233 +0,0 @@
-language: cpp
-# gcc is clang on mac
-compiler: gcc
-
-matrix:
- fast_finish: true
- include:
- - name: Ubuntu qmake Qt5.5.1
- os: linux
- dist: trusty
- group: stable
- addons:
- apt:
- sources:
- - ubuntu-toolchain-r-test
- - sourceline: 'ppa:beineri/opt-qt551-trusty'
- update: true
- packages:
- - qt55base
- - qt55tools
- - gcc-9
- - g++-9
- script:
- - PATH="/opt/qt55/bin:$PATH"
- - CXX="g++-9"
- - CC="gcc-9"
- - qt55-env.sh
- - qmake
- - make
- - make install
- - name: Ubuntu qmake dll
- os: linux
- dist: bionic
- group: stable
- services:
- - xvfb
- compiler: gcc
- addons:
- apt:
- sources:
- - ubuntu-toolchain-r-test
- - sourceline: 'ppa:beineri/opt-qt-5.14.2-bionic'
- update: true
- packages:
- - qt514base
- - qt514tools
- - gcc-9
- - g++-9
- - libc6-i386
- - libgl-dev
- - libgl1-mesa-dev
- - mesa-common-dev
- script:
- - PATH="/opt/qt514/bin:$PATH"
- - CXX="g++-9"
- - CC="gcc-9"
- - qt514-env.sh
- - qmake
- - make
- - make install
- - name: Ubuntu qmake static
- os: linux
- dist: bionic
- group: stable
- services:
- - xvfb
- compiler: gcc
- addons:
- apt:
- sources:
- - ubuntu-toolchain-r-test
- - sourceline: 'ppa:beineri/opt-qt-5.14.2-bionic'
- update: true
- packages:
- - qt514base
- - qt514tools
- - gcc-9
- - g++-9
- - libc6-i386
- - libgl-dev
- - libgl1-mesa-dev
- - mesa-common-dev
- script:
- - PATH="/opt/qt514/bin:$PATH"
- - CXX="g++-9"
- - CC="gcc-9"
- - qt514-env.sh
- - qmake "CONFIG+=adsBuildStatic"
- - make
- - make install
- - name: Ubuntu CMake dll
- os: linux
- dist: bionic
- group: stable
- services:
- - xvfb
- compiler: gcc
- addons:
- apt:
- sources:
- - ubuntu-toolchain-r-test
- - sourceline: 'ppa:beineri/opt-qt-5.14.2-bionic'
- update: true
- packages:
- - qt514base
- - qt514tools
- - gcc-9
- - g++-9
- - libc6-i386
- - libgl-dev
- - libgl1-mesa-dev
- - mesa-common-dev
- script:
- - PATH="/opt/qt514/bin:$PATH"
- - CXX="g++-9"
- - CC="gcc-9"
- - qt514-env.sh
- - mkdir ./build
- - cd ./build
- - cmake --version
- - cmake -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_STATIC=OFF -DBUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX="./installed" ../
- - cmake --build .
- - cmake --build . --target install
- - cmake -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_STATIC=OFF -DBUILD_EXAMPLES=ON -DCMAKE_DEBUG_POSTFIX=d -DCMAKE_INSTALL_PREFIX="./installed" ../
- - cmake --build .
- - cmake --build . --target install
- - name: Ubuntu CMake Static
- os: linux
- dist: bionic
- group: stable
- services:
- - xvfb
- compiler: gcc
- addons:
- apt:
- sources:
- - ubuntu-toolchain-r-test
- - sourceline: 'ppa:beineri/opt-qt-5.14.2-bionic'
- update: true
- packages:
- - qt514base
- - qt514tools
- - gcc-9
- - g++-9
- - libc6-i386
- - libgl-dev
- - libgl1-mesa-dev
- - mesa-common-dev
- script:
- - PATH="/opt/qt514/bin:$PATH"
- - CXX="g++-9"
- - CC="gcc-9"
- - qt514-env.sh
- - mkdir ./build
- - cd ./build
- - cmake --version
- - cmake -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_STATIC=ON -DBUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX="./installed" ../
- - cmake --build .
- - cmake --build . --target install
- - cmake -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_STATIC=ON -DBUILD_EXAMPLES=ON -DCMAKE_DEBUG_POSTFIX=d -DCMAKE_INSTALL_PREFIX="./installed" ../
- - cmake --build .
- - cmake --build . --target install
- - name: macOS CMake dll
- os: osx
- osx_image: xcode11.3
- compiler: clang
- addons:
- homebrew:
- packages:
- - qt
- update: true
- script:
- - PATH="/usr/local/opt/qt5/bin:$PATH"
- - mkdir -p build
- - cd build
- - cmake --version
- - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=DEBUG -DCMAKE_DEBUG_POSTFIX=_debug -DBUILD_EXAMPLES=ON -DBUILD_STATIC=OFF -DCMAKE_INSTALL_PREFIX="./installed" ../
- - cmake --build .
- - cmake --build . --target install
- - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_EXAMPLES=ON -DBUILD_STATIC=OFF -DCMAKE_INSTALL_PREFIX="./installed" ../
- - cmake --build .
- - cmake --build . --target install
- - name: macOS CMake static
- os: osx
- osx_image: xcode11.3
- compiler: clang
- addons:
- homebrew:
- packages:
- - qt
- update: true
- script:
- - PATH="/usr/local/opt/qt5/bin:$PATH"
- - mkdir -p build
- - cd build
- - cmake --version
- - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=DEBUG -DCMAKE_DEBUG_POSTFIX=_debug -DBUILD_EXAMPLES=ON -DBUILD_STATIC=ON -DCMAKE_INSTALL_PREFIX="./installed" ../
- - cmake --build .
- - cmake --build . --target install
- - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_EXAMPLES=ON -DBUILD_STATIC=ON -DCMAKE_INSTALL_PREFIX="./installed" ../
- - cmake --build .
- - cmake --build . --target install
- - name: macOS qmake dll
- os: osx
- osx_image: xcode11.3
- compiler: clang
- addons:
- homebrew:
- packages:
- - qt
- update: true
- script:
- - PATH="/usr/local/opt/qt5/bin:$PATH"
- - qmake
- - make
- - make install
- - name: macOS qmake static
- os: osx
- osx_image: xcode11.3
- compiler: clang
- addons:
- homebrew:
- packages:
- - qt
- update: true
- script:
- - PATH="/usr/local/opt/qt5/bin:$PATH"
- - qmake "CONFIG+=adsBuildStatic"
- - make
- - make install
-notifications:
- email: false
-
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/CMakeLists.txt b/scribus/third_party/Qt-Advanced-Docking-System/CMakeLists.txt
index 2a807197e..2dbcbdb08 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/CMakeLists.txt
+++ b/scribus/third_party/Qt-Advanced-Docking-System/CMakeLists.txt
@@ -1,30 +1,39 @@
###<< Scribus
-set(ADS_VERSION "4.3.0")
+set(ADS_VERSION "5.0.0")
###>> Scribus
cmake_minimum_required(VERSION 3.16)
-
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if (POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif (POLICY CMP0091)
+# Add cmake modules path (required for Versioning.cmake and git revision description)
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
+
# By default, the version information is extracted from the git index. However,
# we can override this behavior by explicitly setting ADS_VERSION and
# skipping the git checks. This is useful for cases where this project is being
# used independently of its original git repo (e.g. vendored in another project)
if(NOT ADS_VERSION)
- set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
include(GetGitRevisionDescription)
git_describe(GitTagVersion --tags)
string(REGEX REPLACE "^([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GitTagVersion}")
string(REGEX REPLACE "^[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GitTagVersion}")
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GitTagVersion}")
set(VERSION_SHORT "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
+ set(VERSION_SONAME "${VERSION_MAJOR}")
else()
string(REGEX MATCHALL "[\.]" VERSION_DOT_MATCHES ${ADS_VERSION})
list(LENGTH VERSION_DOT_MATCHES VERSION_DOT_COUNT)
if(VERSION_DOT_COUNT EQUAL 2)
set(VERSION_SHORT ${ADS_VERSION})
+ string(REGEX REPLACE "^([0-9]+)\\..*" "\\1" VERSION_SONAME "${ADS_VERSION}")
+ # Set PROJECT_VERSION_* variables for Versioning.cmake
+ string(REGEX MATCHALL "[0-9]+" VERSION_PARTS "${ADS_VERSION}")
+ list(GET VERSION_PARTS 0 PROJECT_VERSION_MAJOR)
+ list(GET VERSION_PARTS 1 PROJECT_VERSION_MINOR)
+ list(GET VERSION_PARTS 2 PROJECT_VERSION_PATCH)
else()
message(FATAL_ERROR "ADS_VERSION must be in major.minor.patch format, e.g. 3.8.1. Got ${ADS_VERSION}")
endif()
@@ -37,10 +46,15 @@ project(QtADS LANGUAGES CXX VERSION ${VERSION_SHORT})
option(BUILD_STATIC "Build the static library" ON)
option(BUILD_EXAMPLES "Build the examples" OFF)
-if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
- set(ads_PlatformDir "x86")
+# Platform directory: auto-detected based on pointer size, or manually set
+if(NOT ADS_PLATFORM_DIR)
+ if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
+ set(ads_PlatformDir "x86")
+ else()
+ set(ads_PlatformDir "x64")
+ endif()
else()
- set(ads_PlatformDir "x64")
+ set(ads_PlatformDir "${ADS_PLATFORM_DIR}")
endif()
add_subdirectory(src)
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/README.md b/scribus/third_party/Qt-Advanced-Docking-System/README.md
index ca76dbaf6..b777976f5 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/README.md
+++ b/scribus/third_party/Qt-Advanced-Docking-System/README.md
@@ -4,10 +4,10 @@
------------------
-[](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/latest)
+[](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/latest)
[](gnu-lgpl-v2.1.md)
[](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/actions?query=workflow%3Alinux-builds)
-[](https://ci.appveyor.com/project/githubuser0xFFFF/qt-advanced-docking-system/branch/master)
+[](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/actions/workflows/windows-cmake.yml)
[](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/graphs/contributors)
Qt Advanced Docking System lets you create customizable layouts using a full
@@ -15,14 +15,62 @@ 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
+- [Documentation](https://githubuser0xffff.github.io/Qt-Advanced-Docking-System/doc/user-guide.html)
+- Original Repository: [https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System)
[](https://www.youtube.com/watch?v=7pdNfafg3Qc)
## 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
+### Release 5.0
+
+#### Full Dark Mode Support
+
+Thanks to the [contribution](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/pull/842) from [Vojtěch Miškovský](https://github.com/miskovoj), Qt ADS now provides full dark mode support with automatic theme switching. This includes:
+
+- New stylesheets and icons
+- Automatic detection of the current theme (light/dark)
+- Automatic palette update propagation to user widgets
+
+
+
+[read more...](doc/user-guide.md#default-style-sheet)
+
+#### Native Wayland Support
+
+Thanks to the outstanding contributions of [Matt Liberty](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/pull/844),
+the creator of [Joulescope](#joulescope), and [Davide Faconti](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/pull/837), the creator of [PlotJuggler](#plot-juggler), Qt ADS now provides native
+Wayland support, making Linux desktop environments such as GNOME and KDE first-class platforms for the Advanced Docking System.
+
+
+
+Previous versions relied on mechanisms that are not supported by the Wayland protocol, resulting in
+incorrect drag previews and broken docking behavior. The new implementation adopts Wayland-native
+APIs while preserving the familiar Qt ADS user experience.
+
+Highlights include:
+
+- Full support for docking, undocking, and re-docking floating windows on Wayland
+- Accurate drag previews and correctly positioned docking overlays
+- Hybrid drag behavior: smooth in-window docking with seamless transition to native compositor-managed window dragging
+- Platform-specific implementation that affects only Wayland—Windows, macOS, and X11 continue to use the existing, proven code path
+- Improved compatibility with modern Linux desktop environments while maintaining the same intuitive docking workflow across all platforms
+
+With these changes, Qt ADS now offers a reliable and polished docking experience on native Wayland without sacrificing compatibility or behavior on other operating systems.
+
+### Release 4.5
+
+#### Tabs at Bottom
+
+A new global dock manager flag `TabsAtBottom` has been added to configuration flags. This flag allows to configure if the tabs of dock areas are shown at the top (default) or at the bottom of the respective container.
+
+If the flag is set, tabs will be shown at the bottom instead of in the title bar.
+
+
+
+### Release 4.1
+
+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
@@ -57,7 +105,7 @@ That means, you can drag them to a different border or sidebar:
#### Auto-Hide Tab Sorting
-You can drag Auto-Hide tabs to a new position in the current sidebar
+You can drag Auto-Hide tabs to a new position in the current sidebar
to sort them:

@@ -81,7 +129,7 @@ sidebar:
#### 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
+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):

@@ -141,6 +189,12 @@ know it from Visual Studio.
### Overview
- [New and Noteworthy](#new-and-noteworthy)
+ - [Release 5.0](#release-50)
+ - [Full Dark Mode Support](#full-dark-mode-support)
+ - [Native Wayland Support](#native-wayland-support)
+ - [Release 4.5](#release-45)
+ - [Tabs at Bottom](#tabs-at-bottom)
+ - [Release 4.1](#release-41)
- [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)
@@ -161,12 +215,14 @@ know it from Visual Studio.
- [Auto-Hide Functionality](#auto-hide-functionality)
- [Python Bindings](#python-bindings)
- [PySide6](#pyside6)
+ - [PyQt6](#pyqt6)
- [PyQt5](#pyqt5)
- [Tested Compatible Environments](#tested-compatible-environments)
- [Supported Qt Versions](#supported-qt-versions)
- [Windows](#windows)
- [macOS](#macos)
- [Linux](#linux)
+ - [Wayland](#wayland)
- [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)
@@ -189,8 +245,10 @@ know it from Visual Studio.
- [RDE – Robox Development Environment](#rde--robox-development-environment)
- [ResInsight](#resinsight)
- [ADTF 3](#adtf-3)
- - [DREAM.3D NX](#dream3d-nx)
+ - [DREAM3D-NX](#dream3d-nx)
- [LabPlot](#labplot)
+ - [Scrutiny Debugger](#scrutiny-debugger)
+ - [PiSoWorks](#pisoworks)
- [Alternative Docking System Implementations](#alternative-docking-system-implementations)
- [KDDockWidgets](#kddockwidgets)
- [QtitanDocking](#qtitandocking)
@@ -217,7 +275,7 @@ into floating windows is supported.
### Grouped dragging
-When dragging the titlebar of a dock, all the tabs that are tabbed with it are
+When dragging the titlebar of a dock, all the tabs that are tabbed with it are
going to be dragged. So you can move complete groups of tabbed widgets into
a floating widget or from one dock area to another one.
@@ -230,7 +288,7 @@ a floating widget or from one dock area to another one.
A perspective defines the set and layout of dock windows in the main
window. You can save the current layout of the dockmanager into a named
perspective to make your own custom perspective. Later you can simply
-select a perspective from the perspective list to quickly switch the complete
+select a perspective from the perspective list to quickly switch the complete
main window layout.

@@ -252,6 +310,7 @@ If this flag is cleared, the widget resizing is deferred until the mouse button
In contrast to the standard Qt docking system, docking with the ADS works more like a drag & 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
- `DragPreviewShowsContentPixmap`: the created drag preview window shows a static copy of the content of the dock widget / dock are that is dragged
- `DragPreviewHasWindowFrame`: this flag configures if the drag preview is frameless like a QRubberBand or looks like a real window
@@ -308,7 +367,7 @@ More about the auto hide configuration options in the [online documentation...](

Thanks to the contribution of several users, the Advanced Docking System comes
-with a complete Python integration. Python bindings are available for **PyQt5** and
+with a complete Python integration. Python bindings are available for **PyQt5**, **PyQt6**, and
**PySide6**.
### PySide6
@@ -321,13 +380,30 @@ 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).
+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)
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.
+### PyQt6
+
+A PyQt6 ADS package is available via PyPi and can be installed on Windows,
+macOS, and Linux with:
+
+```bash
+pip install PyQt6Ads
+```
+
+Sample code is available [here](https://github.com/pyapp-kit/PyQt6Ads/tree/main/examples).
+
+The PyQt6 bindings were contributed by:
+
+- [tlambert03](https://github.com/tlambert03)
+
+Please file PyQt6Ads-specific issues at [pyapp-kit/PyQt6Ads](https://github.com/pyapp-kit/PyQt6Ads).
+
### PyQt5
A package is available via [conda-forge](https://github.com/conda-forge/pyqtads-feedstock).
@@ -351,21 +427,19 @@ The library supports **Qt5** and **Qt6**.
### Windows
-Windows 10 [](https://ci.appveyor.com/project/githubuser0xFFFF/qt-advanced-docking-system/branch/master)
+Windows 10 / 11
+[](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/actions/workflows/windows-cmake.yml)
The library was developed on and for Windows. It is used in a commercial Windows application and is therefore constantly tested.
### macOS
-macOS [](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
-
The application can be compiled for macOS. A user reported, that the library works on macOS. If have not tested it.

### Linux
-[](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
[](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 it is possible for Windows. It is only possible to support and test a small subset of Linux distributions. The library can be compiled for and has been developed and tested with some Linux distributions. Depending on the used window manager or compositor, dock widgets
@@ -374,12 +448,12 @@ the library switches to `QWidget` based title bars.
- **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
+- **Ubuntu 22.04 and later** - uses Wayland -> native title bars (see [Wayland](#wayland) below)
There are some requirements for the Linux distribution that have to be met:
- an X server that supports ARGB visuals and a compositing window manager. This is required to display the translucent dock overlays ([https://doc.qt.io/qt-5/qwidget.html#creating-translucent-windows](https://doc.qt.io/qt-5/qwidget.html#creating-translucent-windows)). If your Linux distribution does not support this, or if you disable this feature, you will very likely see issue [#95](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/95).
-- Wayland is not properly supported by Qt yet. If you use Wayland, then you should set the session type to x11: `XDG_SESSION_TYPE=x11 ./AdvancedDockingSystemDemo`. You will find more details about this in issue [#288](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/288).
+- On Wayland the dock overlays are rendered as child widgets and this requirement does not apply.
Screenshot Kubuntu:

@@ -387,6 +461,27 @@ Screenshot Kubuntu:
Screenshot Ubuntu:

+#### Wayland
+
+Since Qt 6.6.3 docking is supported on Wayland. Earlier Qt versions do not implement the `xdg_toplevel_drag_v1` protocol that is required to drag a floating window with the cursor, so on those versions you should still set the session type to X11 (XWayland): `XDG_SESSION_TYPE=x11 ./AdvancedDockingSystemDemo`. You will find more details in issues [#288](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/288) and [#714](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/714).
+
+Wayland does not allow a client to move its own top level windows in screen coordinates or to query the global cursor position, so docking is implemented differently than on the other platforms. This results in a few behavioral differences on Wayland:
+
+- Floating dock containers always use native window decorations (the custom
+ `QWidget` title bar is not available), because the custom title bar cannot
+ move the window.
+- Undocking and re-docking use a compositor driven drag (the floating window
+ itself follows the cursor) instead of the translucent drag preview.
+- The compositor controls the window stacking, so floating windows are not
+ forced to stay on top of the main window.
+- Saved layouts restore the docked arrangement, the floating-window sizes and
+ their maximized/normal state, but **not** the on-screen position of floating
+ windows (the same applies to the application's own main window). Wayland does
+ not let a client position its top-level windows, so the compositor decides
+ where restored windows appear. Restoring positions requires compositor side
+ session management (the staging `xx-session-management-v1` protocol), which is
+ not yet available through Qt.
+
## Build
The Linux build requires private header files. Make sure that they are installed.
@@ -462,7 +557,7 @@ MainWindow::MainWindow(QWidget *parent) :
// Create the dock manager after the ui is setup. Because the
// parent parameter is a QMainWindow the dock manager registers
// itself as the central widget as such the ui must be set up first.
- m_DockManager = new ads::CDockManager(this);
+ DockManager = new ads::CDockManager(this);
// Create example content label - this can be any application specific
// widget
@@ -473,7 +568,7 @@ MainWindow::MainWindow(QWidget *parent) :
// Create a dock widget with the title Label 1 and set the created label
// as the dock widget content
- ads::CDockWidget* DockWidget = new ads::CDockWidget("Label 1");
+ ads::CDockWidget* DockWidget = DockManager->createDockWidget("Label 1");
DockWidget->setWidget(l);
// Add the toggleViewAction of the dock widget to the menu to give
@@ -481,7 +576,7 @@ MainWindow::MainWindow(QWidget *parent) :
ui->menuView->addAction(DockWidget->toggleViewAction());
// Add the dock widget to the top dock widget area
- m_DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);
+ DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);
}
MainWindow::~MainWindow()
@@ -582,7 +677,7 @@ highlights are:
- Simple Drag & Drop user interface.
- Load data from file.
- Connect to live streaming of data.
-- Save the visualization layout and configurations to re-use them later.
+- Save the visualization layout and configurations to reuse them later.
- Fast OpenGL visualization.
- Can handle thousands of timeseries and millions of data points.
- Transform your data using a simple editor: derivative, moving average, integral, etc…
@@ -594,7 +689,7 @@ highlights are:
### [Notepad Next](https://github.com/dail8859/NotepadNext)
-Notepad Next is a cross-platform reimplementation of Notepad++ that uses the
+Notepad Next is a cross-platform reimplementation of Notepad++ that uses the
Advanced Docking System to arrange the open source files on the screen.
[read more...](https://github.com/dail8859/NotepadNext)
@@ -657,7 +752,7 @@ The Automotive Data and Time-Triggered Framework was designed as a Rapid Prototy
- 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
+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:
@@ -667,15 +762,19 @@ says about the switch to Qt Advanced Docking:

-### [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.
+### [DREAM3D-NX](https://www.dream3d.io)
+
+DREAM3D-NX *(Digital Representation Environment for Analysis of Materials in 3D)* is a 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.
+[BlueQuartz Software](http://www.bluequartz.net/) has completely rewritten the old DREAM.3D version 6.5 application
+taking advantage of the Advanced Docking System to present a highly customizable user interface
+for DREAM3D-NX Version 7.
+
+[read more...](http://www.dream3d.io/)

-[read more...](http://dream3d.bluequartz.net/)
### [LabPlot](https://labplot.kde.org/)
@@ -683,9 +782,53 @@ KDE LabPlot is the ultimate free, open source and cross-platform tool for scient
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.
+[read more...](https://labplot.kde.org/)
+

-[read more...](https://labplot.kde.org/)
+
+### [Scrutiny Debugger](https://scrutinydebugger.com/)
+
+Scrutiny is an [open source](https://github.com/scrutinydebugger/) non-intrusive, real-time debugger for embedded systems, built for fast introspection, memory access, and signal visualization—without stopping your application. It uses the Qt Advanced Docking System (ADS) to provide fully customizable dashboards for monitoring and control.
+
+Some of the highlights are:
+
+- **Debug without interfering** — Inspect C++ memory live without disrupting execution flow.
+- **HIL testing made easy** — Write to variables through the GUI or SDK to simulate conditions.
+- **Configure during production** — Access and tweak variables anytime via GUI or Python.
+- **Catch fast events** — Embedded graphs sample at task-level frequency, even with multithreading.
+- **Build your dashboard** — Use ADS to create and save custom layouts for your debug sessions.
+- **No JTAG needed** — Communicates over serial, CAN, or network interfaces.
+- **Compact C++11 library** — Lightweight and easy to integrate into your firmware.
+- **Live graphs and runtime values** — Visualize variables, RPVs, and aliases in real time.
+
+ADS powers Scrutiny’s flexible interface, letting users organize views and data panels to suit their workflow — ideal for real-time monitoring, testing, and debugging.
+
+[read more...](https://scrutinydebugger.com/)
+
+[](https://www.youtube.com/watch?v=Dd3osxW-Clo)
+
+
+### [PiSoWorks](https://pypi.org/project/pisoworks/)
+
+PiSoWorks is an application for controlling the piezo amplifiers, such as the [NV200/D](https://www.piezosystem.com/product/nv-200-d-compact-amplifier/), from [piezosystem jena](https://www.piezosystem.com/) GmbH.
+
+[read more...](https://piezosystemjena.github.io/PiSoWorks/multiple_devices.html)
+
+
+
+
+### [Joulescope](https://www.joulescope.com/)
+
+**Joulescope** is a professional desktop application for precision current, voltage, power, and energy analysis, widely used by embedded systems engineers to optimize the energy consumption of their hardware and firmware. Its highly customizable, dockable user interface has been powered by Qt Advanced Docking System (Qt ADS) for many years, making it an excellent real-world validation of the library.
+
+Matt Liberty, the creator of Joulescope, made a [major contribution](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/pull/844) to Qt ADS by implementing native Wayland support. His work brings a reliable and polished docking experience to modern Linux desktop environments while preserving the existing behavior on Windows, macOS, and X11.
+
+Thanks to this contribution, Qt ADS now delivers a first-class docking experience on Wayland and is ready for the next generation of Linux desktop environments.
+
+[read more...](https://www.joulescope.com/)
+
+
## Alternative Docking System Implementations
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/cmake/modules/FileVersionInfo.rc.in b/scribus/third_party/Qt-Advanced-Docking-System/cmake/modules/FileVersionInfo.rc.in
new file mode 100644
index 000000000..812b1ae92
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/cmake/modules/FileVersionInfo.rc.in
@@ -0,0 +1,29 @@
+#include <windows.h>
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
+ PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS 0
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE 0
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "My Company\0"
+ VALUE "FileDescription", "@PROJECT_NAME@\0"
+ VALUE "FileVersion", "@PROJECT_VERSION_STRING@\0"
+ VALUE "ProductVersion", "@PROJECT_VERSION_STRING@\0"
+ VALUE "GitCommitFull", "@PROJECT_GIT_HASH@\0"
+ VALUE "GitCommitShort", "@PROJECT_GIT_HASH_SHORT@\0"
+ END
+ END
+
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0409, 1200
+ END
+END
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/cmake/modules/Versioning.cmake b/scribus/third_party/Qt-Advanced-Docking-System/cmake/modules/Versioning.cmake
new file mode 100644
index 000000000..282828d9d
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/cmake/modules/Versioning.cmake
@@ -0,0 +1,100 @@
+# ============================================================
+# Versioning.cmake (Reusable Version + Resource Generator)
+# ============================================================
+
+# Freeze the directory where this module lives
+# This is critical — it prevents paths from breaking when the
+# function is invoked from other CMakeLists.txt files.
+set(_VERSIONING_MODULE_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "Versioning module directory")
+
+# ------------------------------------------------------------
+# Extract version information from Git or use predefined version
+# ------------------------------------------------------------
+if(NOT DEFINED PROJECT_VERSION_MAJOR OR NOT DEFINED PROJECT_VERSION_MINOR OR NOT DEFINED PROJECT_VERSION_PATCH)
+ # Get tag (expected: v1.2.3 or 1.2.3 or 1.2.3-12-gHASH)
+ execute_process(
+ COMMAND git describe --tags --dirty
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ OUTPUT_VARIABLE GIT_DESC_RAW
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+
+ # Remove leading "v" if present
+ string(REGEX REPLACE "^v" "" GIT_DESC "${GIT_DESC_RAW}")
+
+ # Extract major.minor.patch
+ string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)" _ "${GIT_DESC}")
+ set(PROJECT_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ set(PROJECT_VERSION_MINOR "${CMAKE_MATCH_2}")
+ set(PROJECT_VERSION_PATCH "${CMAKE_MATCH_3}")
+
+
+
+ # Commit hash (full + short)
+ execute_process(
+ COMMAND git rev-parse HEAD
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ OUTPUT_VARIABLE PROJECT_GIT_HASH
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+
+ execute_process(
+ COMMAND git rev-parse --short HEAD
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ OUTPUT_VARIABLE PROJECT_GIT_HASH_SHORT
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+endif()
+
+set(PROJECT_VERSION_STRING
+ "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}"
+)
+
+# Export variables to parent scope
+set(PROJECT_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}" PARENT_SCOPE)
+set(PROJECT_VERSION_MINOR "${PROJECT_VERSION_MINOR}" PARENT_SCOPE)
+set(PROJECT_VERSION_PATCH "${PROJECT_VERSION_PATCH}" PARENT_SCOPE)
+set(PROJECT_VERSION_STRING "${PROJECT_VERSION_STRING}" PARENT_SCOPE)
+set(PROJECT_GIT_HASH "${PROJECT_GIT_HASH}" PARENT_SCOPE)
+set(PROJECT_GIT_HASH_SHORT "${PROJECT_GIT_HASH_SHORT}" PARENT_SCOPE)
+
+# Public variable for users
+set(PROJECT_AUTO_VERSION "${PROJECT_VERSION_STRING}" PARENT_SCOPE)
+
+# ------------------------------------------------------------
+# Reusable function: Attach Windows version resources to target
+# ------------------------------------------------------------
+function(add_windows_version_resources target)
+ if(NOT WIN32)
+ return()
+ endif()
+
+ if(NOT TARGET "${target}")
+ message(FATAL_ERROR "add_windows_version_resources: target '${target}' not found.")
+ endif()
+
+ # Absolute path to the template (never changes)
+ get_filename_component(_rc_in
+ "${_VERSIONING_MODULE_DIR}/FileVersionInfo.rc.in"
+ ABSOLUTE
+ )
+
+ if(NOT EXISTS "${_rc_in}")
+ message(FATAL_ERROR
+ "FileVersionInfo.rc.in missing at: ${_rc_in}"
+ )
+ endif()
+
+ # Output in the caller's binary dir
+ set(_rc_out "${CMAKE_CURRENT_BINARY_DIR}/${target}_version.rc")
+ get_filename_component(_rc_out "${_rc_out}" ABSOLUTE)
+
+ # Ensure directory exists
+ file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+
+ # Configure the template
+ configure_file("${_rc_in}" "${_rc_out}" @ONLY)
+
+ # Add to the target
+ target_sources(${target} PRIVATE "${_rc_out}")
+endfunction()
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/doc/DarkMode.png b/scribus/third_party/Qt-Advanced-Docking-System/doc/DarkMode.png
new file mode 100644
index 000000000..f66a886f5
Binary files /dev/null and b/scribus/third_party/Qt-Advanced-Docking-System/doc/DarkMode.png differ
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/doc/DarkModeOverlay.png b/scribus/third_party/Qt-Advanced-Docking-System/doc/DarkModeOverlay.png
new file mode 100644
index 000000000..1b9c4689d
Binary files /dev/null and b/scribus/third_party/Qt-Advanced-Docking-System/doc/DarkModeOverlay.png differ
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/doc/Wayland_Logo.svg b/scribus/third_party/Qt-Advanced-Docking-System/doc/Wayland_Logo.svg
new file mode 100644
index 000000000..45f8d8e44
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/doc/Wayland_Logo.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="266" height="266" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<title>Wayland logo</title>
+ <g transform="translate(-208.6 -332.1)">
+ <circle cx="341.4" cy="465.2" r="122.9" style="fill:#ffbc00"/>
+ <g transform="scale(.9156 1.092)" style="fill:#fff">
+ <path d="m443.9 314.6h2.35l-1.495 1.495h-0.8544v-1.495m-173 3.631v1.709l-5.554 6.836h-0.8544l-0.8544-5.34c3.275-2.136 5.696-3.204 7.263-3.204m202.5 2.35c4.842 1.9e-4 7.547 3.062 8.117 9.185l-4.059 28.84h1.495l3.204-2.136h0.8544v0.6408c-4.415 2.706-8.687 10.11-12.82 22.22-1.567 10.4-4.201 20.01-7.904 28.84-3.276 9.114-4.913 17.52-4.913 25.21l-6.195 15.17c-1.7e-4 1.282 2.35 2.563 7.049 3.845-0.8546 2.991-2.136 4.486-3.845 4.486v0.8544h1.495v0.6408c-1.7e-4 1.567-2.421 2.35-7.263 2.35l0.8544 0.8544v2.991h-1.495c0.9967 2.991 3.133 4.486 6.408 4.486v1.495h-6.408v0.8544c2.136 4e-5 3.204 1.282 3.204 3.845l-8.972 2.991 0.8544 0.8544v0.6408c-1.6e-4 0.9969-1.068 1.495-3.204 1.495v0.8544c2.706 3e-5 4.058 0.4985 4.059 1.495-3.845 1.282-8.901 7.619-15.17 19.01-6.408 10.11-11.96 15.17-16.66 15.17h-1.709c-3.56-2.279-6.48-9.826-8.758-22.64-9.114-19.51-13.67-30.97-13.67-34.39-1e-4 -8.829-2.919-18.23-8.758-28.2-1.567-4.415-2.635-9.968-3.204-16.66l-3.845-0.8544c-9.684 14.67-14.74 26.13-15.17 34.39-2.706 4.842-4.842 10.68-6.408 17.52 5.839 1.567 8.758 3.062 8.758 4.486v0.8544c-4.557-0.5696-7.761-1.638-9.612-3.204-1.994 3.845-4.628 14.53-7.904 32.04-2.563 8.117-5.768 12.18-9.612 12.18-10.82-3.56-19.87-9.399-27.13-17.52-1.139 2e-5 -2.991-4.059-5.554-12.18-1.566 3e-5 -2.635-4.059-3.204-12.18-5.411-11.53-9.114-24.71-11.11-39.52v-22.22h-0.8544l-3.845 0.8544v-0.8544c1e-5 -0.9967 1.282-1.495 3.845-1.495l-0.8544-12.82v-10.04l-6.195-32.04v-13.67c2.706-8.544 7.405-12.82 14.1-12.82h44.86v1.495c-3.56 0.1426-5.981 0.9258-7.263 2.35-2.706-1.566-5.34-2.35-7.904-2.35h-8.758l-4.913 0.6408-0.8544-0.6408h-0.6408l-6.408 0.6408-3.204-0.6408-2.35 0.6408-2.563-0.6408c10.4 11.39 16.52 21.01 18.37 28.84h7.263v1.495h-5.554v1.709c2.136 6.551 3.703 9.826 4.699 9.826h1.709l3.845-0.8544 0.8544 0.8544 0.8544-0.8544 0.8544 0.8544v0.6408c-2.848 1.709-4.771 4.059-5.767 7.049h-0.6408v1.495h1.495c1.994 23.78 5.696 41.8 11.11 54.04l3.204 2.136h1.709c2.136 8e-5 6.622-8.331 13.46-24.99 4.415-7.547 7.619-14.17 9.612-19.87l-0.8544-2.35c4.415-5.554 8.972-8.331 13.67-8.331h1.495c2.99 1.4e-4 5.127 1.567 6.408 4.699 3.987 4.7 7.191 11.75 9.612 21.15l11.96 22.22c1.566 1.567 2.35 3.347 2.35 5.34 4.414 8.402 8.402 13.96 11.96 16.66h2.563c2.99 6e-5 6.978-10.4 11.96-31.19 0.8543 9e-5 3.204-5.554 7.049-16.66v-0.8544l-13.46-1.495-3.204 0.8544h-4.059v-1.709l8.117-0.6408h15.81c6.123-18.37 11.75-32.61 16.88-42.72 1.709-20.79 4.058-31.19 7.049-31.19l9.612-3.845m-45.5 2.35c-0.8546 1.994-2.706 2.991-5.554 2.991v-1.495l5.554-1.495m-80.53 3.845h21.57v1.495l-4.913 0.6408-4.699-0.6408-4.059 1.495-1.495-1.495h-6.408v-1.495m-112.4 2.991h2.35l1.495 1.495v0.8544l-4.699 4.486v3.845h-1.709v-2.35l0.8544-0.6408v-0.8544l-4.059-3.845c0.9969-1.994 2.919-2.99 5.767-2.991m157 9.185h2.35v0.6408c-1.1e-4 0.997-0.7834 1.495-2.35 1.495l-0.8544 0.8544v0.8544l-2.35-0.8544v-1.495l3.204-1.495m-11.96 8.331v0.8544c-1e-4 1.139-3.418 2.35-10.25 3.631v-1.495l4.699-2.136 0.8544 0.6408h0.6408l4.059-1.495m-139.5 7.69v0.6408l-1.709 1.495-0.6408-0.6408v-0.8544l0.6408-0.6408h1.709m116.4 0v0.6408c-2.991 2.279-7.832 4.344-14.53 6.195v-1.495c1.139 1.5e-4 1.709-0.7831 1.709-2.35l12.82-2.991m40.59 7.476 0.8544 0.8544v0.6408l-1.495 1.709h-0.8544l-1.709-1.709v-0.6408l3.204-0.8544m29.48 0.8544h0.8544v0.6408l-1.495 1.709h-0.8544v-0.8544l1.495-1.495m-13.46 10.68 3.204 2.136c-0.5698 1.567-2.136 2.35-4.699 2.35l-1.709-2.35c-1.3e-4 -0.7119 1.068-1.424 3.204-2.136m19.22 9.826 0.6408 0.8544v0.6408l-0.6408 0.8544h-1.709v-0.8544l1.709-1.495m-30.33 7.69v0.6408l-4.059 3.204h-2.35v-0.8544c-1.1e-4 -1.282 2.136-2.278 6.408-2.991m-132.4 29.69h0.8544v0.6408c-2.136 4.7-3.987 7.548-5.554 8.544h-1.709v-3.204l6.408-5.981m104.5 35.67h0.8544v1.495l-6.408 3.204-0.8544-0.8544v-1.495l6.408-2.35m-87.79 10.04h1.495l2.563 8.331h-1.709l-2.35-7.69v-0.6408m85.44 9.826h0.6408l2.563 2.35-0.8544 0.6408h-0.8544l-1.495-2.136v-0.8544"/>
+ </g>
+ </g>
+</svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/doc/cfg_flag_AutoHideOpenOnDragHover.gif b/scribus/third_party/Qt-Advanced-Docking-System/doc/cfg_flag_AutoHideOpenOnDragHover.gif
new file mode 100644
index 000000000..8b62e26ce
Binary files /dev/null and b/scribus/third_party/Qt-Advanced-Docking-System/doc/cfg_flag_AutoHideOpenOnDragHover.gif differ
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/doc/cfg_flag_TabsAtBottom.png b/scribus/third_party/Qt-Advanced-Docking-System/doc/cfg_flag_TabsAtBottom.png
new file mode 100644
index 000000000..724987a95
Binary files /dev/null and b/scribus/third_party/Qt-Advanced-Docking-System/doc/cfg_flag_TabsAtBottom.png differ
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/doc/cfg_flag_TabsAtBottom_true.png b/scribus/third_party/Qt-Advanced-Docking-System/doc/cfg_flag_TabsAtBottom_true.png
new file mode 100644
index 000000000..63969335f
Binary files /dev/null and b/scribus/third_party/Qt-Advanced-Docking-System/doc/cfg_flag_TabsAtBottom_true.png differ
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_dream3d_nx.png b/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_dream3d_nx.png
index b64434fd0..07af0ed16 100644
Binary files a/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_dream3d_nx.png and b/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_dream3d_nx.png differ
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_joulescope.jpg b/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_joulescope.jpg
new file mode 100644
index 000000000..94dec8d2c
Binary files /dev/null and b/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_joulescope.jpg differ
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_joulescope2.png b/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_joulescope2.png
new file mode 100644
index 000000000..b30492db6
Binary files /dev/null and b/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_joulescope2.png differ
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_pysoworks.png b/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_pysoworks.png
new file mode 100644
index 000000000..9e06aa77c
Binary files /dev/null and b/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_pysoworks.png differ
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_scrutiny-dark.png b/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_scrutiny-dark.png
new file mode 100644
index 000000000..250d658c4
Binary files /dev/null and b/scribus/third_party/Qt-Advanced-Docking-System/doc/showcase_scrutiny-dark.png differ
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/doc/user-guide.md b/scribus/third_party/Qt-Advanced-Docking-System/doc/user-guide.md
index e59bae6aa..ed9978e0a 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/doc/user-guide.md
+++ b/scribus/third_party/Qt-Advanced-Docking-System/doc/user-guide.md
@@ -29,8 +29,11 @@
- [`MiddleMouseButtonClosesTab`](#middlemousebuttonclosestab)
- [`DisableTabTextEliding`](#disabletabtexteliding)
- [`ShowTabTextOnlyForActiveTab`](#showtabtextonlyforactivetab)
-- [Auto-Hide Configuration Flags](#auto-hide-configuration-flags)
- - [Auto Hide Dock Widgets](#auto-hide-dock-widgets)
+ - [`DoubleClickUndocksWidget`](#doubleclickundockswidget)
+ - [`TabsAtBottom`](#tabsatbottom)
+ - [`UseNativeWindows`](#usenativewindows)
+ - [`DisableStyleheet`](#disablestyleheet)
+- [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)
@@ -39,6 +42,8 @@
- [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)
+ - [Preferred Aut Hide Sidebar Location](#preferred-aut-hide-sidebar-location)
+- [Auto-Hide Configuration Flags](#auto-hide-configuration-flags)
- [Setting Auto-Hide Flags](#setting-auto-hide-flags)
- [`AutoHideFeatureEnabled`](#autohidefeatureenabled)
- [`DockAreaHasAutoHideButton`](#dockareahasautohidebutton)
@@ -49,6 +54,8 @@
- [`AutoHideCloseButtonCollapsesDock`](#autohideclosebuttoncollapsesdock)
- [`AutoHideHasCloseButton`](#autohidehasclosebutton)
- [`AutoHideHasMinimizeButton`](#autohidehasminimizebutton)
+ - [`AutoHideOpenOnDragHover`](#autohideopenondraghover)
+ - [`AutoHideCloseOnOutsideMouseClick`](#autohidecloseonoutsidemouseclick)
- [DockWidget Feature Flags](#dockwidget-feature-flags)
- [`DockWidgetClosable`](#dockwidgetclosable)
- [`DockWidgetMovable`](#dockwidgetmovable)
@@ -62,8 +69,16 @@
- [Central Widget](#central-widget)
- [Empty Dock Area](#empty-dock-area)
- [Custom Close Handling](#custom-close-handling)
-- [Styling](#styling)
+- [Globally Lock Docking Features](#globally-lock-docking-features)
+- [Dock Widget Size / Minimum Size Handling](#dock-widget-size--minimum-size-handling)
+- [Styling / themes](#styling--themes)
+ - [Default Style Sheet](#default-style-sheet)
- [Disabling the Internal Style Sheet](#disabling-the-internal-style-sheet)
+- [Using ADS on Linux](#using-ads-on-linux)
+ - [Supported Distributions](#supported-distributions)
+ - [Requirements](#requirements)
+ - [Manjaro xfce 25.0.1 and Xubuntu 24.04.2 issues](#manjaro-xfce-2501-and-xubuntu-24042-issues)
+- [OpenGl + ADS](#opengl--ads)
## Configuration Flags
@@ -150,7 +165,7 @@ This ie enabled by default to minimize the size of the saved data.
### `TabCloseButtonIsToolButton`
-If enabled the tab close buttons will be `QToolButtons` instead of `QPushButtons` -
+If enabled the tab close buttons will be `QToolButtons` instead of `QPushButtons` -
disabled by default. Normally the default configuration should be ok but if your
application requires `QToolButtons` instead of `QPushButtons` for styling reasons
or for any other reasons, then you can enable this flag.
@@ -181,7 +196,7 @@ constant, that means, if enabled, the tabs need more space.
### `DragPreviewIsDynamic`
-If non-opaque undocking is enabled, this flag defines the behavior of the drag
+If non-opaque undocking is enabled, this flag defines the behavior of the drag
preview window. If this flag is enabled, then it will give the user the
impression, that the floating drag preview is dynamically adjusted to the drop
area. In order to give the perfect impression, you should disable the flags
@@ -197,7 +212,7 @@ CDockManager::setConfigFlag(CDockManager::DragPreviewHasWindowFrame, false);
### `DragPreviewShowsContentPixmap`
-If non-opaque undocking is enabled, the created drag preview window shows a
+If non-opaque undocking is enabled, the created drag preview window shows a
copy of the content of the dock widget / dock are that is dragged, if this
flag is enabled (default).
@@ -210,7 +225,7 @@ like window without any content.
### `DragPreviewHasWindowFrame`
-If non-opaque undocking is enabled, then this flag configures if the drag
+If non-opaque undocking is enabled, then this flag configures if the drag
preview is frameless (default) or looks like a real window. If it is enabled,
then the drag preview is a transparent window with a system window frame.
@@ -378,7 +393,7 @@ ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar
If you have a content widget that does not support focussing for some reason
(like `QVTKOpenGLStereoWidget` from the [VTK library](https://github.com/Kitware/VTK)),
-then you can manually switch the focus by reacting on mouse events. The
+then you can manually switch the focus by reacting on mouse events. The
following code shows, how to install en event filter on the `QVTKOpenGLStereoWidget`
to properly switch the focus on `QEvent::MouseButtonPress`:
@@ -422,7 +437,7 @@ 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
+inserted into an existing dock area. The flag is disabled by default. If 3
dock widgets are inserted with the following code
```c++
@@ -433,7 +448,7 @@ then this is the result, if the flag is disabled:

-If the flag is enabled, then the space is equally distributed to all widgets
+If the flag is enabled, then the space is equally distributed to all widgets
in a splitter:

@@ -495,13 +510,32 @@ for active tabs. Inactive tabs only show their icon:

-## Auto-Hide Configuration Flags
+### `DoubleClickUndocksWidget`
+
+If the flag is set (default), a double click on a tab undocks the dock widget.
+If you would like to disable undocking, just clear this flag.
+
+### `TabsAtBottom`
+
+If the flag is set, tabs will be shown at the bottom instead of in the title bar.
-### Auto Hide Dock Widgets
+
+
+### `UseNativeWindows`
+
+If the flag is set, windows for the dock and area widgets will be native on Windows OS.
+It is disabled by default.
+
+### `DisableStyleheet`
+
+If the flag is set, the dock manager will not apply the default stylesheet. You can
+enable this flag, if you want to use your own stylesheet.
+
+## Auto Hide Dock Widgets
The Advanced Docking System supports "Auto-Hide" functionality for **all**
dock containers. The "Auto Hide" feature allows to display more information
-using less screen space by hiding or showing windows pinned to one of the
+using less screen space by hiding or showing windows pinned to one of the
four dock container borders.
Enabling this feature adds a button with a pin icon to each dock area.
@@ -563,7 +597,7 @@ That means, you can drag them to a different border or sidebar:
### Auto-Hide Tab Sorting
-You can drag Auto-Hide tabs to a new position in the current sidebar
+You can drag Auto-Hide tabs to a new position in the current sidebar
to sort them:

@@ -596,8 +630,30 @@ CDockWidget* TableDockWidget = new CDockWidget("Table 1");
DockManager->addAutoHideDockWidget(SideBarLeft, TableDockWidget);
```
+### Preferred Aut Hide Sidebar Location
+
+By default, docking a widget to auto-hide determines the target sidebar based on the widget's current geometry. While this works well for most layouts, applications with fixed panel arrangements may prefer explicit control over the sidebar placement.
+
+Use `setPreferredAutoHideSideBarLocation()` to specify the preferred auto-hide sidebar for a dock widget:
+
+```c++
+dockWidget->setPreferredAutoHideSideBarLocation(SideBarLeft);
+```
+
+When a preferred location is set, the widget is always pinned to the specified sidebar instead of using geometry-based detection. The default value (`SideBarNone`) preserves the existing behavior.
+
+When restoring (unpinning) a widget, the docking system also attempts to merge it into an existing dock area containing widgets with the same preferred sidebar location, avoiding unnecessary split areas and keeping related widgets grouped as tabs.
+
+**API**
+
+```c++
+void setPreferredAutoHideSideBarLocation(SideBarLocation location); SideBarLocation preferredAutoHideSideBarLocation() const;
+```
+
See `autohide` example or the demo application to learn how it works.
+## Auto-Hide Configuration Flags
+
### Setting Auto-Hide Flags
The Advanced Docking System has a number of global configuration flags to
@@ -632,7 +688,7 @@ the other Auto-Hide flags will be evaluated.
### `DockAreaHasAutoHideButton`
-If this flag is set (default), then each dock area has a pin button in the title
+If this flag is set (default), then each dock area has a pin button in the title
bar to toggle Auto-Hide state.

@@ -676,7 +732,7 @@ works if this feature is enabled.
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).
+the auto hide dock (collapsing the dock).

@@ -704,6 +760,20 @@ If this flag is set (disabled by default), then each auto hide widget has a mini

+### `AutoHideOpenOnDragHover`
+
+If this flag is set (disabled by default), then holding a dragging cursor hover an auto-hide collapsed dock's tab will open said dock:
+
+
+
+Said dock must be set to accept drops to hide when cursor leaves its scope. See `AutoHideDragNDropExample` for more details.
+
+### `AutoHideCloseOnOutsideMouseClick`
+
+If this flag is set (default), the auto hide dock container will collapse if the
+user clicks outside of the container. If not set, the auto hide container can be
+closed only via click on auto hide sidebar tab.
+
## DockWidget Feature Flags
### `DockWidgetClosable`
@@ -825,20 +895,182 @@ Normally clicking the close button of a dock widget will just hide the widget an
When an entire area is closed, the default behavior is to hide the dock widgets it contains regardless of the `DockWidgetDeleteOnClose` flag except if there is only one dock widget. In this special case, the `DockWidgetDeleteOnClose` flag is followed. This behavior can be changed by setting the `DockWidgetForceCloseWithArea` flag to all the dock widgets that needs to be closed with their area.
-## Styling
+## Globally Lock Docking Features
+
+It is possible to globally lock features of all dock widgets to "freeze" the
+current workspace layout. That means, you can now lock your workspace
+to avoid accidentally dragging a docked view. When locking wasn't possible,
+users had to manually dock it back to the desired place after each accidental
+undock.
+
+You can use a combination of the following feature flags to define which features
+shall get locked:
+
+- `CDockWidget::DockWidgetClosable`
+- `CDockWidget::DockWidgetMovable`
+- `CDockWidget::DockWidgetFloatable`
+- `CDockWidget::DockWidgetPinable`
+
+To clear the locked features, you can use `CDockWidget::NoDockWidgetFeatures`
+The following code shows how to lock and unlock all dock widget features
+globally.
+
+```c++
+DockManager->lockDockWidgetFeaturesGlobally();
+DockManager->lockDockWidgetFeaturesGlobally(CDockWidget::NoDockWidgetFeatures);
+```
+
+## Dock Widget Size / Minimum Size Handling
+
+There are several `CDockWidget` mode enums to control how a `CDockWidget` is
+resized and how the docking system handles the minimum size of a dockwidget.
+
+The first one is the `eInsertMode` enum:
+
+```c++
+enum eInsertMode
+{
+ AutoScrollArea,
+ ForceScrollArea,
+ ForceNoScrollArea
+};
+```
+
+The InsertMode defines how the widget is inserted into the dock widget, when you
+call the `CDockWidget::setWidget` method:
+
+```c++
+DockWidget->setWidget(widget, CDockWidget::AutoScrollArea);
+```
+
+The content of a dock widget should be resizable do a very small size to
+prevent the dock widget from blocking the resizing. To ensure, that a
+dock widget can be resized very well, it is better to insert the content
+widget into a scroll area or to provide a widget that is already a scroll
+area or that contains a scroll area (such as an `QAbstractItemView`)
+If the InsertMode is `AutoScrollArea`, the DockWidget tries to automatically
+detect how to insert the given widget. If the widget is derived from
+`QScrollArea` (i.e. an `QAbstractItemView`), then the widget is inserted
+directly. If the given widget is not a scroll area, the widget will be
+inserted into a scroll area.
+
+To force insertion into a scroll area, you can also provide the InsertMode
+`ForceScrollArea`. In this case a scroll area will also be created for content
+widgets that are derived from `QScrollArea` To prevent insertion into a scroll
+area, you can provide the InsertMode `ForceNoScrollArea`. In this case, the
+content widget is always inserted directly.
+
+A second enum, the `eMinimumSizeHintMode` defines, which value will be returned
+from the `CDockWidget::minimumSizeHint()` function:
+
+```c++
+enum eMinimumSizeHintMode
+{
+ MinimumSizeHintFromDockWidget,
+ MinimumSizeHintFromContent,
+ MinimumSizeHintFromDockWidgetMinimumSize,
+ MinimumSizeHintFromContentMinimumSize,
+};
+```
+
+To ensure, that a dock widget does not block resizing, the dock widget
+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`. 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.
+
+## Styling / themes
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
icons are styleable this way.
+### Default Style Sheet
+
+The dock manager uses an internal stylesheet to style its components.
+The library ships with a set of default Qt stylesheets located in the `src/stylesheets` directory supporting both light and dark themes.
+
+
+
+By default, the dock manager automatically selects the appropriate stylesheet according to the application's current color palette. When the application switches between light and dark mode (for example due to an operating system theme change), the corresponding stylesheet and icon set are applied automatically.
+
+In addition, palette changes are propagated to all docking widgets, ensuring that palette-based colors are updated consistently.
+
+The stylesheet selection behavior can be configured through `CDockManager::setColorSchemeMode`. Three modes are available:
+
+| Mode | Description |
+| --------------------------- | ---------------------------------------------------------------------------------------------- |
+| **FollowPalette** (default) | Automatically selects the light or dark stylesheet based on the application's current palette. |
+| **Light** | Always uses the light stylesheet, regardless of the application palette. |
+| **Dark** | Always uses the dark stylesheet, regardless of the application palette.
+
+Simply set the mode after creating the dock manager instance:
+
+```c++
+DockManager->setColorSchemeMode(CDockManager::ColorSchemeMode::FollowPalette);
+```
+
### Disabling the Internal Style Sheet
-The dock manager uses an internal stylesheet to style its components. That
-means, the style that you see in the demo application comes from the
-internal stylesheets that you will find in `src/stylesheets` folder. If you want
-to disable this internal stylesheet because your application uses its own,
-just call the function for settings the stylesheet with an empty string.
+If you want to disable this internal stylesheet because your application uses its own, just call the function for settings the stylesheet with an empty string.
```c++
DockManager->setStyleSheet("");
```
+or you can use the configuration flag `DisableStylesheet` to disable the internal stylesheet completely. This is useful if you want to use your own stylesheet and don't want the internal stylesheet to be applied at all.
+
+```c++
+CDockManager::setConfigFlag(CDockManager::DisableStyleheet, true);
+```
+
+## Using ADS on Linux
+
+### Supported 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 it is possible for Windows. It is only possible to support and test a small subset of Linux distributions. The library can be compiled for and has been developed and tested with some Linux distributions. Depending on the used window manager or compositor, dock widgets
+with native title bars are supported or not. If native title bars are not supported,
+the library switches to `QWidget` based title bars.
+
+- **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
+
+### Requirements
+
+There are some requirements for the Linux distribution that have to be met:
+
+- an X server that supports ARGB visuals and a compositing window manager. This is required to display the translucent dock overlays ([https://doc.qt.io/qt-5/qwidget.html#creating-translucent-windows](https://doc.qt.io/qt-5/qwidget.html#creating-translucent-windows)). If your Linux distribution does not support this, or if you disable this feature, you will very likely see issue [#95](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/95).
+- With ADS version v5.0.0 Wayland is supported. If you have problems with Wayland, then you should set the session type to x11: `XDG_SESSION_TYPE=x11 ./AdvancedDockingSystemDemo`. You will find more details about this in issue [#288](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/288).
+
+Screenshot Kubuntu:
+
+
+Screenshot Ubuntu:
+
+
+### Manjaro xfce 25.0.1 and Xubuntu 24.04.2 issues
+
+There is a known focus stealing issue with the xfce4 compositor reported in issue [#734]. This issue
+can be solved by enabling the setting **Activate focus stealing prevention**. `Settings > Window Manager Tweaks` has a tab called `Focus`.
+
+Selecting `Activate focus stealing prevention` and `Do nothing` for `When a window raises itself`, seems to mitigate the issue. Deselecting `Enable display compositing` on the `Compositor` tab, also works.
+
+
+
+## OpenGl + ADS
+
+If you would like to use OpenGL widgets with ADS such as `GLWidget`, QML or `QWebEngineView`, then you need
+to set `QApplication::setAttribute(Qt::AA_ShareOpenGLContexts)` before creating your application and your
+widgets (see issue [#732])
+
+```c++
+int main(int argc, char *argv[])
+{
+ QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
+ QApplication application(argc, argv);
+ ...
+}
+```
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/doc/xfce4_focus_stealing_issue.png b/scribus/third_party/Qt-Advanced-Docking-System/doc/xfce4_focus_stealing_issue.png
new file mode 100644
index 000000000..09f04079f
Binary files /dev/null and b/scribus/third_party/Qt-Advanced-Docking-System/doc/xfce4_focus_stealing_issue.png differ
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/sip/DockAreaTitleBar.sip b/scribus/third_party/Qt-Advanced-Docking-System/sip/DockAreaTitleBar.sip
index 70e3d9039..06c7b1971 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/sip/DockAreaTitleBar.sip
+++ b/scribus/third_party/Qt-Advanced-Docking-System/sip/DockAreaTitleBar.sip
@@ -12,10 +12,14 @@ class CTitleBarButton : QToolButton
%End
public:
- CTitleBarButton(bool visible = true, QWidget* parent /TransferThis/ = Q_NULLPTR );
+ CTitleBarButton(bool ShowInTitleBar, bool HideWhenDisabled, TitleBarButton ButtonId,
+ QWidget* /TransferThis/ = Q_NULLPTR );
virtual void setVisible(bool);
void setShowInTitleBar(bool);
+ TitleBarButton buttonId() const;
+ ads::CDockAreaTitleBar* titleBar() const;
+ bool isInAutoHideArea() const;
protected:
bool event(QEvent *ev);
@@ -44,13 +48,15 @@ public:
ads::CDockAreaTabBar* tabBar() const;
ads::CTitleBarButton* button(ads::TitleBarButton which) const;
ads::CElidingLabel* autoHideTitleLabel() const;
+ ads::CDockAreaWidget* dockAreaWidget() 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();
-
+ void showAutoHideControls(bool Show);
+ bool isAutoHide() const;
signals:
void tabBarClicked(int index);
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/sip/DockAreaWidget.sip b/scribus/third_party/Qt-Advanced-Docking-System/sip/DockAreaWidget.sip
index 527482172..6e091f6ab 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/sip/DockAreaWidget.sip
+++ b/scribus/third_party/Qt-Advanced-Docking-System/sip/DockAreaWidget.sip
@@ -41,6 +41,7 @@ public:
ads::CDockManager* dockManager() const;
ads::CDockContainerWidget* dockContainer() const;
ads::CAutoHideDockContainer* autoHideDockContainer() const;
+ ads::CDockSplitter* parentSplitter() const;
bool isAutoHide() const;
void setAutoHideDockContainer(CAutoHideDockContainer*);
virtual QSize minimumSizeHint() const;
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/sip/DockContainerWidget.sip b/scribus/third_party/Qt-Advanced-Docking-System/sip/DockContainerWidget.sip
index 9159452d3..982dcf6c9 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/sip/DockContainerWidget.sip
+++ b/scribus/third_party/Qt-Advanced-Docking-System/sip/DockContainerWidget.sip
@@ -20,13 +20,14 @@ class CDockContainerWidget : QFrame
protected:
virtual bool event(QEvent *e);
- QSplitter* rootSplitter() const;
+ ads::CDockSplitter* 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, int TabIndex = -1);
void addDockArea(ads::CDockAreaWidget* DockAreaWidget /Transfer/, ads::DockWidgetArea area = ads::CenterDockWidgetArea);
void removeDockArea(ads::CDockAreaWidget* area /TransferBack/);
+ /*QList<QPointer<ads::CDockAreaWidget>> removeAllDockAreas();*/
void saveState(QXmlStreamWriter& Stream) const;
bool restoreState(CDockingStateReader& Stream, bool Testing);
ads::CDockAreaWidget* lastAddedDockAreaWidget(ads::DockWidgetArea area) const;
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/sip/DockManager.sip b/scribus/third_party/Qt-Advanced-Docking-System/sip/DockManager.sip
index b7faf9c34..8ece9c6db 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/sip/DockManager.sip
+++ b/scribus/third_party/Qt-Advanced-Docking-System/sip/DockManager.sip
@@ -172,6 +172,8 @@ public:
FloatingContainerForceNativeTitleBar,
FloatingContainerForceQWidgetTitleBar,
MiddleMouseButtonClosesTab,
+ DisableTabTextEliding,
+ ShowTabTextOnlyForActiveTab,
DefaultDockAreaButtons,
DefaultBaseConfig,
DefaultOpaqueConfig,
@@ -188,6 +190,8 @@ public:
AutoHideSideBarsIconOnly,
AutoHideShowOnMouseOver,
AutoHideCloseButtonCollapsesDock,
+ AutoHideHasCloseButton,
+ AutoHideHasMinimizeButton,
DefaultAutoHideConfig,
};
typedef QFlags<ads::CDockManager::eAutoHideFlag> AutoHideFlags;
@@ -245,6 +249,12 @@ public:
void setSplitterSizes(ads::CDockAreaWidget *ContainedArea, const QList<int>& sizes);
static void setFloatingContainersTitle(const QString& Title);
static QString floatingContainersTitle();
+ void setDockWidgetToolBarStyle(Qt::ToolButtonStyle Style, ads::CDockWidget::eState State);
+ Qt::ToolButtonStyle dockWidgetToolBarStyle(ads::CDockWidget::eState State) const;
+ void setDockWidgetToolBarIconSize(const QSize& IconSize, ads::CDockWidget::eState State);
+ QSize dockWidgetToolBarIconSize(ads::CDockWidget::eState State) const;
+ ads::CDockWidget::DockWidgetFeatures globallyLockedDockWidgetFeatures() const;
+ void lockDockWidgetFeaturesGlobally(ads::CDockWidget::DockWidgetFeatures Features = ads::CDockWidget::GloballyLockableFeatures);
public slots:
void endLeavingMinimizedState();
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/sip/DockWidget.sip b/scribus/third_party/Qt-Advanced-Docking-System/sip/DockWidget.sip
index 5fac34c4f..c19656114 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/sip/DockWidget.sip
+++ b/scribus/third_party/Qt-Advanced-Docking-System/sip/DockWidget.sip
@@ -39,6 +39,7 @@ public:
DefaultDockWidgetFeatures,
AllDockWidgetFeatures,
DockWidgetAlwaysCloseAndDelete,
+ GloballyLockableFeatures,
NoDockWidgetFeatures
};
typedef QFlags<ads::CDockWidget::DockWidgetFeature> DockWidgetFeatures;
@@ -49,6 +50,12 @@ public:
StateDocked,
StateFloating
};
+
+ enum eToolBarStyleSource
+ {
+ ToolBarStyleFromDockManager,
+ ToolBarStyleFromDockWidget
+ };
enum eInsertMode
{
@@ -72,7 +79,7 @@ public:
};
- CDockWidget(const QString &title, QWidget* parent /TransferThis/ = 0);
+ CDockWidget(const QString &title, QWidget* parent /TransferThis/ = Q_NULLPTR);
virtual ~CDockWidget();
virtual QSize minimumSizeHint() const;
void setWidget(QWidget* widget /Transfer/, ads::CDockWidget::eInsertMode InsertMode = AutoScrollArea);
@@ -82,6 +89,7 @@ public:
void setFeatures(ads::CDockWidget::DockWidgetFeatures features);
void setFeature(ads::CDockWidget::DockWidgetFeature flag, bool on);
ads::CDockWidget::DockWidgetFeatures features() const;
+ void notifyFeaturesChanged();
ads::CDockManager* dockManager() const;
ads::CDockContainerWidget* dockContainer() const;
ads::CFloatingDockContainer* floatingDockContainer() const;
@@ -95,6 +103,7 @@ public:
bool isInFloatingContainer() const;
bool isClosed() const;
QAction* toggleViewAction() const;
+ void setToggleViewAction(QAction* action);
void setToggleViewActionMode(ads::CDockWidget::eToggleViewActionMode Mode);
void setMinimumSizeHintMode(ads::CDockWidget::eMinimumSizeHintMode Mode);
ads::CDockWidget::eMinimumSizeHintMode minimumSizeHintMode() const;
@@ -104,6 +113,8 @@ public:
QToolBar* toolBar() const;
QToolBar* createDefaultToolBar();
void setToolBar(QToolBar* ToolBar /Transfer/ );
+ void setToolBarStyleSource(ads::CDockWidget::eToolBarStyleSource Source);
+ ads::CDockWidget::eToolBarStyleSource toolBarStyleSource() const;
void setToolBarStyle(Qt::ToolButtonStyle Style, ads::CDockWidget::eState State);
Qt::ToolButtonStyle toolBarStyle(ads::CDockWidget::eState State) const;
void setToolBarIconSize(const QSize& IconSize, ads::CDockWidget::eState State);
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/sip/ElidingLabel.sip b/scribus/third_party/Qt-Advanced-Docking-System/sip/ElidingLabel.sip
index 7cd47b189..57fef9c18 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/sip/ElidingLabel.sip
+++ b/scribus/third_party/Qt-Advanced-Docking-System/sip/ElidingLabel.sip
@@ -17,8 +17,8 @@ protected:
virtual void mouseDoubleClickEvent( QMouseEvent *ev );
public:
- CElidingLabel(QWidget* parent /TransferThis/ = 0, Qt::WindowFlags f = 0);
- CElidingLabel(const QString& text, QWidget* parent /TransferThis/ = 0, Qt::WindowFlags f = 0);
+ CElidingLabel(QWidget* parent /TransferThis/ = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags ());
+ CElidingLabel(const QString& text, QWidget* parent /TransferThis/ = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags ());
virtual ~CElidingLabel();
Qt::TextElideMode elideMode() const;
void setElideMode(Qt::TextElideMode mode);
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/sip/FloatingDockContainer.sip b/scribus/third_party/Qt-Advanced-Docking-System/sip/FloatingDockContainer.sip
index b36f4ce13..79ed06e38 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/sip/FloatingDockContainer.sip
+++ b/scribus/third_party/Qt-Advanced-Docking-System/sip/FloatingDockContainer.sip
@@ -44,6 +44,7 @@ protected:
void startDragging(const QPoint& DragStartMousePos, const QSize& Size,
QWidget* MouseEventHandler);
virtual void finishDragging();
+ void deleteContent();
void initFloatingGeometry(const QPoint& DragStartMousePos, const QSize& Size);
void moveFloating();
bool restoreState(ads::CDockingStateReader& Stream, bool Testing);
@@ -82,6 +83,7 @@ public:
bool hasTopLevelDockWidget() const;
ads::CDockWidget* topLevelDockWidget() const;
QList<ads::CDockWidget*> dockWidgets() const;
+ void finishDropOperation();
%If (WS_X11)
void onMaximizeRequest();
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/sip/ads_globals.sip b/scribus/third_party/Qt-Advanced-Docking-System/sip/ads_globals.sip
index bbe649122..719b9306e 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/sip/ads_globals.sip
+++ b/scribus/third_party/Qt-Advanced-Docking-System/sip/ads_globals.sip
@@ -73,7 +73,8 @@ namespace ads
TitleBarButtonTabsMenu,
TitleBarButtonUndock,
TitleBarButtonClose,
- TitleBarButtonAutoHide
+ TitleBarButtonAutoHide,
+ TitleBarButtonMinimize
};
enum eDragState
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideDockContainer.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideDockContainer.cpp
index 44af9e23a..1909ad590 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideDockContainer.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideDockContainer.cpp
@@ -124,6 +124,21 @@ struct AutoHideDockContainerPrivate
*/
AutoHideDockContainerPrivate(CAutoHideDockContainer *_public);
+ /**
+ * Convenience function to ease access to dock manager components factory
+ */
+ QSharedPointer<ads::CDockComponentsFactory> componentsFactory() const
+ {
+ if (!DockWidget || !DockWidget->dockManager())
+ {
+ return CDockComponentsFactory::factory();
+ }
+ else
+ {
+ return DockWidget->dockManager()->componentsFactory();
+ }
+ }
+
/**
* Convenience function to get a dock widget area
*/
@@ -199,7 +214,7 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarL
{
hide(); // auto hide dock container is initially always hidden
d->SideTabBarArea = area;
- d->SideTab = componentsFactory()->createDockWidgetSideTab(nullptr);
+ d->SideTab = d->componentsFactory()->createDockWidgetSideTab(nullptr);
connect(d->SideTab, &CAutoHideTab::pressed, this, &CAutoHideDockContainer::toggleCollapseState);
d->DockArea = new CDockAreaWidget(DockWidget->dockManager(), parent);
d->DockArea->setObjectName("autoHideDockArea");
@@ -400,7 +415,31 @@ void CAutoHideDockContainer::moveContentsToParent()
// to the user and he does not have to search where the widget was inserted.
d->DockWidget->setDockArea(nullptr);
auto DockContainer = dockContainer();
- DockContainer->addDockWidget(d->getDockWidgetArea(d->SideTabBarArea), d->DockWidget);
+ auto targetArea = d->getDockWidgetArea(d->SideTabBarArea);
+
+ // If the widget has a preferred auto-hide location, try to find an existing
+ // opened dock area that contains a widget with the same preferred location
+ // and merge as a tab instead of creating a new split.
+ auto preferred = d->DockWidget->preferredAutoHideSideBarLocation();
+ if (preferred != SideBarNone)
+ {
+ for (auto area : DockContainer->openedDockAreas())
+ {
+ if (!area || area->isAutoHide()) continue;
+ // Check if any widget in this area has the same preferred location
+ for (auto dw : area->dockWidgets())
+ {
+ if (dw && dw->preferredAutoHideSideBarLocation() == preferred)
+ {
+ DockContainer->addDockWidget(CenterDockWidgetArea,
+ d->DockWidget, area);
+ return;
+ }
+ }
+ }
+ }
+
+ DockContainer->addDockWidget(targetArea, d->DockWidget);
}
@@ -410,8 +449,8 @@ void CAutoHideDockContainer::cleanupAndDelete()
const auto dockWidget = d->DockWidget;
if (dockWidget)
{
-
auto SideTab = d->SideTab;
+ dockWidget->setSideTabWidget(nullptr);
SideTab->removeFromSideBar();
SideTab->setParent(nullptr);
SideTab->hide();
@@ -467,6 +506,17 @@ void CAutoHideDockContainer::collapseView(bool Enable)
{
updateSize();
d->updateResizeHandleSizeLimitMax();
+ // If the parent dock container has native child windows (e.g. because
+ // an OpenGL or VTK content widget called winId()), this panel is an
+ // alien (non-native) widget and will always be obscured by those native
+ // sibling windows regardless of Qt's paint order. Native OS windows are
+ // rendered above the parent's painted (alien) content by the windowing
+ // system. To allow raise() to use OS-level Z-order and appear on top,
+ // this panel must first be promoted to a native window itself.
+ if (parentWidget() && parentWidget()->internalWinId() && !internalWinId())
+ {
+ winId();
+ }
raise();
show();
d->DockWidget->dockManager()->setDockWidgetFocused(d->DockWidget);
@@ -587,8 +637,12 @@ bool CAutoHideDockContainer::eventFilter(QObject* watched, QEvent* event)
return Super::eventFilter(watched, event);
}
- // user clicked into container - collapse the auto hide widget
- collapseView(true);
+ // user clicked outside of autohide container - collapse the auto hide widget
+ if (CDockManager::testAutoHideConfigFlag(
+ CDockManager::AutoHideCloseOnOutsideMouseClick))
+ {
+ collapseView(true);
+ }
}
else if (event->type() == internal::FloatingWidgetDragStartEvent)
{
@@ -657,6 +711,14 @@ bool CAutoHideDockContainer::event(QEvent* event)
return Super::event(event);
}
+//============================================================================
+void CAutoHideDockContainer::dragLeaveEvent(QDragLeaveEvent*)
+{
+ if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover))
+ {
+ collapseView(true);
+ }
+}
//============================================================================
Qt::Orientation CAutoHideDockContainer::orientation() const
@@ -709,4 +771,3 @@ int CAutoHideDockContainer::tabIndex() const
}
}
-
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideDockContainer.h b/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideDockContainer.h
index 2fdce37a2..e12dbbaca 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideDockContainer.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideDockContainer.h
@@ -65,6 +65,7 @@ protected:
virtual void resizeEvent(QResizeEvent* event) override;
virtual void leaveEvent(QEvent *event) override;
virtual bool event(QEvent* event) override;
+ virtual void dragLeaveEvent(QDragLeaveEvent* ev) override;
/**
* Updates the size considering the size limits and the resize margins
@@ -139,7 +140,7 @@ public:
/**
* Moves the contents to the parent container widget
- * Used before removing this Auto Hide dock container
+ * Used before removing this Auto Hide dock container
*/
void moveContentsToParent();
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideSideBar.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideSideBar.cpp
index f08172ec6..7dea2fe3e 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideSideBar.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideSideBar.cpp
@@ -414,7 +414,14 @@ void CAutoHideSideBar::saveState(QXmlStreamWriter& s) const
QSize CAutoHideSideBar::minimumSizeHint() const
{
QSize Size = sizeHint();
- Size.setWidth(10);
+ if (d->isHorizontal())
+ {
+ Size.setWidth(0);
+ }
+ else
+ {
+ Size.setHeight(0);
+ }
return Size;
}
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideTab.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideTab.cpp
index e2d6265c4..f6f3ad93c 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideTab.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideTab.cpp
@@ -33,6 +33,8 @@
#include <QApplication>
#include <QElapsedTimer>
#include <QMenu>
+#include <QEvent>
+#include <QTimer>
#include "AutoHideDockContainer.h"
#include "AutoHideSideBar.h"
@@ -41,6 +43,7 @@
#include "DockWidget.h"
#include "FloatingDragPreview.h"
#include "DockOverlay.h"
+#include "ads_globals.h"
namespace ads
{
@@ -55,6 +58,7 @@ struct AutoHideTabPrivate
CAutoHideSideBar* SideBar = nullptr;
Qt::Orientation Orientation{Qt::Vertical};
QElapsedTimer TimeSinceHoverMousePress;
+ QTimer DragOverTimer;
bool MousePressed = false;
eDragState DragState = DraggingInactive;
QPoint GlobalDragStartMousePosition;
@@ -135,7 +139,7 @@ struct AutoHideTabPrivate
IFloatingWidget* createFloatingWidget(T* Widget)
{
auto w = new CFloatingDragPreview(Widget);
- _this->connect(w, &CFloatingDragPreview::draggingCanceled, [=]()
+ _this->connect(w, &CFloatingDragPreview::draggingCanceled, [this]()
{
DragState = DraggingInactive;
});
@@ -252,6 +256,14 @@ CAutoHideTab::CAutoHideTab(QWidget* parent) :
{
setAttribute(Qt::WA_NoMousePropagation);
setFocusPolicy(Qt::NoFocus);
+ if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover)) {
+ setAcceptDrops(true);
+ }
+
+ d->DragOverTimer.setInterval(CDockManager::configParam(
+ CDockManager::AutoHideOpenOnDragHoverDelay_ms, 500).toInt());
+ d->DragOverTimer.setSingleShot(true);
+ connect(&d->DragOverTimer, &QTimer::timeout, this, &CAutoHideTab::onDragHoverDelayExpired);
}
@@ -355,7 +367,6 @@ bool CAutoHideTab::event(QEvent* event)
case QEvent::Leave:
d->forwardEventToDockContainer(event);
break;
-
default:
break;
}
@@ -493,48 +504,74 @@ void CAutoHideTab::mouseReleaseEvent(QMouseEvent* ev)
//============================================================================
-void CAutoHideTab::mouseMoveEvent(QMouseEvent* ev)
+void CAutoHideTab::mouseMoveEvent(QMouseEvent *ev)
{
- if (!(ev->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive))
- {
- d->DragState = DraggingInactive;
- Super::mouseMoveEvent(ev);
- return;
- }
+ 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 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);
- }
+ // 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)
+ 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
+ // 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;
+ if (Features.testFlag(CDockWidget::DockWidgetFloatable)
+ || (Features.testFlag(CDockWidget::DockWidgetMovable)))
+ {
+ d->startFloating();
+ }
+ return;
}
- Super::mouseMoveEvent(ev);
+ Super::mouseMoveEvent(ev);
+}
+
+//============================================================================
+void CAutoHideTab::dragEnterEvent(QDragEnterEvent *ev)
+{
+ Q_UNUSED(ev);
+ if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover))
+ {
+ d->DragOverTimer.start();
+ ev->accept();
+ }
+}
+
+//============================================================================
+void CAutoHideTab::dragLeaveEvent(QDragLeaveEvent *ev)
+{
+ Q_UNUSED(ev);
+ if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover))
+ {
+ d->DragOverTimer.stop();
+ }
}
@@ -544,7 +581,6 @@ void CAutoHideTab::requestCloseDockWidget()
d->DockWidget->requestCloseDockWidget();
}
-
//============================================================================
int CAutoHideTab::tabIndex() const
{
@@ -557,4 +593,28 @@ int CAutoHideTab::tabIndex() const
}
+//============================================================================
+void CAutoHideTab::onDragHoverDelayExpired()
+{
+ static const char* const PropertyId = "ActiveDragOverAutoHideContainer";
+
+ // First we check if there is an active auto hide container that is visible
+ // In this case, we collapse it before we open the new one
+ auto v = d->DockWidget->dockManager()->property(PropertyId);
+ if (v.isValid())
+ {
+ auto ActiveAutoHideContainer = v.value<QPointer<CAutoHideDockContainer>>();
+ if (ActiveAutoHideContainer)
+ {
+ ActiveAutoHideContainer->collapseView(true);
+ }
+ }
+
+ auto AutoHideContainer = d->DockWidget->autoHideDockContainer();
+ AutoHideContainer->collapseView(false);
+ d->DockWidget->dockManager()->setProperty(PropertyId,
+ QVariant::fromValue(QPointer<CAutoHideDockContainer>(AutoHideContainer)));
+}
+
+
}
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideTab.h b/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideTab.h
index 3a42df852..f3b528518 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideTab.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/AutoHideTab.h
@@ -55,7 +55,7 @@ class ADS_EXPORT CAutoHideTab : public CPushButton
Q_PROPERTY(bool activeTab READ isActiveTab)
Q_PROPERTY(bool iconOnly READ iconOnly)
-private:
+private:
AutoHideTabPrivate* d; ///< private data (pimpl)
friend struct AutoHideTabPrivate;
friend class CDockWidget;
@@ -67,6 +67,7 @@ private:
private Q_SLOTS:
void onAutoHideToActionClicked();
+ void onDragHoverDelayExpired();
protected:
void setSideBar(CAutoHideSideBar *SideTabBar);
@@ -76,6 +77,8 @@ protected:
virtual void mousePressEvent(QMouseEvent* ev) override;
virtual void mouseReleaseEvent(QMouseEvent* ev) override;
virtual void mouseMoveEvent(QMouseEvent* ev) override;
+ virtual void dragEnterEvent(QDragEnterEvent* ev) override;
+ virtual void dragLeaveEvent(QDragLeaveEvent* ev) override;
public:
using Super = CPushButton;
@@ -90,7 +93,7 @@ public:
/**
* Virtual Destructor
*/
- virtual ~CAutoHideTab();
+ ~CAutoHideTab() override;
/**
* Update stylesheet style if a property changes
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/CMakeLists.txt b/scribus/third_party/Qt-Advanced-Docking-System/src/CMakeLists.txt
index 8626d25c5..aa30db5bd 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/CMakeLists.txt
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/CMakeLists.txt
@@ -1,19 +1,23 @@
cmake_minimum_required(VERSION 3.16)
project(QtAdvancedDockingSystem LANGUAGES CXX VERSION ${VERSION_SHORT})
+include(GNUInstallDirs)
+include(Versioning)
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)
- if(DEFINED Qt6Gui_VERSION AND (Qt6Gui_VERSION VERSION_GREATER_EQUAL 6.10))
- find_package(Qt6 COMPONENTS GuiPrivate REQUIRED)
- endif()
- include_directories(${Qt${QT_VERSION_MAJOR}Gui_PRIVATE_INCLUDE_DIRS})
+set(ads_DEP_LIBS Core Gui Widgets)
+if (UNIX AND NOT APPLE AND QT_VERSION_MAJOR STREQUAL "6" AND QT_VERSION_MINOR GREATER 8)
+ set(ads_DEP_LIBS Core Gui GuiPrivate Widgets)
+endif()
+find_package(Qt${QT_VERSION_MAJOR} COMPONENTS ${ads_DEP_LIBS} REQUIRED)
+if (UNIX AND NOT APPLE AND ((QT_VERSION_MAJOR STREQUAL "6" AND QT_VERSION_MINOR GREATER 8) OR QT_VERSION_MAJOR STREQUAL "5"))
+ include_directories(${Qt${QT_VERSION_MAJOR}Gui_PRIVATE_INCLUDE_DIRS})
endif()
+
set(CMAKE_INCLUDE_CURRENT_DIR ON)
if(BUILD_STATIC)
set(CMAKE_STATIC_LIBRARY_SUFFIX "_static${CMAKE_STATIC_LIBRARY_SUFFIX}")
@@ -74,12 +78,15 @@ if (UNIX AND NOT APPLE)
set(ads_HEADERS linux/FloatingWidgetTitleBar.h ${ads_HEADERS})
endif()
-set(library_name "qt${QT_VERSION_MAJOR}advanceddocking")
+set(library_name "qtadvanceddocking-qt${QT_VERSION_MAJOR}")
if(BUILD_STATIC)
add_library(${library_name} STATIC ${ads_SRCS} ${ads_HEADERS})
target_compile_definitions( ${library_name} PUBLIC ADS_STATIC)
else()
add_library( ${library_name} SHARED ${ads_SRCS} ${ads_HEADERS})
+ if(WIN32)
+ add_windows_version_resources(${library_name})
+ endif()
target_compile_definitions( ${library_name} PRIVATE ADS_SHARED_EXPORT)
endif()
@@ -88,11 +95,12 @@ add_library(ads::${library_name} ALIAS ${library_name})
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)
- if(Qt6GuiPrivate_FOUND)
- target_link_libraries(${library_name} PUBLIC Qt6::GuiPrivate)
- endif()
+if(UNIX AND NOT APPLE AND QT_VERSION_MAJOR STREQUAL "6")
+ target_link_libraries(${library_name} PRIVATE Qt6::GuiPrivate) #needed for <qpa/qplatformnativeinterface.h>
+endif()
+
+if (UNIX AND NOT APPLE)
if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
find_package(X11 REQUIRED)
target_link_libraries(${library_name} PUBLIC X11::xcb)
@@ -105,6 +113,7 @@ set_target_properties(${library_name} PROPERTIES
AUTORCC ON
CXX_EXTENSIONS OFF
VERSION ${VERSION_SHORT}
+ SOVERSION ${VERSION_SONAME}
EXPORT_NAME ${library_name}
DEBUG_POSTFIX "d"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
@@ -134,7 +143,7 @@ install(FILES ${ads_HEADERS}
install(FILES
"${CMAKE_CURRENT_SOURCE_DIR}/../LICENSE"
"${CMAKE_CURRENT_SOURCE_DIR}/../gnu-lgpl-v2.1.md"
- DESTINATION license/ads
+ DESTINATION share/ads/license
COMPONENT license
)
install(TARGETS ${library_name}
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTabBar.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTabBar.cpp
index 437fe6d1e..8de254c40 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTabBar.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTabBar.cpp
@@ -111,7 +111,7 @@ void DockAreaTabBarPrivate::updateTabs()
// 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, [&, TabWidget]
+ QTimer::singleShot(0, _this, [&, TabWidget]
{
_this->ensureWidgetVisible(TabWidget);
});
@@ -160,19 +160,9 @@ CDockAreaTabBar::~CDockAreaTabBar()
//============================================================================
void CDockAreaTabBar::wheelEvent(QWheelEvent* Event)
{
- Event->accept();
- const int direction = Event->angleDelta().y();
- if (direction < 0)
- {
- horizontalScrollBar()->setValue(horizontalScrollBar()->value() + 20);
- }
- else
- {
- horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20);
- }
+ QCoreApplication::sendEvent(horizontalScrollBar(), Event);
}
-
//============================================================================
void CDockAreaTabBar::setCurrentIndex(int index)
{
@@ -344,27 +334,13 @@ void CDockAreaTabBar::onTabCloseRequested()
void CDockAreaTabBar::onCloseOtherTabsRequested()
{
auto Sender = qobject_cast<CDockWidgetTab*>(sender());
- for (int i = 0; i < count(); ++i)
- {
- auto Tab = tab(i);
- if (Tab->isClosable() && !Tab->isHidden() && Tab != Sender)
- {
- // If the dock widget is deleted with the closeTab() call, its tab
- // it will no longer be in the layout, and thus the index needs to
- // be updated to not skip any tabs
- int Offset = Tab->dockWidget()->features().testFlag(
- CDockWidget::DockWidgetDeleteOnClose) ? 1 : 0;
- closeTab(i);
-
- // If the the dock widget blocks closing, i.e. if the flag
- // CustomCloseHandling is set, and the dock widget is still open,
- // then we do not need to correct the index
- if (Tab->dockWidget()->isClosed())
- {
- i -= Offset;
- }
- }
- }
+
+ for (int i = count() - 1; i >= 0; --i) {
+ auto Tab = tab(i);
+ if (Tab->isClosable() && !Tab->isHidden() && Tab != Sender) {
+ closeTab(i);
+ }
+ }
}
@@ -390,15 +366,18 @@ void CDockAreaTabBar::onTabWidgetMoved(const QPoint& GlobalPos)
int fromIndex = d->TabsLayout->indexOf(MovingTab);
auto MousePos = mapFromGlobal(GlobalPos);
- MousePos.rx() = qMax(d->firstTab()->geometry().left(), MousePos.x());
- MousePos.rx() = qMin(d->lastTab()->geometry().right(), MousePos.x());
+ MousePos.rx() = qMax(0, MousePos.x());
+ MousePos.rx() = qMin(width(), MousePos.x());
int toIndex = -1;
// Find tab under mouse
for (int i = 0; i < count(); ++i)
{
CDockWidgetTab* DropTab = tab(i);
+ auto TabGeometry = DropTab->geometry();
+ TabGeometry.setTopLeft(d->TabsContainerWidget->mapToParent(TabGeometry.topLeft()));
+ TabGeometry.setBottomRight(d->TabsContainerWidget->mapToParent(TabGeometry.bottomRight()));
if (DropTab == MovingTab || !DropTab->isVisibleTo(this)
- || !DropTab->geometry().contains(MousePos))
+ || !TabGeometry.contains(MousePos))
{
continue;
}
@@ -470,6 +449,15 @@ bool CDockAreaTabBar::eventFilter(QObject *watched, QEvent *event)
updateGeometry();
break;
+ // Manage wheel event
+ case QEvent::Wheel:
+ // Ignore wheel events if tab is currently dragged
+ if (Tab->dragState() == DraggingInactive)
+ {
+ wheelEvent((QWheelEvent* )event);
+ }
+ break;
+
default:
break;
}
@@ -545,6 +533,13 @@ int CDockAreaTabBar::tabInsertIndexAt(const QPoint& Pos) const
}
}
+
+//===========================================================================
+bool CDockAreaTabBar::areTabsOverflowing() const
+{
+ return d->TabsContainerWidget->width() > width();
+}
+
} // namespace ads
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTabBar.h b/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTabBar.h
index 1eec3124e..60557fe61 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTabBar.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTabBar.h
@@ -65,8 +65,7 @@ private Q_SLOTS:
void onTabWidgetMoved(const QPoint& GlobalPos);
protected:
- virtual void wheelEvent(QWheelEvent* Event) override;
-
+ virtual void wheelEvent(QWheelEvent* Event) override;
public:
using Super = QScrollArea;
@@ -153,6 +152,12 @@ public:
*/
virtual QSize sizeHint() const override;
+ /**
+ * This function returns true, if the tabs need more space than the size
+ * of the tab bar.
+ */
+ bool areTabsOverflowing() const;
+
public Q_SLOTS:
/**
* This property sets the index of the tab bar's visible tab
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTitleBar.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTitleBar.cpp
index b3f42f96d..0caa030be 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTitleBar.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTitleBar.cpp
@@ -114,6 +114,14 @@ struct DockAreaTitleBarPrivate
return DockArea->dockManager();
}
+ /**
+ * Convenience function for access to dock manager components factory
+ */
+ QSharedPointer<ads::CDockComponentsFactory> componentsFactory() const
+ {
+ return dockManager()->componentsFactory();
+ }
+
/**
* Returns true if the given config flag is set
* Convenience function to ease config flag testing
@@ -150,6 +158,14 @@ struct DockAreaTitleBarPrivate
*/
IFloatingWidget* makeAreaFloating(const QPoint& Offset, eDragState DragState);
+ /**
+ * Wayland hybrid drag: drive the in-window drag preview from reliable event
+ * coordinates and, when the cursor leaves the source top-level window,
+ * convert the in-window drag into a native compositor platform drag
+ * (mirrors CDockWidgetTab).
+ */
+ void waylandPreviewMove(QMouseEvent* ev);
+
/**
* Helper function to create and initialize the menu entries for
* the "Auto Hide Group To..." menu
@@ -252,10 +268,10 @@ void DockAreaTitleBarPrivate::createAutoHideTitleLabel()
{
AutoHideTitleLabel = new CElidingLabel("");
AutoHideTitleLabel->setObjectName("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));
+ // When the tabs are at the top, they will be at position 0, insert the label behind them, and hide it.
+ Layout->addWidget(AutoHideTitleLabel);
+ AutoHideTitleLabel->setVisible(CDockManager::testConfigFlag(CDockManager::TabsAtBottom));
+ Layout->addWidget(new CSpacerWidget(_this));
}
@@ -264,7 +280,9 @@ void DockAreaTitleBarPrivate::createTabBar()
{
TabBar = componentsFactory()->createDockAreaTabBar(DockArea);
TabBar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
- Layout->addWidget(TabBar);
+ if (!CDockManager::testConfigFlag(CDockManager::TabsAtBottom))
+ Layout->addWidget(TabBar);
+
_this->connect(TabBar, SIGNAL(tabClosed(int)), SLOT(markTabsMenuOutdated()));
_this->connect(TabBar, SIGNAL(tabOpened(int)), SLOT(markTabsMenuOutdated()));
_this->connect(TabBar, SIGNAL(tabInserted(int)), SLOT(markTabsMenuOutdated()));
@@ -281,6 +299,10 @@ IFloatingWidget* DockAreaTitleBarPrivate::makeAreaFloating(const QPoint& Offset,
{
QSize Size = DockArea->size();
this->DragState = DragState;
+ // Wayland hybrid drag: start an in-window drag preview (driven by event
+ // coordinates, confined to the source container) rather than an immediate
+ // platform drag. The drag converts to a native compositor platform drag
+ // only when the cursor leaves the source window (see waylandPreviewMove()).
bool CreateFloatingDockContainer = (DraggingFloatingWidget != DragState);
CFloatingDockContainer* FloatingDockContainer = nullptr;
IFloatingWidget* FloatingWidget;
@@ -295,14 +317,21 @@ IFloatingWidget* DockAreaTitleBarPrivate::makeAreaFloating(const QPoint& Offset,
else
{
auto w = new CFloatingDragPreview(DockArea);
- QObject::connect(w, &CFloatingDragPreview::draggingCanceled, [=]()
+ QObject::connect(w, &CFloatingDragPreview::draggingCanceled, [this]()
{
this->DragState = DraggingInactive;
});
+ if (internal::isWayland())
+ {
+ // Confine the in-window preview to the source container; its
+ // position and the drop overlays are driven by event coordinates
+ // delivered to the title bar (see waylandPreviewMove()).
+ w->setSourceContainer(DockArea->dockContainer());
+ }
FloatingWidget = w;
}
- FloatingWidget->startFloating(Offset, Size, DragState, nullptr);
+ FloatingWidget->startFloating(Offset, Size, DragState, nullptr);
if (FloatingDockContainer)
{
auto TopLevelDockWidget = FloatingDockContainer->topLevelDockWidget();
@@ -324,10 +353,49 @@ void DockAreaTitleBarPrivate::startFloating(const QPoint& Offset)
DockArea->autoHideDockContainer()->hide();
}
FloatingWidget = makeAreaFloating(Offset, DraggingFloatingWidget);
+ // On Wayland the hybrid drag now starts an in-window preview (it no longer
+ // blocks on a platform drag here), so the drag-start event is reported like
+ // on every other platform.
qApp->postEvent(DockArea, new QEvent((QEvent::Type)internal::DockedWidgetDragStartEvent));
}
+//============================================================================
+void DockAreaTitleBarPrivate::waylandPreviewMove(QMouseEvent* ev)
+{
+ const QPoint GlobalPos = internal::globalPositionOf(ev);
+
+ // FloatingWidget is a CFloatingDragPreview during the in-window phase
+ // (DraggingFloatingWidget state on Wayland; see makeAreaFloating()). While
+ // the cursor stays inside the source window the preview just follows it.
+ auto Preview = static_cast<CFloatingDragPreview*>(FloatingWidget);
+ if (CFloatingDockContainer::waylandMoveOrLeaveInWindowPreview(
+ Preview, _this->window(), GlobalPos))
+ {
+ return;
+ }
+
+ // Boundary cross: the preview was torn down, convert the gesture into a
+ // native compositor platform drag of a freshly created floating widget.
+ FloatingWidget = nullptr;
+ DragState = DraggingInactive;
+
+ if (DockArea->autoHideDockContainer())
+ {
+ DockArea->autoHideDockContainer()->cleanupAndDelete();
+ }
+ auto FloatingDockContainer = new CFloatingDockContainer(DockArea);
+ auto TopLevelDockWidget = FloatingDockContainer->topLevelDockWidget();
+ if (TopLevelDockWidget)
+ {
+ TopLevelDockWidget->emitTopLevelChanged(true);
+ }
+ CFloatingDockContainer::startPlatformDragForFloatingWidget(
+ FloatingDockContainer, DragStartMousePos, DockArea->size(),
+ _this->mapToGlobal(DragStartMousePos), _this);
+}
+
+
//============================================================================
CDockAreaTitleBar::CDockAreaTitleBar(CDockAreaWidget* parent) :
QFrame(parent),
@@ -343,8 +411,8 @@ CDockAreaTitleBar::CDockAreaTitleBar(CDockAreaWidget* parent) :
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
d->createTabBar();
- d->createButtons();
d->createAutoHideTitleLabel();
+ d->createButtons();
setFocusPolicy(Qt::NoFocus);
}
@@ -377,27 +445,51 @@ CDockAreaTabBar* CDockAreaTitleBar::tabBar() const
return d->TabBar;
}
+
+//============================================================================
+void CDockAreaTitleBar::resizeEvent(QResizeEvent *event)
+{
+ Super::resizeEvent(event);
+ if (CDockManager::testConfigFlag(CDockManager::DockAreaDynamicTabsMenuButtonVisibility)
+ && CDockManager::testConfigFlag(CDockManager::DisableTabTextEliding))
+ {
+ // Use queued connection to ensure that the resizing and relayouting has
+ // finished to ensure that the d->TabBar->areTabsOverflowing() function
+ // returns the correct value
+ QMetaObject::invokeMethod(this, "markTabsMenuOutdated", Qt::QueuedConnection);
+ }
+}
+
+
//============================================================================
void CDockAreaTitleBar::markTabsMenuOutdated()
{
- if(DockAreaTitleBarPrivate::testConfigFlag(CDockManager::DockAreaDynamicTabsMenuButtonVisibility))
+ if (CDockManager::testConfigFlag(CDockManager::DockAreaDynamicTabsMenuButtonVisibility))
{
- bool hasElidedTabTitle = false;
- for (int i = 0; i < d->TabBar->count(); ++i)
+ bool TabsMenuButtonVisible = false;
+ if (CDockManager::testConfigFlag(CDockManager::DisableTabTextEliding))
{
- if (!d->TabBar->isTabOpen(i))
- {
- continue;
- }
- CDockWidgetTab* Tab = d->TabBar->tab(i);
- if(Tab->isTitleElided())
+ TabsMenuButtonVisible = d->TabBar->areTabsOverflowing();
+ }
+ else
+ {
+ bool hasElidedTabTitle = false;
+ for (int i = 0; i < d->TabBar->count(); ++i)
{
- hasElidedTabTitle = true;
- break;
+ if (!d->TabBar->isTabOpen(i))
+ {
+ continue;
+ }
+ CDockWidgetTab* Tab = d->TabBar->tab(i);
+ if(Tab->isTitleElided())
+ {
+ hasElidedTabTitle = true;
+ break;
+ }
}
+ TabsMenuButtonVisible = (hasElidedTabTitle && (d->TabBar->count() > 1));
}
- bool visible = (hasElidedTabTitle && (d->TabBar->count() > 1));
- QMetaObject::invokeMethod(d->TabsMenuButton, "setVisible", Qt::QueuedConnection, Q_ARG(bool, visible));
+ QMetaObject::invokeMethod(d->TabsMenuButton, "setVisible", Qt::QueuedConnection, Q_ARG(bool, TabsMenuButtonVisible));
}
d->MenuOutdated = true;
}
@@ -657,7 +749,16 @@ void CDockAreaTitleBar::mouseMoveEvent(QMouseEvent* ev)
// move floating window
if (d->isDraggingState(DraggingFloatingWidget))
{
- d->FloatingWidget->moveFloating();
+ if (internal::isWayland())
+ {
+ // Wayland hybrid drag: in-window preview until the cursor leaves
+ // the source window, then convert to a native platform drag.
+ d->waylandPreviewMove(ev);
+ }
+ else
+ {
+ d->FloatingWidget->moveFloating();
+ }
return;
}
@@ -665,9 +766,24 @@ void CDockAreaTitleBar::mouseMoveEvent(QMouseEvent* ev)
// sense to move it to a new floating widget and leave this one
// empty
if (d->DockArea->dockContainer()->isFloating()
- && d->DockArea->dockContainer()->visibleDockAreaCount() == 1
+ && d->DockArea->dockContainer()->visibleDockAreaCount() == 1
&& !d->DockArea->isAutoHide())
{
+ // On Wayland, dragging the title bar of the last dock area of a
+ // floating widget drags the existing floating widget, so the user
+ // can dock it into another container
+ int DragDistanceWayland = (d->DragStartMousePos - ev->pos()).manhattanLength();
+ if (internal::isWayland()
+ && DragDistanceWayland >= CDockManager::startDragDistance())
+ {
+ auto FloatingContainer = d->DockArea->dockContainer()->floatingWidget();
+ if (FloatingContainer)
+ {
+ d->DragState = DraggingInactive;
+ CFloatingDockContainer::startPlatformDrag(FloatingContainer,
+ mapToGlobal(d->DragStartMousePos), this);
+ }
+ }
return;
}
@@ -709,6 +825,11 @@ void CDockAreaTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
return;
}
+ if (!CDockManager::testConfigFlag(CDockManager::DoubleClickUndocksWidget))
+ {
+ return;
+ }
+
d->makeAreaFloating(event->pos(), DraggingInactive);
}
@@ -744,24 +865,35 @@ void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev)
return;
}
- const bool isAutoHide = d->DockArea->isAutoHide();
+ auto Menu = buildContextMenu(nullptr);
+ Menu->exec(ev->globalPos());
+ delete Menu;
+}
+
+QMenu* CDockAreaTitleBar::buildContextMenu(QMenu *Menu)
+{
+ const bool isAutoHide = d->DockArea->isAutoHide();
const bool isTopLevelArea = d->DockArea->isTopLevelArea();
QAction* Action;
- QMenu Menu(this);
- if (!isTopLevelArea)
+ if (Menu == nullptr)
+ {
+ Menu = new QMenu(this);
+ }
+
+ if (!isTopLevelArea)
{
- Action = Menu.addAction(isAutoHide ? tr("Detach") : tr("Detach Group"),
+ Action = Menu->addAction(isAutoHide ? tr("Detach") : tr("Detach Group"),
this, SLOT(onUndockButtonClicked()));
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable));
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
{
- Action = Menu.addAction(isAutoHide ? tr("Unpin (Dock)") : tr("Pin Group"), this, SLOT(onAutoHideDockAreaActionClicked()));
+ Action = Menu->addAction(isAutoHide ? tr("Unpin (Dock)") : tr("Pin Group"), this, SLOT(onAutoHideDockAreaActionClicked()));
auto AreaIsPinnable = d->DockArea->features().testFlag(CDockWidget::DockWidgetPinnable);
Action->setEnabled(AreaIsPinnable);
if (!isAutoHide)
{
- auto menu = Menu.addMenu(tr("Pin Group To..."));
+ auto menu = Menu->addMenu(tr("Pin Group To..."));
menu->setEnabled(AreaIsPinnable);
d->createAutoHideToAction(tr("Top"), SideBarTop, menu);
d->createAutoHideToAction(tr("Left"), SideBarLeft, menu);
@@ -769,28 +901,27 @@ void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev)
d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu);
}
}
- Menu.addSeparator();
+ Menu->addSeparator();
}
if (isAutoHide)
{
- Action = Menu.addAction(tr("Minimize"), this, SLOT(minimizeAutoHideContainer()));
- Action = Menu.addAction(tr("Close"), this, SLOT(onAutoHideCloseActionTriggered()));
+ 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 = Menu->addAction(isAutoHide ? tr("Close") : tr("Close Group"), this, SLOT(onCloseButtonClicked()));
}
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable));
if (!isAutoHide && !isTopLevelArea)
{
- Action = Menu.addAction(tr("Close Other Groups"), d->DockArea, SLOT(closeOtherAreas()));
+ Action = Menu->addAction(tr("Close Other Groups"), d->DockArea, SLOT(closeOtherAreas()));
}
- Menu.exec(ev->globalPos());
+ return Menu;
}
-
//============================================================================
void CDockAreaTitleBar::insertWidget(int index, QWidget *widget)
{
@@ -853,9 +984,10 @@ QString CDockAreaTitleBar::titleBarButtonToolTip(TitleBarButton Button) const
//============================================================================
void CDockAreaTitleBar::showAutoHideControls(bool Show)
{
- d->TabBar->setVisible(!Show); // Auto hide toolbar never has tabs
+ d->TabBar->setVisible(!Show); // Auto hide toolbar never has tabs
d->MinimizeButton->setVisible(Show);
- d->AutoHideTitleLabel->setVisible(Show);
+ if (!CDockManager::testConfigFlag(CDockManager::TabsAtBottom))
+ d->AutoHideTitleLabel->setVisible(Show);
}
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTitleBar.h b/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTitleBar.h
index f4179d917..5d4895876 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTitleBar.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaTitleBar.h
@@ -152,6 +152,11 @@ protected:
*/
virtual void contextMenuEvent(QContextMenuEvent *event) override;
+ /**
+ * Handle resize events
+ */
+ virtual void resizeEvent(QResizeEvent *event) override;
+
public Q_SLOTS:
/**
* Call this slot to tell the title bar that it should update the tabs menu
@@ -171,7 +176,7 @@ public:
/**
* Virtual Destructor
*/
- virtual ~CDockAreaTitleBar();
+ ~CDockAreaTitleBar() override;
/**
* Returns the pointer to the tabBar()
@@ -244,6 +249,20 @@ public:
*/
bool isAutoHide() const;
+ /**
+ * Fills the provided menu with standard entries. If a nullptr is passed, a
+ * new menu is created and filled with standard entries.
+ * This function is called from the actual version of contextMenuEvent, but
+ * can be called from any code. Caller is responsible of deleting the created
+ * object.
+ *
+ * @param menu The QMenu to fill with standard entries. If nullptr, a new
+ * QMenu will be created.
+ * @return The filled QMenu, either the provided one or a newly created one if
+ * nullptr was passed.
+ */
+ virtual QMenu *buildContextMenu(QMenu *);
+
Q_SIGNALS:
/**
* This signal is emitted if a tab in the tab bar is clicked by the user
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.cpp
index 0678e33c3..61c94dccd 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.cpp
@@ -1,1495 +1,1570 @@
-/*******************************************************************************
-** Qt Advanced Docking System
-** Copyright (C) 2017 Uwe Kindler
-**
-** This library is free software; you can redistribute it and/or
-** modify it under the terms of the GNU Lesser General Public
-** License as published by the Free Software Foundation; either
-** version 2.1 of the License, or (at your option) any later version.
-**
-** This library is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-** Lesser General Public License for more details.
-**
-** You should have received a copy of the GNU Lesser General Public
-** License along with this library; If not, see <http://www.gnu.org/licenses/>.
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockAreaWidget.cpp
-/// \author Uwe Kindler
-/// \date 24.02.2017
-/// \brief Implementation of CDockAreaWidget class
-//============================================================================
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include <AutoHideDockContainer.h>
-#include <AutoHideTab.h>
-#include "DockAreaWidget.h"
-
-#include <QStackedLayout>
-#include <QScrollBar>
-#include <QWheelEvent>
-#include <QStyle>
-#include <QPushButton>
-#include <QDebug>
-#include <QMenu>
-#include <QXmlStreamWriter>
-#include <QList>
-
-#include "ElidingLabel.h"
-#include "DockContainerWidget.h"
-#include "DockWidget.h"
-#include "FloatingDockContainer.h"
-#include "DockManager.h"
-#include "DockOverlay.h"
-#include "DockAreaTabBar.h"
-#include "DockSplitter.h"
-#include "DockAreaTitleBar.h"
-#include "DockComponentsFactory.h"
-#include "DockWidgetTab.h"
-#include "DockingStateReader.h"
-
-
-namespace ads
-{
-static const char* const INDEX_PROPERTY = "index";
-static const char* const ACTION_PROPERTY = "action";
-
-/**
- * Check, if auto hide is enabled
- */
-static bool isAutoHideFeatureEnabled()
-{
- return CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled);
-}
-
-
-/**
- * Internal dock area layout mimics stack layout but only inserts the current
- * widget into the internal QLayout object.
- * \warning Only the current widget has a parent. All other widgets
- * do not have a parent. That means, a widget that is in this layout may
- * return nullptr for its parent() function if it is not the current widget.
- */
-class CDockAreaLayout
-{
-private:
- QBoxLayout* m_ParentLayout;
- QList<QPointer<QWidget>> m_Widgets;
- int m_CurrentIndex = -1;
- QWidget* m_CurrentWidget = nullptr;
-
-public:
- /**
- * Creates an instance with the given parent layout
- */
- CDockAreaLayout(QBoxLayout* ParentLayout)
- : m_ParentLayout(ParentLayout)
- {
-
- }
-
- /**
- * Returns the number of widgets in this layout
- */
- int count() const
- {
- return m_Widgets.count();
- }
-
- /**
- * Inserts the widget at the given index position into the internal widget
- * list
- */
- void insertWidget(int index, QWidget* Widget)
- {
- Widget->setParent(nullptr);
- if (index < 0)
- {
- index = m_Widgets.count();
- }
- m_Widgets.insert(index, Widget);
- if (m_CurrentIndex < 0)
- {
- setCurrentIndex(index);
- }
- else
- {
- if (index <= m_CurrentIndex )
- {
- ++m_CurrentIndex;
- }
- }
- }
-
- /**
- * Removes the given widget from the layout
- */
- void removeWidget(QWidget* Widget)
- {
- if (currentWidget() == Widget)
- {
- auto LayoutItem = m_ParentLayout->takeAt(1);
- if (LayoutItem)
- {
- LayoutItem->widget()->setParent(nullptr);
- }
- delete LayoutItem;
- m_CurrentWidget = nullptr;
- m_CurrentIndex = -1;
- }
- else if (indexOf(Widget) < m_CurrentIndex)
- {
- --m_CurrentIndex;
- }
- m_Widgets.removeOne(Widget);
- }
-
- /**
- * Returns the current selected widget
- */
- QWidget* currentWidget() const
- {
- return m_CurrentWidget;
- }
-
- /**
- * Activates the widget with the give index.
- */
- void setCurrentIndex(int index)
- {
- QWidget *prev = currentWidget();
- QWidget *next = widget(index);
- if (!next || (next == prev && !m_CurrentWidget))
- {
- return;
- }
-
- bool reenableUpdates = false;
- QWidget *parent = m_ParentLayout->parentWidget();
-
- if (parent && parent->updatesEnabled())
- {
- reenableUpdates = true;
- parent->setUpdatesEnabled(false);
- }
-
- auto LayoutItem = m_ParentLayout->takeAt(1);
- if (LayoutItem)
- {
- LayoutItem->widget()->setParent(nullptr);
- }
- delete LayoutItem;
-
- m_ParentLayout->addWidget(next);
- if (prev)
- {
- prev->hide();
- }
- m_CurrentIndex = index;
- m_CurrentWidget = next;
-
-
- if (reenableUpdates)
- {
- parent->setUpdatesEnabled(true);
- }
- }
-
- /**
- * Returns the index of the current active widget
- */
- int currentIndex() const
- {
- return m_CurrentIndex;
- }
-
- /**
- * Returns true if there are no widgets in the layout
- */
- bool isEmpty() const
- {
- return m_Widgets.empty();
- }
-
- /**
- * Returns the index of the given widget
- */
- int indexOf(QWidget* w) const
- {
- return m_Widgets.indexOf(w);
- }
-
- /**
- * Returns the widget for the given index
- */
- QWidget* widget(int index) const
- {
- return (index < m_Widgets.size()) ? m_Widgets.at(index) : nullptr;
- }
-
- /**
- * Returns the geometry of the current active widget
- */
- QRect geometry() const
- {
- return m_Widgets.empty() ? QRect() : currentWidget()->geometry();
- }
-};
-
-
-
-using DockAreaLayout = CDockAreaLayout;
-static const DockWidgetAreas DefaultAllowedAreas = AllDockAreas;
-
-
-/**
- * Private data class of CDockAreaWidget class (pimpl)
- */
-struct DockAreaWidgetPrivate
-{
- CDockAreaWidget* _this = nullptr;
- QBoxLayout* Layout = nullptr;
- DockAreaLayout* ContentsLayout = nullptr;
- CDockAreaTitleBar* TitleBar = nullptr;
- CDockManager* DockManager = nullptr;
- CAutoHideDockContainer* AutoHideDockContainer = nullptr;
- bool UpdateTitleBarButtons = false;
- DockWidgetAreas AllowedAreas = DefaultAllowedAreas;
- QSize MinSizeHint;
- CDockAreaWidget::DockAreaFlags Flags{CDockAreaWidget::DefaultFlags};
-
- /**
- * Private data constructor
- */
- DockAreaWidgetPrivate(CDockAreaWidget* _public);
-
- /**
- * Creates the layout for top area with tabs and close button
- */
- void createTitleBar();
-
- /**
- * Returns the dock widget with the given index
- */
- CDockWidget* dockWidgetAt(int index)
- {
- return qobject_cast<CDockWidget*>(ContentsLayout->widget(index));
- }
-
- /**
- * Convenience function to ease title widget access by index
- */
- CDockWidgetTab* tabWidgetAt(int index)
- {
- return dockWidgetAt(index)->tabWidget();
- }
-
-
- /**
- * Returns the tab action of the given dock widget
- */
- QAction* dockWidgetTabAction(CDockWidget* DockWidget) const
- {
- return qvariant_cast<QAction*>(DockWidget->property(ACTION_PROPERTY));
- }
-
- /**
- * Returns the index of the given dock widget
- */
- int dockWidgetIndex(CDockWidget* DockWidget) const
- {
- return DockWidget->property(INDEX_PROPERTY).toInt();
- }
-
- /**
- * Convenience function for tabbar access
- */
- CDockAreaTabBar* tabBar() const
- {
- return TitleBar->tabBar();
- }
-
- /**
- * Updates the enable state of the close and detach button
- */
- void updateTitleBarButtonStates();
-
- /**
- * Updates the enable state of the close and detach button
- */
- void updateTitleBarButtonVisibility(bool isTopLevel);
-
- /**
- * Scans all contained dock widgets for the max. minimum size hint
- */
- void updateMinimumSizeHint()
- {
- MinSizeHint = QSize();
- for (int i = 0; i < ContentsLayout->count(); ++i)
- {
- auto Widget = ContentsLayout->widget(i);
- MinSizeHint.setHeight(qMax(MinSizeHint.height(), Widget->minimumSizeHint().height()));
- MinSizeHint.setWidth(qMax(MinSizeHint.width(), Widget->minimumSizeHint().width()));
- }
- }
-};
-
-
-//============================================================================
-DockAreaWidgetPrivate::DockAreaWidgetPrivate(CDockAreaWidget* _public) :
- _this(_public)
-{
-
-}
-
-
-//============================================================================
-void DockAreaWidgetPrivate::createTitleBar()
-{
- TitleBar = componentsFactory()->createDockAreaTitleBar(_this);
- Layout->addWidget(TitleBar);
- QObject::connect(tabBar(), &CDockAreaTabBar::tabCloseRequested, _this, &CDockAreaWidget::onTabCloseRequested);
- QObject::connect(TitleBar, &CDockAreaTitleBar::tabBarClicked, _this, &CDockAreaWidget::setCurrentIndex);
- QObject::connect(tabBar(), &CDockAreaTabBar::tabMoved, _this, &CDockAreaWidget::reorderDockWidget);
-}
-
-
-//============================================================================
-void DockAreaWidgetPrivate::updateTitleBarButtonStates()
-{
- if (_this->isHidden())
- {
- UpdateTitleBarButtons = true;
- return;
- }
-
- if (_this->isAutoHide())
- {
- if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideHasCloseButton))
- {
- TitleBar->button(TitleBarButtonClose)->setEnabled(
- _this->features().testFlag(CDockWidget::DockWidgetClosable));
- }
- }
- else
- {
- TitleBar->button(TitleBarButtonUndock)->setEnabled(
- _this->features().testFlag(CDockWidget::DockWidgetFloatable));
- TitleBar->button(TitleBarButtonClose)->setEnabled(
- _this->features().testFlag(CDockWidget::DockWidgetClosable));
- }
- TitleBar->button(TitleBarButtonAutoHide)->setEnabled(
- _this->features().testFlag(CDockWidget::DockWidgetPinnable));
- TitleBar->updateDockWidgetActionsButtons();
- UpdateTitleBarButtons = false;
-}
-
-
-//============================================================================
-void DockAreaWidgetPrivate::updateTitleBarButtonVisibility(bool IsTopLevel)
-{
- auto *const container = _this->dockContainer();
- if (!container)
- {
- return;
- }
-
- bool IsAutoHide = _this->isAutoHide();
- if (IsAutoHide)
- {
- bool ShowCloseButton = CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideHasCloseButton);
- TitleBar->button(TitleBarButtonClose)->setVisible(ShowCloseButton);
- TitleBar->button(TitleBarButtonAutoHide)->setVisible(true);
- TitleBar->button(TitleBarButtonUndock)->setVisible(false);
- TitleBar->button(TitleBarButtonTabsMenu)->setVisible(false);
- }
- else if (IsTopLevel)
- {
- TitleBar->button(TitleBarButtonClose)->setVisible(!container->isFloating());
- TitleBar->button(TitleBarButtonAutoHide)->setVisible(!container->isFloating());
- // Undock and tabs should never show when auto hidden
- TitleBar->button(TitleBarButtonUndock)->setVisible(!container->isFloating());
- TitleBar->button(TitleBarButtonTabsMenu)->setVisible(true);
- }
- else
- {
- TitleBar->button(TitleBarButtonClose)->setVisible(true);
- bool ShowAutoHideButton = CDockManager::testAutoHideConfigFlag(CDockManager::DockAreaHasAutoHideButton);
- TitleBar->button(TitleBarButtonAutoHide)->setVisible(ShowAutoHideButton);
- TitleBar->button(TitleBarButtonUndock)->setVisible(true);
- TitleBar->button(TitleBarButtonTabsMenu)->setVisible(true);
- }
-}
-
-
-//============================================================================
-CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent) :
- QFrame(parent),
- d(new DockAreaWidgetPrivate(this))
-{
- d->DockManager = DockManager;
- d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
- d->Layout->setContentsMargins(0, 0, 0, 0);
- d->Layout->setSpacing(0);
- setLayout(d->Layout);
-
- d->createTitleBar();
- d->ContentsLayout = new DockAreaLayout(d->Layout);
- if (d->DockManager)
- {
- Q_EMIT d->DockManager->dockAreaCreated(this);
- }
-}
-
-//============================================================================
-CDockAreaWidget::~CDockAreaWidget()
-{
- ADS_PRINT("~CDockAreaWidget()");
- delete d->ContentsLayout;
- delete d;
-}
-
-
-//============================================================================
-CDockManager* CDockAreaWidget::dockManager() const
-{
- return d->DockManager;
-}
-
-
-//============================================================================
-CDockContainerWidget* CDockAreaWidget::dockContainer() const
-{
- return internal::findParent<CDockContainerWidget*>(this);
-}
-
-//============================================================================
-CAutoHideDockContainer* CDockAreaWidget::autoHideDockContainer() const
-{
- return d->AutoHideDockContainer;
-}
-
-
-//============================================================================
-CDockSplitter* CDockAreaWidget::parentSplitter() const
-{
- return internal::findParent<CDockSplitter*>(this);
-}
-
-//============================================================================
-bool CDockAreaWidget::isAutoHide() const
-{
- return d->AutoHideDockContainer != nullptr;
-}
-
-//============================================================================
-void CDockAreaWidget::setAutoHideDockContainer(CAutoHideDockContainer* AutoHideDockContainer)
-{
- d->AutoHideDockContainer = AutoHideDockContainer;
- updateAutoHideButtonCheckState();
- updateTitleBarButtonsToolTips();
- d->TitleBar->button(TitleBarButtonAutoHide)->setShowInTitleBar(true);
-}
-
-
-//============================================================================
-void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget)
-{
- insertDockWidget(d->ContentsLayout->count(), 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);
- auto TabWidget = DockWidget->tabWidget();
- // Inserting the tab will change the current index which in turn will
- // make the tab widget visible in the slot
- d->tabBar()->blockSignals(true);
- d->tabBar()->insertTab(index, TabWidget);
- d->tabBar()->blockSignals(false);
- TabWidget->setVisible(!DockWidget->isClosed());
- d->TitleBar->autoHideTitleLabel()->setText(DockWidget->windowTitle());
- DockWidget->setProperty(INDEX_PROPERTY, index);
- d->MinSizeHint.setHeight(qMax(d->MinSizeHint.height(), DockWidget->minimumSizeHint().height()));
- d->MinSizeHint.setWidth(qMax(d->MinSizeHint.width(), DockWidget->minimumSizeHint().width()));
- if (Activate)
- {
- setCurrentIndex(index);
- DockWidget->setClosedState(false); // Set current index can show the widget without changing the close state, added to keep the close state consistent
- }
- // If this dock area is hidden, then we need to make it visible again
- // by calling DockWidget->toggleViewInternal(true);
- if (!this->isVisible() && d->ContentsLayout->count() > 1 && !dockManager()->isRestoringState())
- {
- DockWidget->toggleViewInternal(true);
- }
- d->updateTitleBarButtonStates();
- updateTitleBarVisibility();
-}
-
-
-//============================================================================
-void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
-{
- ADS_PRINT("CDockAreaWidget::removeDockWidget");
- if (!DockWidget)
- {
- return;
- }
-
-
- // If this dock area is in a auto hide container, then we can delete
- // the auto hide container now
- if (isAutoHide())
- {
- autoHideDockContainer()->cleanupAndDelete();
- return;
- }
-
- auto CurrentDockWidget = currentDockWidget();
- auto NextOpenDockWidget = (DockWidget == CurrentDockWidget) ? nextOpenDockWidget(DockWidget) : nullptr;
-
- d->ContentsLayout->removeWidget(DockWidget);
- auto TabWidget = DockWidget->tabWidget();
- TabWidget->hide();
- d->tabBar()->removeTab(TabWidget);
- TabWidget->setParent(DockWidget);
- DockWidget->setDockArea(nullptr);
- CDockContainerWidget* DockContainer = dockContainer();
- if (NextOpenDockWidget)
- {
- setCurrentDockWidget(NextOpenDockWidget);
- }
- else if (d->ContentsLayout->isEmpty() && DockContainer->dockAreaCount() >= 1)
- {
- ADS_PRINT("Dock Area empty");
- DockContainer->removeDockArea(this);
- this->deleteLater();
- if(DockContainer->dockAreaCount() == 0)
- {
- if(CFloatingDockContainer* FloatingDockContainer = DockContainer->floatingWidget())
- {
- FloatingDockContainer->hide();
- FloatingDockContainer->deleteLater();
- }
- }
- }
- else if (DockWidget == CurrentDockWidget)
- {
- // if contents layout is not empty but there are no more open dock
- // widgets, then we need to hide the dock area because it does not
- // contain any visible content
- hideAreaWithNoVisibleContent();
- }
-
- d->updateTitleBarButtonStates();
- updateTitleBarVisibility();
- d->updateMinimumSizeHint();
- auto TopLevelDockWidget = DockContainer->topLevelDockWidget();
- if (TopLevelDockWidget)
- {
- TopLevelDockWidget->emitTopLevelChanged(true);
- }
-
-#if (ADS_DEBUG_LEVEL > 0)
- DockContainer->dumpLayout();
-#endif
-}
-
-
-//============================================================================
-void CDockAreaWidget::hideAreaWithNoVisibleContent()
-{
- this->toggleView(false);
-
- // Hide empty parent splitters
- auto Splitter = parentSplitter();
- internal::hideEmptyParentSplitters(Splitter);
-
- //Hide empty floating widget
- CDockContainerWidget* Container = this->dockContainer();
- if (!Container->isFloating() && !CDockManager::testConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar))
- {
- return;
- }
-
- updateTitleBarVisibility();
- auto TopLevelWidget = Container->topLevelDockWidget();
- auto FloatingWidget = Container->floatingWidget();
- if (TopLevelWidget)
- {
- if (FloatingWidget)
- {
- FloatingWidget->updateWindowTitle();
- }
- CDockWidget::emitTopLevelEventForWidget(TopLevelWidget, true);
- }
- else if (Container->openedDockAreas().isEmpty() && FloatingWidget)
- {
- FloatingWidget->hide();
- }
- if (isAutoHide())
- {
- autoHideDockContainer()->hide();
- }
-}
-
-
-//============================================================================
-void CDockAreaWidget::onTabCloseRequested(int Index)
-{
- ADS_PRINT("CDockAreaWidget::onTabCloseRequested " << Index);
- dockWidget(Index)->requestCloseDockWidget();
-}
-
-
-//============================================================================
-CDockWidget* CDockAreaWidget::currentDockWidget() const
-{
- int CurrentIndex = currentIndex();
- if (CurrentIndex < 0)
- {
- return nullptr;
- }
-
- return dockWidget(CurrentIndex);
-}
-
-
-//============================================================================
-void CDockAreaWidget::setCurrentDockWidget(CDockWidget* DockWidget)
-{
- if (dockManager()->isRestoringState())
- {
- return;
- }
-
- internalSetCurrentDockWidget(DockWidget);
-}
-
-
-//============================================================================
-void CDockAreaWidget::internalSetCurrentDockWidget(CDockWidget* DockWidget)
-{
- int Index = index(DockWidget);
- if (Index < 0)
- {
- return;
- }
-
- setCurrentIndex(Index);
- DockWidget->setClosedState(false); // Set current index can show the widget without changing the close state, added to keep the close state consistent
-}
-
-
-//============================================================================
-void CDockAreaWidget::setCurrentIndex(int index)
-{
- auto TabBar = d->tabBar();
- if (index < 0 || index > (TabBar->count() - 1))
- {
- qWarning() << Q_FUNC_INFO << "Invalid index" << index;
- return;
- }
-
- auto cw = d->ContentsLayout->currentWidget();
- auto nw = d->ContentsLayout->widget(index);
- if (cw == nw && !nw->isHidden())
- {
- return;
- }
-
- Q_EMIT currentChanging(index);
- TabBar->setCurrentIndex(index);
- d->ContentsLayout->setCurrentIndex(index);
- d->ContentsLayout->currentWidget()->show();
- Q_EMIT currentChanged(index);
-}
-
-
-//============================================================================
-int CDockAreaWidget::currentIndex() const
-{
- return d->ContentsLayout->currentIndex();
-}
-
-
-//============================================================================
-QRect CDockAreaWidget::titleBarGeometry() const
-{
- return d->TitleBar->geometry();
-}
-
-//============================================================================
-QRect CDockAreaWidget::contentAreaGeometry() const
-{
- return d->ContentsLayout->geometry();
-}
-
-
-//============================================================================
-int CDockAreaWidget::index(CDockWidget* DockWidget)
-{
- return d->ContentsLayout->indexOf(DockWidget);
-}
-
-
-//============================================================================
-QList<CDockWidget*> CDockAreaWidget::dockWidgets() const
-{
- QList<CDockWidget*> DockWidgetList;
- for (int i = 0; i < d->ContentsLayout->count(); ++i)
- {
- DockWidgetList.append(dockWidget(i));
- }
- return DockWidgetList;
-}
-
-
-//============================================================================
-int CDockAreaWidget::openDockWidgetsCount() const
-{
- int Count = 0;
- for (int i = 0; i < d->ContentsLayout->count(); ++i)
- {
- if (dockWidget(i) && !dockWidget(i)->isClosed())
- {
- ++Count;
- }
- }
- return Count;
-}
-
-
-//============================================================================
-QList<CDockWidget*> CDockAreaWidget::openedDockWidgets() const
-{
- QList<CDockWidget*> DockWidgetList;
- for (int i = 0; i < d->ContentsLayout->count(); ++i)
- {
- CDockWidget* DockWidget = dockWidget(i);
- if (DockWidget && !DockWidget->isClosed())
- {
- DockWidgetList.append(dockWidget(i));
- }
- }
- return DockWidgetList;
-}
-
-
-//============================================================================
-int CDockAreaWidget::indexOfFirstOpenDockWidget() const
-{
- for (int i = 0; i < d->ContentsLayout->count(); ++i)
- {
- if (dockWidget(i) && !dockWidget(i)->isClosed())
- {
- return i;
- }
- }
-
- return -1;
-}
-
-
-//============================================================================
-int CDockAreaWidget::dockWidgetsCount() const
-{
- return d->ContentsLayout->count();
-}
-
-
-//============================================================================
-CDockWidget* CDockAreaWidget::dockWidget(int Index) const
-{
- return qobject_cast<CDockWidget*>(d->ContentsLayout->widget(Index));
-}
-
-//============================================================================
-void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex)
-{
- ADS_PRINT("CDockAreaWidget::reorderDockWidget");
- if (fromIndex >= d->ContentsLayout->count() || fromIndex < 0
- || toIndex >= d->ContentsLayout->count() || toIndex < 0 || fromIndex == toIndex)
- {
- ADS_PRINT("Invalid index for tab movement" << fromIndex << toIndex);
- return;
- }
-
- auto Widget = d->ContentsLayout->widget(fromIndex);
- d->ContentsLayout->removeWidget(Widget);
- d->ContentsLayout->insertWidget(toIndex, Widget);
- setCurrentIndex(toIndex);
-}
-
-
-//============================================================================
-void CDockAreaWidget::toggleDockWidgetView(CDockWidget* DockWidget, bool Open)
-{
- Q_UNUSED(DockWidget);
- Q_UNUSED(Open);
- updateTitleBarVisibility();
-}
-
-
-//============================================================================
-void CDockAreaWidget::updateTitleBarVisibility()
-{
- CDockContainerWidget* Container = dockContainer();
- if (!Container)
- {
- return;
- }
-
- if (!d->TitleBar)
- {
- return;
- }
-
- bool IsAutoHide = isAutoHide();
- if (!CDockManager::testConfigFlag(CDockManager::AlwaysShowTabs))
- {
- bool Hidden = Container->hasTopLevelDockWidget() && (Container->isFloating()
- || CDockManager::testConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar));
- Hidden |= (d->Flags.testFlag(HideSingleWidgetTitleBar) && openDockWidgetsCount() == 1);
- Hidden &= !IsAutoHide; // Titlebar must always be visible when auto hidden so it can be dragged
- d->TitleBar->setVisible(!Hidden);
- }
-
- if (isAutoHideFeatureEnabled())
- {
- d->TitleBar->showAutoHideControls(IsAutoHide);
- updateTitleBarButtonVisibility(Container->topLevelDockArea() == this);
- }
-}
-
-
-//============================================================================
-void CDockAreaWidget::markTitleBarMenuOutdated()
-{
- if (d->TitleBar)
- {
- d->TitleBar->markTabsMenuOutdated();
- }
-}
-
-
-//============================================================================
-void CDockAreaWidget::updateAutoHideButtonCheckState()
-{
- auto autoHideButton = titleBarButton(TitleBarButtonAutoHide);
- autoHideButton->blockSignals(true);
- autoHideButton->setChecked(isAutoHide());
- autoHideButton->blockSignals(false);
-}
-
-
-//============================================================================
-void CDockAreaWidget::updateTitleBarButtonVisibility(bool IsTopLevel) const
-{
- d->updateTitleBarButtonVisibility(IsTopLevel);
-}
-
-
-//============================================================================
-void CDockAreaWidget::updateTitleBarButtonsToolTips()
-{
- internal::setToolTip(titleBarButton(TitleBarButtonClose),
- titleBar()->titleBarButtonToolTip(TitleBarButtonClose));
- internal::setToolTip(titleBarButton(TitleBarButtonAutoHide),
- titleBar()->titleBarButtonToolTip(TitleBarButtonAutoHide));
-}
-
-
-//============================================================================
-void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
-{
- s.writeStartElement("Area");
- s.writeAttribute("Tabs", QString::number(d->ContentsLayout->count()));
- auto CurrentDockWidget = currentDockWidget();
- QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : "";
- s.writeAttribute("Current", Name);
-
- if (d->AllowedAreas != DefaultAllowedAreas)
- {
- s.writeAttribute("AllowedAreas", QString::number(d->AllowedAreas, 16));
- }
-
- if (d->Flags != DefaultFlags)
- {
- s.writeAttribute("Flags", QString::number(d->Flags, 16));
- }
- ADS_PRINT("CDockAreaWidget::saveState TabCount: " << d->ContentsLayout->count()
- << " Current: " << Name);
- for (int i = 0; i < d->ContentsLayout->count(); ++i)
- {
- dockWidget(i)->saveState(s);
- }
- s.writeEndElement();
-}
-
-
-//============================================================================
-bool CDockAreaWidget::restoreState(CDockingStateReader& s, CDockAreaWidget*& CreatedWidget,
- bool Testing, CDockContainerWidget* Container)
-{
- bool Ok;
-#ifdef ADS_DEBUG_PRINT
- int Tabs = s.attributes().value("Tabs").toInt(&Ok);
- if (!Ok)
- {
- return false;
- }
-#endif
-
- QString CurrentDockWidget = s.attributes().value("Current").toString();
- ADS_PRINT("Restore NodeDockArea Tabs: " << Tabs << " Current: "
- << CurrentDockWidget);
-
- auto DockManager = Container->dockManager();
- CDockAreaWidget* DockArea = nullptr;
- if (!Testing)
- {
- DockArea = new CDockAreaWidget(DockManager, Container);
- const auto AllowedAreasAttribute = s.attributes().value("AllowedAreas");
- if (!AllowedAreasAttribute.isEmpty())
- {
- DockArea->setAllowedAreas((DockWidgetArea)AllowedAreasAttribute.toInt(nullptr, 16));
- }
-
- const auto FlagsAttribute = s.attributes().value("Flags");
- if (!FlagsAttribute.isEmpty())
- {
- DockArea->setDockAreaFlags((CDockAreaWidget::DockAreaFlags)FlagsAttribute.toInt(nullptr, 16));
- }
- }
-
- while (s.readNextStartElement())
- {
- if (s.name() != QLatin1String("Widget"))
- {
- continue;
- }
-
- auto ObjectName = s.attributes().value("Name");
- if (ObjectName.isEmpty())
- {
- return false;
- }
-
- bool Closed = s.attributes().value("Closed").toInt(&Ok);
- if (!Ok)
- {
- return false;
- }
-
- s.skipCurrentElement();
- CDockWidget* DockWidget = DockManager->findDockWidget(ObjectName.toString());
- if (!DockWidget || Testing)
- {
- continue;
- }
-
- ADS_PRINT("Dock Widget found - parent " << DockWidget->parent());
- if (DockWidget->autoHideDockContainer())
- {
- DockWidget->autoHideDockContainer()->cleanupAndDelete();
- }
-
- // We hide the DockArea here to prevent the short display (the flashing)
- // of the dock areas during application startup
- DockArea->hide();
- DockArea->addDockWidget(DockWidget);
- DockWidget->setToggleViewActionChecked(!Closed);
- DockWidget->setClosedState(Closed);
- DockWidget->setProperty(internal::ClosedProperty, Closed);
- DockWidget->setProperty(internal::DirtyProperty, false);
- }
-
- if (Testing)
- {
- return true;
- }
-
- if (!DockArea->dockWidgetsCount())
- {
- delete DockArea;
- DockArea = nullptr;
- }
- else
- {
- DockArea->setProperty("currentDockWidget", CurrentDockWidget);
- }
-
- CreatedWidget = DockArea;
- return true;
-}
-
-
-//============================================================================
-CDockWidget* CDockAreaWidget::nextOpenDockWidget(CDockWidget* DockWidget) const
-{
- auto OpenDockWidgets = openedDockWidgets();
- if (OpenDockWidgets.count() > 1 || (OpenDockWidgets.count() == 1 && OpenDockWidgets[0] != DockWidget))
- {
- if (OpenDockWidgets.last() == DockWidget)
- {
- CDockWidget* NextDockWidget = OpenDockWidgets[OpenDockWidgets.count() - 2];
- // search backwards for widget with tab
- for (int i = OpenDockWidgets.count() - 2; i >= 0; --i)
- {
- auto dw = OpenDockWidgets[i];
- if (!dw->features().testFlag(CDockWidget::NoTab))
- {
- return dw;
- }
- }
-
- // return widget without tab
- return NextDockWidget;
- }
- else
- {
- int IndexOfDockWidget = OpenDockWidgets.indexOf(DockWidget);
- CDockWidget* NextDockWidget = OpenDockWidgets[IndexOfDockWidget + 1];
- // search forwards for widget with tab
- for (int i = IndexOfDockWidget + 1; i < OpenDockWidgets.count(); ++i)
- {
- auto dw = OpenDockWidgets[i];
- if (!dw->features().testFlag(CDockWidget::NoTab))
- {
- return dw;
- }
- }
-
- // search backwards for widget with tab
- for (int i = IndexOfDockWidget - 1; i >= 0; --i)
- {
- auto dw = OpenDockWidgets[i];
- if (!dw->features().testFlag(CDockWidget::NoTab))
- {
- return dw;
- }
- }
-
- // return widget without tab
- return NextDockWidget;
- }
- }
- else
- {
- return nullptr;
- }
-}
-
-
-//============================================================================
-CDockWidget::DockWidgetFeatures CDockAreaWidget::features(eBitwiseOperator Mode) const
-{
- if (BitwiseAnd == Mode)
- {
- CDockWidget::DockWidgetFeatures Features(CDockWidget::AllDockWidgetFeatures);
- for (const auto DockWidget : dockWidgets())
- {
- Features &= DockWidget->features();
- }
- return Features;
- }
- else
- {
- CDockWidget::DockWidgetFeatures Features(CDockWidget::NoDockWidgetFeatures);
- for (const auto DockWidget : dockWidgets())
- {
- Features |= DockWidget->features();
- }
- return Features;
- }
-}
-
-
-//============================================================================
-void CDockAreaWidget::toggleView(bool Open)
-{
- setVisible(Open);
-
- Q_EMIT viewToggled(Open);
-}
-
-
-//============================================================================
-void CDockAreaWidget::setVisible(bool Visible)
-{
- Super::setVisible(Visible);
- if (d->UpdateTitleBarButtons)
- {
- d->updateTitleBarButtonStates();
- }
-}
-
-
-//============================================================================
-void CDockAreaWidget::setAllowedAreas(DockWidgetAreas areas)
-{
- d->AllowedAreas = areas;
-}
-
-
-//============================================================================
-DockWidgetAreas CDockAreaWidget::allowedAreas() const
-{
- return d->AllowedAreas;
-}
-
-
-//============================================================================
-CDockAreaWidget::DockAreaFlags CDockAreaWidget::dockAreaFlags() const
-{
- return d->Flags;
-}
-
-
-//============================================================================
-void CDockAreaWidget::setDockAreaFlags(DockAreaFlags Flags)
-{
- auto ChangedFlags = d->Flags ^ Flags;
- d->Flags = Flags;
- if (ChangedFlags.testFlag(HideSingleWidgetTitleBar))
- {
- updateTitleBarVisibility();
- }
-}
-
-
-//============================================================================
-void CDockAreaWidget::setDockAreaFlag(eDockAreaFlag Flag, bool On)
-{
- auto flags = dockAreaFlags();
- internal::setFlag(flags, Flag, On);
- setDockAreaFlags(flags);
-}
-
-
-//============================================================================
-QAbstractButton* CDockAreaWidget::titleBarButton(TitleBarButton which) const
-{
- return d->TitleBar->button(which);
-}
-
-
-//============================================================================
-void CDockAreaWidget::closeArea()
-{
- // If there is only one single dock widget and this widget has the
- // DeleteOnClose feature or CustomCloseHandling, then we delete the dock widget now;
- // in the case of CustomCloseHandling, the CDockWidget class will emit its
- // closeRequested signal and not actually delete unless the signal is handled in a way that deletes it
- auto OpenDockWidgets = openedDockWidgets();
- if (OpenDockWidgets.count() == 1 &&
- (OpenDockWidgets[0]->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) || OpenDockWidgets[0]->features().testFlag(CDockWidget::CustomCloseHandling))
- && !isAutoHide())
- {
- OpenDockWidgets[0]->closeDockWidgetInternal();
- }
- else
- {
- for (auto DockWidget : openedDockWidgets())
- {
- if ((DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) && DockWidget->features().testFlag(CDockWidget::DockWidgetForceCloseWithArea)) ||
- DockWidget->features().testFlag(CDockWidget::CustomCloseHandling))
- {
- DockWidget->closeDockWidgetInternal();
- }
- else if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) && isAutoHide())
- {
- DockWidget->closeDockWidgetInternal();
- }
- else
- {
- DockWidget->toggleView(false);
- }
- }
- }
-}
-
-
-enum eBorderLocation
-{
- BorderNone = 0,
- BorderLeft = 0x01,
- BorderRight = 0x02,
- BorderTop = 0x04,
- BorderBottom = 0x08,
- BorderVertical = BorderLeft | BorderRight,
- BorderHorizontal = BorderTop | BorderBottom,
- BorderTopLeft = BorderTop | BorderLeft,
- BorderTopRight = BorderTop | BorderRight,
- BorderBottomLeft = BorderBottom | BorderLeft,
- BorderBottomRight = BorderBottom | BorderRight,
- BorderVerticalBottom = BorderVertical | BorderBottom,
- BorderVerticalTop = BorderVertical | BorderTop,
- BorderHorizontalLeft = BorderHorizontal | BorderLeft,
- BorderHorizontalRight = BorderHorizontal | BorderRight,
- BorderAll = BorderVertical | BorderHorizontal
-};
-
-
-//============================================================================
-SideBarLocation CDockAreaWidget::calculateSideTabBarArea() const
-{
- auto Container = dockContainer();
- auto ContentRect = Container->contentRect();
-
- int borders = BorderNone; // contains all borders that are touched by the dock ware
- auto DockAreaTopLeft = mapTo(Container, rect().topLeft());
- auto DockAreaRect = rect();
- DockAreaRect.moveTo(DockAreaTopLeft);
- const qreal aspectRatio = DockAreaRect.width() / (qMax(1, DockAreaRect.height()) * 1.0);
- const qreal sizeRatio = (qreal)ContentRect.width() / DockAreaRect.width();
- static const int MinBorderDistance = 16;
- bool HorizontalOrientation = (aspectRatio > 1.0) && (sizeRatio < 3.0);
-
- // measure border distances - a distance less than 16 px means we touch the
- // border
- int BorderDistance[4];
-
- int Distance = qAbs(ContentRect.topLeft().y() - DockAreaRect.topLeft().y());
- BorderDistance[SideBarLocation::SideBarTop] = (Distance < MinBorderDistance) ? 0 : Distance;
- if (!BorderDistance[SideBarLocation::SideBarTop])
- {
- borders |= BorderTop;
- }
-
- Distance = qAbs(ContentRect.bottomRight().y() - DockAreaRect.bottomRight().y());
- BorderDistance[SideBarLocation::SideBarBottom] = (Distance < MinBorderDistance) ? 0 : Distance;
- if (!BorderDistance[SideBarLocation::SideBarBottom])
- {
- borders |= BorderBottom;
- }
-
- Distance = qAbs(ContentRect.topLeft().x() - DockAreaRect.topLeft().x());
- BorderDistance[SideBarLocation::SideBarLeft] = (Distance < MinBorderDistance) ? 0 : Distance;
- if (!BorderDistance[SideBarLocation::SideBarLeft])
- {
- borders |= BorderLeft;
- }
-
- Distance = qAbs(ContentRect.bottomRight().x() - DockAreaRect.bottomRight().x());
- BorderDistance[SideBarLocation::SideBarRight] = (Distance < MinBorderDistance) ? 0 : Distance;
- if (!BorderDistance[SideBarLocation::SideBarRight])
- {
- borders |= BorderRight;
- }
-
- auto SideTab = SideBarLocation::SideBarRight;
- switch (borders)
- {
- // 1. It's touching all borders
- case BorderAll: SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarRight; break;
-
- // 2. It's touching 3 borders
- case BorderVerticalBottom : SideTab = SideBarLocation::SideBarBottom; break;
- case BorderVerticalTop : SideTab = SideBarLocation::SideBarTop; break;
- case BorderHorizontalLeft: SideTab = SideBarLocation::SideBarLeft; break;
- case BorderHorizontalRight: SideTab = SideBarLocation::SideBarRight; break;
-
- // 3. It's touching horizontal or vertical borders
- case BorderVertical : SideTab = SideBarLocation::SideBarBottom; break;
- case BorderHorizontal: SideTab = SideBarLocation::SideBarRight; break;
-
- // 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. It's touching only one border
- case BorderLeft: SideTab = SideBarLocation::SideBarLeft; break;
- case BorderRight: SideTab = SideBarLocation::SideBarRight; break;
- case BorderTop: SideTab = SideBarLocation::SideBarTop; break;
- case BorderBottom: SideTab = SideBarLocation::SideBarBottom; break;
- }
-
- return SideTab;
-}
-
-
-//============================================================================
-void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location, int TabIndex)
-{
- if (!isAutoHideFeatureEnabled())
- {
- return;
- }
-
- if (!Enable)
- {
- if (isAutoHide())
- {
- 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())
- {
- if (Enable == isAutoHide())
- {
- continue;
- }
-
- if (!DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable))
- {
- continue;
- }
-
- dockContainer()->createAndSetupAutoHideContainer(area, DockWidget, TabIndex++);
- }
-}
-
-
-//============================================================================
-void CDockAreaWidget::toggleAutoHide(SideBarLocation Location)
-{
- if (!isAutoHideFeatureEnabled())
- {
- return;
- }
-
- setAutoHide(!isAutoHide(), Location);
-}
-
-
-//============================================================================
-void CDockAreaWidget::closeOtherAreas()
-{
- dockContainer()->closeOtherAreas(this);
-}
-
-
-//============================================================================
-CDockAreaTitleBar* CDockAreaWidget::titleBar() const
-{
- return d->TitleBar;
-}
-
-
-//============================================================================
-bool CDockAreaWidget::isCentralWidgetArea() const
-{
- if (dockWidgetsCount()!= 1)
- {
- return false;
- }
-
- return dockManager()->centralWidget() == dockWidgets().constFirst();
-}
-
-
-//============================================================================
-bool CDockAreaWidget::containsCentralWidget() const
-{
- auto centralWidget = dockManager()->centralWidget();
- for (const auto &dockWidget : dockWidgets())
- {
- if (dockWidget == centralWidget)
- {
- return true;
- }
- }
-
- return false;
-}
-
-
-//============================================================================
-QSize CDockAreaWidget::minimumSizeHint() const
-{
- if (!d->MinSizeHint.isValid())
- {
- return Super::minimumSizeHint();
- }
-
- if (d->TitleBar->isVisible())
- {
- return d->MinSizeHint + QSize(0, d->TitleBar->minimumSizeHint().height());
- }
- else
- {
- return d->MinSizeHint;
- }
-}
-
-
-//============================================================================
-void CDockAreaWidget::onDockWidgetFeaturesChanged()
-{
- if (d->TitleBar)
- {
- d->updateTitleBarButtonStates();
- }
-}
-
-
-//============================================================================
-bool CDockAreaWidget::isTopLevelArea() const
-{
- auto Container = dockContainer();
- if (!Container)
- {
- return false;
- }
-
- return (Container->topLevelDockArea() == this);
-}
-
-
-//============================================================================
-void CDockAreaWidget::setFloating()
-{
- d->TitleBar->setAreaFloating();
-}
-
-
-#ifdef Q_OS_WIN
-//============================================================================
-bool CDockAreaWidget::event(QEvent *e)
-{
- switch (e->type())
- {
- case QEvent::PlatformSurface: return true;
- default:
- break;
- }
-
- return Super::event(e);
-}
-#endif
-
-} // namespace ads
-
-//---------------------------------------------------------------------------
-// EOF DockAreaWidget.cpp
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockAreaWidget.cpp
+/// \author Uwe Kindler
+/// \date 24.02.2017
+/// \brief Implementation of CDockAreaWidget class
+//============================================================================
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include <AutoHideDockContainer.h>
+#include <AutoHideTab.h>
+#include "DockAreaWidget.h"
+
+#include <QStackedLayout>
+#include <QScrollBar>
+#include <QStyle>
+#include <QPushButton>
+#include <QDebug>
+#include <QMenu>
+#include <QXmlStreamWriter>
+#include <QList>
+
+#include "ElidingLabel.h"
+#include "DockContainerWidget.h"
+#include "DockWidget.h"
+#include "FloatingDockContainer.h"
+#include "DockManager.h"
+#include "DockOverlay.h"
+#include "DockAreaTabBar.h"
+#include "DockSplitter.h"
+#include "DockAreaTitleBar.h"
+#include "DockComponentsFactory.h"
+#include "DockWidgetTab.h"
+#include "DockingStateReader.h"
+
+
+namespace ads
+{
+static const char* const INDEX_PROPERTY = "index";
+static const char* const ACTION_PROPERTY = "action";
+
+/**
+ * Check, if auto hide is enabled
+ */
+static bool isAutoHideFeatureEnabled()
+{
+ return CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled);
+}
+
+
+/**
+ * Internal dock area layout mimics stack layout but only inserts the current
+ * widget into the internal QLayout object.
+ * \warning Only the current widget has a parent. All other widgets
+ * do not have a parent. That means, a widget that is in this layout may
+ * return nullptr for its parent() function if it is not the current widget.
+ */
+class CDockAreaLayout
+{
+private:
+ QBoxLayout* m_ParentLayout;
+ QList<QPointer<QWidget>> m_Widgets;
+ int m_CurrentIndex = -1;
+ QWidget* m_CurrentWidget = nullptr;
+
+public:
+ /**
+ * Creates an instance with the given parent layout
+ */
+ CDockAreaLayout(QBoxLayout* ParentLayout)
+ : m_ParentLayout(ParentLayout)
+ {
+
+ }
+
+ /**
+ * Returns the number of widgets in this layout
+ */
+ int count() const
+ {
+ return m_Widgets.count();
+ }
+
+ /**
+ * Inserts the widget at the given index position into the internal widget
+ * list
+ */
+ void insertWidget(int index, QWidget* Widget)
+ {
+ Widget->setParent(nullptr);
+ if (index < 0)
+ {
+ index = m_Widgets.count();
+ }
+ m_Widgets.insert(index, Widget);
+ if (m_CurrentIndex < 0)
+ {
+ setCurrentIndex(index);
+ }
+ else
+ {
+ if (index <= m_CurrentIndex )
+ {
+ ++m_CurrentIndex;
+ }
+ }
+ }
+
+ /**
+ * Removes the given widget from the layout
+ */
+ void removeWidget(QWidget* Widget)
+ {
+ if (currentWidget() == Widget)
+ {
+ auto LayoutItem = m_ParentLayout->takeAt(1);
+ if (LayoutItem)
+ {
+ LayoutItem->widget()->setParent(nullptr);
+ }
+ delete LayoutItem;
+ m_CurrentWidget = nullptr;
+ m_CurrentIndex = -1;
+ }
+ else if (indexOf(Widget) < m_CurrentIndex)
+ {
+ --m_CurrentIndex;
+ }
+ m_Widgets.removeOne(Widget);
+ }
+
+ /**
+ * Returns the current selected widget
+ */
+ QWidget* currentWidget() const
+ {
+ return m_CurrentWidget;
+ }
+
+ /**
+ * Activates the widget with the give index.
+ */
+ void setCurrentIndex(int index)
+ {
+ QWidget *prev = currentWidget();
+ QWidget *next = widget(index);
+ if (!next || (next == prev && !m_CurrentWidget))
+ {
+ return;
+ }
+
+ bool reenableUpdates = false;
+ QWidget *parent = m_ParentLayout->parentWidget();
+
+ if (parent && parent->updatesEnabled())
+ {
+ reenableUpdates = true;
+ parent->setUpdatesEnabled(false);
+ }
+
+ if (m_CurrentWidget)
+ {
+ auto LayoutItem = m_ParentLayout->takeAt(1);
+ if (LayoutItem)
+ {
+ LayoutItem->widget()->setParent(nullptr);
+ }
+ delete LayoutItem;
+ }
+
+ m_ParentLayout->insertWidget(1, next);
+ if (prev)
+ {
+ prev->hide();
+ }
+ m_CurrentIndex = index;
+ m_CurrentWidget = next;
+
+
+ if (reenableUpdates)
+ {
+ parent->setUpdatesEnabled(true);
+ }
+ }
+
+ /**
+ * Returns the index of the current active widget
+ */
+ int currentIndex() const
+ {
+ return m_CurrentIndex;
+ }
+
+ /**
+ * Returns true if there are no widgets in the layout
+ */
+ bool isEmpty() const
+ {
+ return m_Widgets.empty();
+ }
+
+ /**
+ * Returns the index of the given widget
+ */
+ int indexOf(QWidget* w) const
+ {
+ return m_Widgets.indexOf(w);
+ }
+
+ /**
+ * Returns the widget for the given index
+ */
+ QWidget* widget(int index) const
+ {
+ return (index < m_Widgets.size()) ? m_Widgets.at(index) : nullptr;
+ }
+
+ /**
+ * Returns the geometry of the current active widget
+ */
+ QRect geometry() const
+ {
+ return m_Widgets.empty() ? QRect() : currentWidget()->geometry();
+ }
+};
+
+
+
+using DockAreaLayout = CDockAreaLayout;
+static const DockWidgetAreas DefaultAllowedAreas = AllDockAreas;
+
+
+/**
+ * Private data class of CDockAreaWidget class (pimpl)
+ */
+struct DockAreaWidgetPrivate
+{
+ CDockAreaWidget* _this = nullptr;
+ QBoxLayout* Layout = nullptr;
+ DockAreaLayout* ContentsLayout = nullptr;
+ CDockAreaTitleBar* TitleBar = nullptr;
+ CDockManager* DockManager = nullptr;
+ CAutoHideDockContainer* AutoHideDockContainer = nullptr;
+ bool UpdateTitleBarButtons = false;
+ DockWidgetAreas AllowedAreas = DefaultAllowedAreas;
+ QSize MinSizeHint;
+ CDockAreaWidget::DockAreaFlags Flags{CDockAreaWidget::DefaultFlags};
+
+ /**
+ * Private data constructor
+ */
+ DockAreaWidgetPrivate(CDockAreaWidget* _public);
+
+ /**
+ * Convenience function to ease components factory access
+ */
+ QSharedPointer<ads::CDockComponentsFactory> componentsFactory() const
+ {
+ return DockManager->componentsFactory();
+ }
+
+ /**
+ * Creates the layout for top area with tabs and close button
+ */
+ void createTitleBar();
+
+ /**
+ * Returns the dock widget with the given index
+ */
+ CDockWidget* dockWidgetAt(int index)
+ {
+ return qobject_cast<CDockWidget*>(ContentsLayout->widget(index));
+ }
+
+ /**
+ * Convenience function to ease title widget access by index
+ */
+ CDockWidgetTab* tabWidgetAt(int index)
+ {
+ return dockWidgetAt(index)->tabWidget();
+ }
+
+
+ /**
+ * Returns the tab action of the given dock widget
+ */
+ QAction* dockWidgetTabAction(CDockWidget* DockWidget) const
+ {
+ return qvariant_cast<QAction*>(DockWidget->property(ACTION_PROPERTY));
+ }
+
+ /**
+ * Returns the index of the given dock widget
+ */
+ int dockWidgetIndex(CDockWidget* DockWidget) const
+ {
+ return DockWidget->property(INDEX_PROPERTY).toInt();
+ }
+
+ /**
+ * Convenience function for tabbar access
+ */
+ CDockAreaTabBar* tabBar() const
+ {
+ return TitleBar->tabBar();
+ }
+
+ /**
+ * Updates the enable state of the close and detach button
+ */
+ void updateTitleBarButtonStates();
+
+ /**
+ * Updates the enable state of the close and detach button
+ */
+ void updateTitleBarButtonVisibility(bool isTopLevel);
+
+ /**
+ * Scans all contained dock widgets for the max. minimum size hint
+ */
+ void updateMinimumSizeHint()
+ {
+ MinSizeHint = QSize();
+ for (int i = 0; i < ContentsLayout->count(); ++i)
+ {
+ auto Widget = ContentsLayout->widget(i);
+ MinSizeHint.setHeight(qMax(MinSizeHint.height(), Widget->minimumSizeHint().height()));
+ MinSizeHint.setWidth(qMax(MinSizeHint.width(), Widget->minimumSizeHint().width()));
+ }
+ }
+};
+
+
+//============================================================================
+DockAreaWidgetPrivate::DockAreaWidgetPrivate(CDockAreaWidget* _public) :
+ _this(_public)
+{
+
+}
+
+
+//============================================================================
+void DockAreaWidgetPrivate::createTitleBar()
+{
+ TitleBar = componentsFactory()->createDockAreaTitleBar(_this);
+ Layout->addWidget(TitleBar);
+ if (CDockManager::testConfigFlag(CDockManager::TabsAtBottom))
+ {
+ // Title bar will be index 0, container widgets will be index 1,
+ // so tabs will always be at the end of the layout.
+ Layout->addWidget(tabBar());
+ tabBar()->setVisible(CDockManager::testConfigFlag(CDockManager::AlwaysShowTabs));
+ }
+
+ QObject::connect(tabBar(), &CDockAreaTabBar::tabCloseRequested, _this, &CDockAreaWidget::onTabCloseRequested);
+ QObject::connect(TitleBar, &CDockAreaTitleBar::tabBarClicked, _this, &CDockAreaWidget::setCurrentIndex);
+ QObject::connect(tabBar(), &CDockAreaTabBar::tabMoved, _this, &CDockAreaWidget::reorderDockWidget);
+}
+
+
+//============================================================================
+void DockAreaWidgetPrivate::updateTitleBarButtonStates()
+{
+ if (_this->isHidden())
+ {
+ UpdateTitleBarButtons = true;
+ return;
+ }
+
+ if (_this->isAutoHide())
+ {
+ if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideHasCloseButton))
+ {
+ TitleBar->button(TitleBarButtonClose)->setEnabled(
+ _this->features().testFlag(CDockWidget::DockWidgetClosable));
+ }
+ }
+ else
+ {
+ TitleBar->button(TitleBarButtonUndock)->setEnabled(
+ _this->features().testFlag(CDockWidget::DockWidgetFloatable));
+ TitleBar->button(TitleBarButtonClose)->setEnabled(
+ _this->features().testFlag(CDockWidget::DockWidgetClosable));
+ }
+ TitleBar->button(TitleBarButtonAutoHide)->setEnabled(
+ _this->features().testFlag(CDockWidget::DockWidgetPinnable));
+ TitleBar->updateDockWidgetActionsButtons();
+ UpdateTitleBarButtons = false;
+}
+
+
+//============================================================================
+void DockAreaWidgetPrivate::updateTitleBarButtonVisibility(bool IsTopLevel)
+{
+ auto *const container = _this->dockContainer();
+ if (!container)
+ {
+ return;
+ }
+
+ bool IsAutoHide = _this->isAutoHide();
+ if (IsAutoHide)
+ {
+ bool ShowCloseButton = CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideHasCloseButton);
+ TitleBar->button(TitleBarButtonClose)->setVisible(ShowCloseButton);
+ TitleBar->button(TitleBarButtonAutoHide)->setVisible(true);
+ TitleBar->button(TitleBarButtonUndock)->setVisible(false);
+ TitleBar->button(TitleBarButtonTabsMenu)->setVisible(false);
+ }
+ else if (IsTopLevel)
+ {
+ TitleBar->button(TitleBarButtonClose)->setVisible(!container->isFloating());
+ TitleBar->button(TitleBarButtonAutoHide)->setVisible(!container->isFloating());
+ // Undock and tabs should never show when auto hidden
+ TitleBar->button(TitleBarButtonUndock)->setVisible(!container->isFloating());
+ TitleBar->button(TitleBarButtonTabsMenu)->setVisible(true);
+ }
+ else
+ {
+ TitleBar->button(TitleBarButtonClose)->setVisible(true);
+ bool ShowAutoHideButton = CDockManager::testAutoHideConfigFlag(CDockManager::DockAreaHasAutoHideButton);
+ TitleBar->button(TitleBarButtonAutoHide)->setVisible(ShowAutoHideButton);
+ TitleBar->button(TitleBarButtonUndock)->setVisible(true);
+ TitleBar->button(TitleBarButtonTabsMenu)->setVisible(true);
+ }
+}
+
+
+//============================================================================
+CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent) :
+ QFrame(parent),
+ d(new DockAreaWidgetPrivate(this))
+{
+ d->DockManager = DockManager;
+ d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
+ d->Layout->setContentsMargins(0, 0, 0, 0);
+ d->Layout->setSpacing(0);
+ setLayout(d->Layout);
+
+ d->createTitleBar();
+ d->ContentsLayout = new DockAreaLayout(d->Layout);
+
+ if (CDockManager::testConfigFlag(CDockManager::UseNativeWindows))
+ {
+ winId();
+ }
+
+ if (d->DockManager)
+ {
+ Q_EMIT d->DockManager->dockAreaCreated(this);
+ }
+}
+
+//============================================================================
+CDockAreaWidget::~CDockAreaWidget()
+{
+ ADS_PRINT("~CDockAreaWidget()");
+ delete d->ContentsLayout;
+ delete d;
+}
+
+
+//============================================================================
+CDockManager* CDockAreaWidget::dockManager() const
+{
+ return d->DockManager;
+}
+
+
+//============================================================================
+CDockContainerWidget* CDockAreaWidget::dockContainer() const
+{
+ return internal::findParent<CDockContainerWidget*>(this);
+}
+
+//============================================================================
+CAutoHideDockContainer* CDockAreaWidget::autoHideDockContainer() const
+{
+ return d->AutoHideDockContainer;
+}
+
+
+//============================================================================
+CDockSplitter* CDockAreaWidget::parentSplitter() const
+{
+ return internal::findParent<CDockSplitter*>(this);
+}
+
+//============================================================================
+bool CDockAreaWidget::isAutoHide() const
+{
+ return d->AutoHideDockContainer != nullptr;
+}
+
+//============================================================================
+void CDockAreaWidget::setAutoHideDockContainer(CAutoHideDockContainer* AutoHideDockContainer)
+{
+ d->AutoHideDockContainer = AutoHideDockContainer;
+ updateAutoHideButtonCheckState();
+ updateTitleBarButtonsToolTips();
+ d->TitleBar->button(TitleBarButtonAutoHide)->setShowInTitleBar(true);
+}
+
+
+//============================================================================
+void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget)
+{
+ insertDockWidget(d->ContentsLayout->count(), 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);
+ auto TabWidget = DockWidget->tabWidget();
+ // Inserting the tab will change the current index which in turn will
+ // make the tab widget visible in the slot
+ d->tabBar()->blockSignals(true);
+ d->tabBar()->insertTab(index, TabWidget);
+ d->tabBar()->blockSignals(false);
+ TabWidget->setVisible(!DockWidget->isClosed());
+ d->TitleBar->autoHideTitleLabel()->setText(DockWidget->windowTitle());
+ DockWidget->setProperty(INDEX_PROPERTY, index);
+ d->MinSizeHint.setHeight(qMax(d->MinSizeHint.height(), DockWidget->minimumSizeHint().height()));
+ d->MinSizeHint.setWidth(qMax(d->MinSizeHint.width(), DockWidget->minimumSizeHint().width()));
+ if (Activate)
+ {
+ setCurrentIndex(index);
+ DockWidget->setClosedState(false); // Set current index can show the widget without changing the close state, added to keep the close state consistent
+ }
+ // If this dock area is hidden, then we need to make it visible again
+ // by calling DockWidget->toggleViewInternal(true);
+ if (!this->isVisible() && d->ContentsLayout->count() > 1 && !dockManager()->isRestoringState())
+ {
+ DockWidget->toggleViewInternal(true);
+ }
+ d->updateTitleBarButtonStates();
+ updateTitleBarVisibility();
+}
+
+
+//============================================================================
+void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
+{
+ ADS_PRINT("CDockAreaWidget::removeDockWidget");
+ if (!DockWidget)
+ {
+ return;
+ }
+
+
+ // If this dock area is in a auto hide container, then we can delete
+ // the auto hide container now
+ if (isAutoHide())
+ {
+ autoHideDockContainer()->cleanupAndDelete();
+ return;
+ }
+
+ auto CurrentDockWidget = currentDockWidget();
+ auto NextOpenDockWidget = (DockWidget == CurrentDockWidget) ? nextOpenDockWidget(DockWidget) : nullptr;
+
+ d->ContentsLayout->removeWidget(DockWidget);
+ auto TabWidget = DockWidget->tabWidget();
+ TabWidget->hide();
+ d->tabBar()->removeTab(TabWidget);
+ TabWidget->setParent(DockWidget);
+ DockWidget->setDockArea(nullptr);
+ CDockContainerWidget* DockContainer = dockContainer();
+ if (NextOpenDockWidget)
+ {
+ setCurrentDockWidget(NextOpenDockWidget);
+ }
+ else if (d->ContentsLayout->isEmpty() && DockContainer->dockAreaCount() >= 1)
+ {
+ ADS_PRINT("Dock Area empty");
+ DockContainer->removeDockArea(this);
+ this->deleteLater();
+ if(DockContainer->dockAreaCount() == 0)
+ {
+ if(CFloatingDockContainer* FloatingDockContainer = DockContainer->floatingWidget())
+ {
+ FloatingDockContainer->finishDropOperation();
+ }
+ }
+ }
+ else if (DockWidget == CurrentDockWidget)
+ {
+ // if contents layout is not empty but there are no more open dock
+ // widgets, then we need to hide the dock area because it does not
+ // contain any visible content
+ hideAreaWithNoVisibleContent();
+ }
+
+ d->updateTitleBarButtonStates();
+ updateTitleBarVisibility();
+ d->updateMinimumSizeHint();
+ auto TopLevelDockWidget = DockContainer->topLevelDockWidget();
+ if (TopLevelDockWidget)
+ {
+ TopLevelDockWidget->emitTopLevelChanged(true);
+ }
+
+#if (ADS_DEBUG_LEVEL > 0)
+ DockContainer->dumpLayout();
+#endif
+}
+
+
+//============================================================================
+void CDockAreaWidget::hideAreaWithNoVisibleContent()
+{
+ this->toggleView(false);
+
+ // Hide empty parent splitters
+ auto Splitter = parentSplitter();
+ internal::hideEmptyParentSplitters(Splitter);
+
+ //Hide empty floating widget
+ CDockContainerWidget* Container = this->dockContainer();
+ if (!Container->isFloating() && !CDockManager::testConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar))
+ {
+ return;
+ }
+
+ updateTitleBarVisibility();
+ auto TopLevelWidget = Container->topLevelDockWidget();
+ auto FloatingWidget = Container->floatingWidget();
+ if (TopLevelWidget)
+ {
+ if (FloatingWidget)
+ {
+ FloatingWidget->updateWindowTitle();
+ }
+ CDockWidget::emitTopLevelEventForWidget(TopLevelWidget, true);
+ }
+ else if (Container->openedDockAreas().isEmpty() && FloatingWidget)
+ {
+ FloatingWidget->hide();
+ }
+ if (isAutoHide())
+ {
+ autoHideDockContainer()->hide();
+ }
+}
+
+
+//============================================================================
+void CDockAreaWidget::onTabCloseRequested(int Index)
+{
+ ADS_PRINT("CDockAreaWidget::onTabCloseRequested " << Index);
+ dockWidget(Index)->requestCloseDockWidget();
+}
+
+
+//============================================================================
+CDockWidget* CDockAreaWidget::currentDockWidget() const
+{
+ int CurrentIndex = currentIndex();
+ if (CurrentIndex < 0)
+ {
+ return nullptr;
+ }
+
+ return dockWidget(CurrentIndex);
+}
+
+
+//============================================================================
+void CDockAreaWidget::setCurrentDockWidget(CDockWidget* DockWidget)
+{
+ if (dockManager()->isRestoringState())
+ {
+ return;
+ }
+
+ internalSetCurrentDockWidget(DockWidget);
+}
+
+
+//============================================================================
+void CDockAreaWidget::internalSetCurrentDockWidget(CDockWidget* DockWidget)
+{
+ int Index = index(DockWidget);
+ if (Index < 0)
+ {
+ return;
+ }
+
+ setCurrentIndex(Index);
+ DockWidget->setClosedState(false); // Set current index can show the widget without changing the close state, added to keep the close state consistent
+}
+
+
+//============================================================================
+void CDockAreaWidget::setCurrentIndex(int index)
+{
+ auto TabBar = d->tabBar();
+ if (index < 0 || index > (TabBar->count() - 1))
+ {
+ qWarning() << Q_FUNC_INFO << "Invalid index" << index;
+ return;
+ }
+
+ auto cw = d->ContentsLayout->currentWidget();
+ auto nw = d->ContentsLayout->widget(index);
+ if (cw == nw && !nw->isHidden())
+ {
+ return;
+ }
+
+ Q_EMIT currentChanging(index);
+ TabBar->setCurrentIndex(index);
+ d->ContentsLayout->setCurrentIndex(index);
+ d->ContentsLayout->currentWidget()->show();
+ d->TitleBar->autoHideTitleLabel()->setText(d->ContentsLayout->currentWidget()->windowTitle());
+ Q_EMIT currentChanged(index);
+}
+
+
+//============================================================================
+int CDockAreaWidget::currentIndex() const
+{
+ return d->ContentsLayout->currentIndex();
+}
+
+
+//============================================================================
+QRect CDockAreaWidget::titleBarGeometry() const
+{
+ return d->TitleBar->geometry();
+}
+
+//============================================================================
+QRect CDockAreaWidget::contentAreaGeometry() const
+{
+ return d->ContentsLayout->geometry();
+}
+
+
+//============================================================================
+int CDockAreaWidget::index(CDockWidget* DockWidget)
+{
+ return d->ContentsLayout->indexOf(DockWidget);
+}
+
+
+//============================================================================
+QList<CDockWidget*> CDockAreaWidget::dockWidgets() const
+{
+ QList<CDockWidget*> DockWidgetList;
+ for (int i = 0; i < d->ContentsLayout->count(); ++i)
+ {
+ DockWidgetList.append(dockWidget(i));
+ }
+ return DockWidgetList;
+}
+
+
+//============================================================================
+int CDockAreaWidget::openDockWidgetsCount() const
+{
+ int Count = 0;
+ for (int i = 0; i < d->ContentsLayout->count(); ++i)
+ {
+ if (dockWidget(i) && !dockWidget(i)->isClosed())
+ {
+ ++Count;
+ }
+ }
+ return Count;
+}
+
+
+//============================================================================
+QList<CDockWidget*> CDockAreaWidget::openedDockWidgets() const
+{
+ QList<CDockWidget*> DockWidgetList;
+ for (int i = 0; i < d->ContentsLayout->count(); ++i)
+ {
+ CDockWidget* DockWidget = dockWidget(i);
+ if (DockWidget && !DockWidget->isClosed())
+ {
+ DockWidgetList.append(dockWidget(i));
+ }
+ }
+ return DockWidgetList;
+}
+
+
+//============================================================================
+int CDockAreaWidget::indexOfFirstOpenDockWidget() const
+{
+ for (int i = 0; i < d->ContentsLayout->count(); ++i)
+ {
+ if (dockWidget(i) && !dockWidget(i)->isClosed())
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+//============================================================================
+int CDockAreaWidget::dockWidgetsCount() const
+{
+ return d->ContentsLayout->count();
+}
+
+
+//============================================================================
+CDockWidget* CDockAreaWidget::dockWidget(int Index) const
+{
+ return qobject_cast<CDockWidget*>(d->ContentsLayout->widget(Index));
+}
+
+//============================================================================
+void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex)
+{
+ ADS_PRINT("CDockAreaWidget::reorderDockWidget");
+ if (fromIndex >= d->ContentsLayout->count() || fromIndex < 0
+ || toIndex >= d->ContentsLayout->count() || toIndex < 0 || fromIndex == toIndex)
+ {
+ ADS_PRINT("Invalid index for tab movement" << fromIndex << toIndex);
+ return;
+ }
+
+ auto Widget = d->ContentsLayout->widget(fromIndex);
+ d->ContentsLayout->removeWidget(Widget);
+ d->ContentsLayout->insertWidget(toIndex, Widget);
+ setCurrentIndex(toIndex);
+}
+
+
+//============================================================================
+void CDockAreaWidget::toggleDockWidgetView(CDockWidget* DockWidget, bool Open)
+{
+ Q_UNUSED(DockWidget);
+ Q_UNUSED(Open);
+ updateTitleBarVisibility();
+}
+
+
+//============================================================================
+void CDockAreaWidget::updateTitleBarVisibility()
+{
+ CDockContainerWidget* Container = dockContainer();
+ if (!Container)
+ {
+ return;
+ }
+
+ if (!d->TitleBar)
+ {
+ return;
+ }
+
+ bool IsAutoHide = isAutoHide();
+ if (!CDockManager::testConfigFlag(CDockManager::AlwaysShowTabs))
+ {
+ bool Hidden = false;
+ // Wayland: the title bar of a floating container must always stay
+ // visible because it is the only handle that can drag the dock
+ // widget back into a dock container. The window decoration is owned
+ // by the compositor and only moves the window
+ bool IsWaylandFloating = internal::isWayland() && Container->isFloating();
+ if (!IsAutoHide && !IsWaylandFloating) // Titlebar must always be visible when auto hidden so it can be dragged
+ {
+ if (Container->isFloating() || CDockManager::testConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar))
+ {
+ // Always show title bar if it contains title bar actions
+ if (CDockWidget* TopLevelWidget = Container->topLevelDockWidget())
+ {
+ Hidden |= TopLevelWidget->titleBarActions().empty();
+ }
+ else if (CDockManager::testConfigFlag(CDockManager::TabsAtBottom))
+ {
+ Hidden = true;
+
+ for (CDockWidget* DockWidget : Container->openedDockWidgets())
+ {
+ if (!DockWidget->titleBarActions().empty())
+ {
+ Hidden = false;
+ break;
+ }
+ }
+ }
+ }
+ if (!Hidden && d->Flags.testFlag(HideSingleWidgetTitleBar))
+ {
+ // Always show title bar if it contains title bar actions
+ auto DockWidgets = openedDockWidgets();
+ Hidden |= (DockWidgets.size() == 1) && DockWidgets.front()->titleBarActions().empty();
+ }
+ }
+ d->TitleBar->setVisible(!Hidden);
+ if (CDockManager::testConfigFlag(CDockManager::TabsAtBottom))
+ d->TitleBar->tabBar()->setVisible(openDockWidgetsCount() > 1);
+ }
+
+ if (isAutoHideFeatureEnabled())
+ {
+ d->TitleBar->showAutoHideControls(IsAutoHide);
+ updateTitleBarButtonVisibility(Container->topLevelDockArea() == this);
+ }
+}
+
+
+//============================================================================
+void CDockAreaWidget::updateWindowTitle()
+{
+ auto currentWidget = d->ContentsLayout->currentWidget();
+ if (d->TitleBar && currentWidget)
+ {
+ d->TitleBar->autoHideTitleLabel()->setText(currentWidget->windowTitle());
+ }
+
+ markTitleBarMenuOutdated();
+}
+
+
+//============================================================================
+void CDockAreaWidget::markTitleBarMenuOutdated()
+{
+ if (d->TitleBar)
+ {
+ d->TitleBar->markTabsMenuOutdated();
+ }
+}
+
+
+//============================================================================
+void CDockAreaWidget::updateAutoHideButtonCheckState()
+{
+ auto autoHideButton = titleBarButton(TitleBarButtonAutoHide);
+ autoHideButton->blockSignals(true);
+ autoHideButton->setChecked(isAutoHide());
+ autoHideButton->blockSignals(false);
+}
+
+
+//============================================================================
+void CDockAreaWidget::updateTitleBarButtonVisibility(bool IsTopLevel) const
+{
+ d->updateTitleBarButtonVisibility(IsTopLevel);
+}
+
+
+//============================================================================
+void CDockAreaWidget::updateTitleBarButtonsToolTips()
+{
+ internal::setToolTip(titleBarButton(TitleBarButtonClose),
+ titleBar()->titleBarButtonToolTip(TitleBarButtonClose));
+ internal::setToolTip(titleBarButton(TitleBarButtonAutoHide),
+ titleBar()->titleBarButtonToolTip(TitleBarButtonAutoHide));
+}
+
+
+//============================================================================
+void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
+{
+ s.writeStartElement("Area");
+ s.writeAttribute("Tabs", QString::number(d->ContentsLayout->count()));
+ auto CurrentDockWidget = currentDockWidget();
+ QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : "";
+ s.writeAttribute("Current", Name);
+
+ if (d->AllowedAreas != DefaultAllowedAreas)
+ {
+ s.writeAttribute("AllowedAreas", QString::number(d->AllowedAreas, 16));
+ }
+
+ if (d->Flags != DefaultFlags)
+ {
+ s.writeAttribute("Flags", QString::number(d->Flags, 16));
+ }
+ ADS_PRINT("CDockAreaWidget::saveState TabCount: " << d->ContentsLayout->count()
+ << " Current: " << Name);
+ for (int i = 0; i < d->ContentsLayout->count(); ++i)
+ {
+ dockWidget(i)->saveState(s);
+ }
+ s.writeEndElement();
+}
+
+
+//============================================================================
+bool CDockAreaWidget::restoreState(CDockingStateReader& s, CDockAreaWidget*& CreatedWidget,
+ bool Testing, CDockContainerWidget* Container)
+{
+ bool Ok;
+#ifdef ADS_DEBUG_PRINT
+ int Tabs = s.attributes().value("Tabs").toInt(&Ok);
+ if (!Ok)
+ {
+ return false;
+ }
+#endif
+
+ QString CurrentDockWidget = s.attributes().value("Current").toString();
+ ADS_PRINT("Restore NodeDockArea Tabs: " << Tabs << " Current: "
+ << CurrentDockWidget);
+
+ auto DockManager = Container->dockManager();
+ CDockAreaWidget* DockArea = nullptr;
+ if (!Testing)
+ {
+ DockArea = new CDockAreaWidget(DockManager, Container);
+ const auto AllowedAreasAttribute = s.attributes().value("AllowedAreas");
+ if (!AllowedAreasAttribute.isEmpty())
+ {
+ DockArea->setAllowedAreas((DockWidgetArea)AllowedAreasAttribute.toInt(nullptr, 16));
+ }
+
+ const auto FlagsAttribute = s.attributes().value("Flags");
+ if (!FlagsAttribute.isEmpty())
+ {
+ DockArea->setDockAreaFlags((CDockAreaWidget::DockAreaFlags)FlagsAttribute.toInt(nullptr, 16));
+ }
+ }
+
+ while (s.readNextStartElement())
+ {
+ if (s.name() != QLatin1String("Widget"))
+ {
+ continue;
+ }
+
+ auto ObjectName = s.attributes().value("Name");
+ if (ObjectName.isEmpty())
+ {
+ return false;
+ }
+
+ bool Closed = s.attributes().value("Closed").toInt(&Ok);
+ if (!Ok)
+ {
+ return false;
+ }
+
+ s.skipCurrentElement();
+ CDockWidget* DockWidget = DockManager->findDockWidget(ObjectName.toString());
+ if (!DockWidget || Testing)
+ {
+ continue;
+ }
+
+ ADS_PRINT("Dock Widget found - parent " << DockWidget->parent());
+ if (DockWidget->autoHideDockContainer())
+ {
+ DockWidget->autoHideDockContainer()->cleanupAndDelete();
+ }
+
+ // We hide the DockArea here to prevent the short display (the flashing)
+ // of the dock areas during application startup
+ DockArea->hide();
+ DockArea->addDockWidget(DockWidget);
+ DockWidget->setToggleViewActionChecked(!Closed);
+ DockWidget->setClosedState(Closed);
+ DockWidget->setProperty(internal::ClosedProperty, Closed);
+ DockWidget->setProperty(internal::DirtyProperty, false);
+ }
+
+ if (Testing)
+ {
+ return true;
+ }
+
+ if (!DockArea->dockWidgetsCount())
+ {
+ delete DockArea;
+ DockArea = nullptr;
+ }
+ else
+ {
+ DockArea->setProperty("currentDockWidget", CurrentDockWidget);
+ }
+
+ CreatedWidget = DockArea;
+ return true;
+}
+
+
+//============================================================================
+CDockWidget* CDockAreaWidget::nextOpenDockWidget(CDockWidget* DockWidget) const
+{
+ auto OpenDockWidgets = openedDockWidgets();
+ if (OpenDockWidgets.count() > 1 || (OpenDockWidgets.count() == 1 && OpenDockWidgets[0] != DockWidget))
+ {
+ if (OpenDockWidgets.last() == DockWidget)
+ {
+ CDockWidget* NextDockWidget = OpenDockWidgets[OpenDockWidgets.count() - 2];
+ // search backwards for widget with tab
+ for (int i = OpenDockWidgets.count() - 2; i >= 0; --i)
+ {
+ auto dw = OpenDockWidgets[i];
+ if (!dw->features().testFlag(CDockWidget::NoTab))
+ {
+ return dw;
+ }
+ }
+
+ // return widget without tab
+ return NextDockWidget;
+ }
+ else
+ {
+ int IndexOfDockWidget = OpenDockWidgets.indexOf(DockWidget);
+ CDockWidget* NextDockWidget = OpenDockWidgets[IndexOfDockWidget + 1];
+ // search forwards for widget with tab
+ for (int i = IndexOfDockWidget + 1; i < OpenDockWidgets.count(); ++i)
+ {
+ auto dw = OpenDockWidgets[i];
+ if (!dw->features().testFlag(CDockWidget::NoTab))
+ {
+ return dw;
+ }
+ }
+
+ // search backwards for widget with tab
+ for (int i = IndexOfDockWidget - 1; i >= 0; --i)
+ {
+ auto dw = OpenDockWidgets[i];
+ if (!dw->features().testFlag(CDockWidget::NoTab))
+ {
+ return dw;
+ }
+ }
+
+ // return widget without tab
+ return NextDockWidget;
+ }
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+
+//============================================================================
+CDockWidget::DockWidgetFeatures CDockAreaWidget::features(eBitwiseOperator Mode) const
+{
+ if (BitwiseAnd == Mode)
+ {
+ CDockWidget::DockWidgetFeatures Features(CDockWidget::AllDockWidgetFeatures);
+ for (const auto DockWidget : dockWidgets())
+ {
+ Features &= DockWidget->features();
+ }
+ return Features;
+ }
+ else
+ {
+ CDockWidget::DockWidgetFeatures Features(CDockWidget::NoDockWidgetFeatures);
+ for (const auto DockWidget : dockWidgets())
+ {
+ Features |= DockWidget->features();
+ }
+ return Features;
+ }
+}
+
+
+//============================================================================
+void CDockAreaWidget::toggleView(bool Open)
+{
+ setVisible(Open);
+
+ Q_EMIT viewToggled(Open);
+}
+
+
+//============================================================================
+void CDockAreaWidget::setVisible(bool Visible)
+{
+ Super::setVisible(Visible);
+ if (d->UpdateTitleBarButtons)
+ {
+ d->updateTitleBarButtonStates();
+ }
+}
+
+
+//============================================================================
+void CDockAreaWidget::setAllowedAreas(DockWidgetAreas areas)
+{
+ d->AllowedAreas = areas;
+}
+
+
+//============================================================================
+DockWidgetAreas CDockAreaWidget::allowedAreas() const
+{
+ return d->AllowedAreas;
+}
+
+
+//============================================================================
+CDockAreaWidget::DockAreaFlags CDockAreaWidget::dockAreaFlags() const
+{
+ return d->Flags;
+}
+
+
+//============================================================================
+void CDockAreaWidget::setDockAreaFlags(DockAreaFlags Flags)
+{
+ auto ChangedFlags = d->Flags ^ Flags;
+ d->Flags = Flags;
+ if (ChangedFlags.testFlag(HideSingleWidgetTitleBar))
+ {
+ updateTitleBarVisibility();
+ }
+}
+
+
+//============================================================================
+void CDockAreaWidget::setDockAreaFlag(eDockAreaFlag Flag, bool On)
+{
+ auto flags = dockAreaFlags();
+ internal::setFlag(flags, Flag, On);
+ setDockAreaFlags(flags);
+}
+
+
+//============================================================================
+QAbstractButton* CDockAreaWidget::titleBarButton(TitleBarButton which) const
+{
+ return d->TitleBar->button(which);
+}
+
+
+//============================================================================
+void CDockAreaWidget::closeArea()
+{
+ // If there is only one single dock widget and this widget has the
+ // DeleteOnClose feature or CustomCloseHandling, then we delete the dock widget now;
+ // in the case of CustomCloseHandling, the CDockWidget class will emit its
+ // closeRequested signal and not actually delete unless the signal is handled in a way that deletes it
+ auto OpenDockWidgets = openedDockWidgets();
+ if (OpenDockWidgets.count() == 1 &&
+ (OpenDockWidgets[0]->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) || OpenDockWidgets[0]->features().testFlag(CDockWidget::CustomCloseHandling))
+ && !isAutoHide())
+ {
+ OpenDockWidgets[0]->closeDockWidgetInternal();
+ }
+ else
+ {
+ for (auto DockWidget : openedDockWidgets())
+ {
+ if ((DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) && DockWidget->features().testFlag(CDockWidget::DockWidgetForceCloseWithArea)) ||
+ DockWidget->features().testFlag(CDockWidget::CustomCloseHandling))
+ {
+ DockWidget->closeDockWidgetInternal();
+ }
+ else if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) && isAutoHide())
+ {
+ DockWidget->closeDockWidgetInternal();
+ }
+ else
+ {
+ DockWidget->toggleView(false);
+ }
+ }
+ }
+}
+
+
+enum eBorderLocation
+{
+ BorderNone = 0,
+ BorderLeft = 0x01,
+ BorderRight = 0x02,
+ BorderTop = 0x04,
+ BorderBottom = 0x08,
+ BorderVertical = BorderLeft | BorderRight,
+ BorderHorizontal = BorderTop | BorderBottom,
+ BorderTopLeft = BorderTop | BorderLeft,
+ BorderTopRight = BorderTop | BorderRight,
+ BorderBottomLeft = BorderBottom | BorderLeft,
+ BorderBottomRight = BorderBottom | BorderRight,
+ BorderVerticalBottom = BorderVertical | BorderBottom,
+ BorderVerticalTop = BorderVertical | BorderTop,
+ BorderHorizontalLeft = BorderHorizontal | BorderLeft,
+ BorderHorizontalRight = BorderHorizontal | BorderRight,
+ BorderAll = BorderVertical | BorderHorizontal
+};
+
+
+//============================================================================
+SideBarLocation CDockAreaWidget::calculateSideTabBarArea() const
+{
+ auto Container = dockContainer();
+ auto ContentRect = Container->contentRect();
+
+ int borders = BorderNone; // contains all borders that are touched by the dock ware
+ auto DockAreaTopLeft = mapTo(Container, rect().topLeft());
+ auto DockAreaRect = rect();
+ DockAreaRect.moveTo(DockAreaTopLeft);
+ const qreal aspectRatio = DockAreaRect.width() / (qMax(1, DockAreaRect.height()) * 1.0);
+ const qreal sizeRatio = (qreal)ContentRect.width() / DockAreaRect.width();
+ static const int MinBorderDistance = 16;
+ bool HorizontalOrientation = (aspectRatio > 1.0) && (sizeRatio < 3.0);
+
+ // measure border distances - a distance less than 16 px means we touch the
+ // border
+ int BorderDistance[4];
+
+ int Distance = qAbs(ContentRect.topLeft().y() - DockAreaRect.topLeft().y());
+ BorderDistance[SideBarLocation::SideBarTop] = (Distance < MinBorderDistance) ? 0 : Distance;
+ if (!BorderDistance[SideBarLocation::SideBarTop])
+ {
+ borders |= BorderTop;
+ }
+
+ Distance = qAbs(ContentRect.bottomRight().y() - DockAreaRect.bottomRight().y());
+ BorderDistance[SideBarLocation::SideBarBottom] = (Distance < MinBorderDistance) ? 0 : Distance;
+ if (!BorderDistance[SideBarLocation::SideBarBottom])
+ {
+ borders |= BorderBottom;
+ }
+
+ Distance = qAbs(ContentRect.topLeft().x() - DockAreaRect.topLeft().x());
+ BorderDistance[SideBarLocation::SideBarLeft] = (Distance < MinBorderDistance) ? 0 : Distance;
+ if (!BorderDistance[SideBarLocation::SideBarLeft])
+ {
+ borders |= BorderLeft;
+ }
+
+ Distance = qAbs(ContentRect.bottomRight().x() - DockAreaRect.bottomRight().x());
+ BorderDistance[SideBarLocation::SideBarRight] = (Distance < MinBorderDistance) ? 0 : Distance;
+ if (!BorderDistance[SideBarLocation::SideBarRight])
+ {
+ borders |= BorderRight;
+ }
+
+ auto SideTab = SideBarLocation::SideBarRight;
+ switch (borders)
+ {
+ // 1. It's touching all borders
+ case BorderAll: SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarRight; break;
+
+ // 2. It's touching 3 borders
+ case BorderVerticalBottom : SideTab = SideBarLocation::SideBarBottom; break;
+ case BorderVerticalTop : SideTab = SideBarLocation::SideBarTop; break;
+ case BorderHorizontalLeft: SideTab = SideBarLocation::SideBarLeft; break;
+ case BorderHorizontalRight: SideTab = SideBarLocation::SideBarRight; break;
+
+ // 3. It's touching horizontal or vertical borders
+ case BorderVertical : SideTab = SideBarLocation::SideBarBottom; break;
+ case BorderHorizontal: SideTab = SideBarLocation::SideBarRight; break;
+
+ // 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. It's touching only one border
+ case BorderLeft: SideTab = SideBarLocation::SideBarLeft; break;
+ case BorderRight: SideTab = SideBarLocation::SideBarRight; break;
+ case BorderTop: SideTab = SideBarLocation::SideBarTop; break;
+ case BorderBottom: SideTab = SideBarLocation::SideBarBottom; break;
+ }
+
+ return SideTab;
+}
+
+
+//============================================================================
+void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location, int TabIndex)
+{
+ if (!isAutoHideFeatureEnabled())
+ {
+ return;
+ }
+
+ if (!Enable)
+ {
+ if (isAutoHide())
+ {
+ 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())
+ {
+ if (Enable == isAutoHide())
+ {
+ continue;
+ }
+
+ if (!DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable))
+ {
+ continue;
+ }
+
+ dockContainer()->createAndSetupAutoHideContainer(area, DockWidget, TabIndex++);
+ }
+}
+
+
+//============================================================================
+void CDockAreaWidget::toggleAutoHide(SideBarLocation Location)
+{
+ if (!isAutoHideFeatureEnabled())
+ {
+ return;
+ }
+
+ setAutoHide(!isAutoHide(), Location);
+}
+
+
+//============================================================================
+void CDockAreaWidget::closeOtherAreas()
+{
+ dockContainer()->closeOtherAreas(this);
+}
+
+
+//============================================================================
+CDockAreaTitleBar* CDockAreaWidget::titleBar() const
+{
+ return d->TitleBar;
+}
+
+
+//============================================================================
+bool CDockAreaWidget::isCentralWidgetArea() const
+{
+ if (dockWidgetsCount()!= 1)
+ {
+ return false;
+ }
+
+ return dockManager()->centralWidget() == dockWidgets().constFirst();
+}
+
+
+//============================================================================
+bool CDockAreaWidget::containsCentralWidget() const
+{
+ auto centralWidget = dockManager()->centralWidget();
+ for (const auto &dockWidget : dockWidgets())
+ {
+ if (dockWidget == centralWidget)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+//============================================================================
+QSize CDockAreaWidget::minimumSizeHint() const
+{
+ if (!d->MinSizeHint.isValid())
+ {
+ return Super::minimumSizeHint();
+ }
+
+ int extraHeight = 0;
+ if (d->TitleBar->isVisible())
+ {
+ extraHeight += d->TitleBar->minimumSizeHint().height();
+ }
+
+ if (CDockManager::testConfigFlag(CDockManager::TabsAtBottom) && d->tabBar()->isVisible())
+ {
+ extraHeight += d->tabBar()->minimumSizeHint().height();
+ }
+
+ return d->MinSizeHint + QSize(0, extraHeight);
+}
+
+
+//============================================================================
+void CDockAreaWidget::onDockWidgetFeaturesChanged()
+{
+ if (d->TitleBar)
+ {
+ d->updateTitleBarButtonStates();
+ }
+}
+
+
+//============================================================================
+bool CDockAreaWidget::isTopLevelArea() const
+{
+ auto Container = dockContainer();
+ if (!Container)
+ {
+ return false;
+ }
+
+ return (Container->topLevelDockArea() == this);
+}
+
+
+//============================================================================
+void CDockAreaWidget::setFloating()
+{
+ d->TitleBar->setAreaFloating();
+}
+
+
+#ifdef Q_OS_WIN
+//============================================================================
+bool CDockAreaWidget::event(QEvent *e)
+{
+ switch (e->type())
+ {
+ case QEvent::PlatformSurface: return true;
+ default:
+ break;
+ }
+
+ return Super::event(e);
+}
+#endif
+
+} // namespace ads
+
+//---------------------------------------------------------------------------
+// EOF DockAreaWidget.cpp
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.h b/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.h
index 0eac0607f..8fea878fb 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockAreaWidget.h
@@ -1,458 +1,464 @@
-#ifndef DockAreaWidgetH
-#define DockAreaWidgetH
-/*******************************************************************************
-** Qt Advanced Docking System
-** Copyright (C) 2017 Uwe Kindler
-**
-** This library is free software; you can redistribute it and/or
-** modify it under the terms of the GNU Lesser General Public
-** License as published by the Free Software Foundation; either
-** version 2.1 of the License, or (at your option) any later version.
-**
-** This library is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-** Lesser General Public License for more details.
-**
-** You should have received a copy of the GNU Lesser General Public
-** License along with this library; If not, see <http://www.gnu.org/licenses/>.
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockAreaWidget.h
-/// \author Uwe Kindler
-/// \date 24.02.2017
-/// \brief Declaration of CDockAreaWidget class
-//============================================================================
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include <QFrame>
-
-#include "ads_globals.h"
-#include "AutoHideTab.h"
-#include "DockWidget.h"
-
-QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
-QT_FORWARD_DECLARE_CLASS(QAbstractButton)
-
-namespace ads
-{
-struct DockAreaWidgetPrivate;
-class CDockManager;
-class CDockContainerWidget;
-class DockContainerWidgetPrivate;
-class CDockAreaTitleBar;
-class CDockingStateReader;
-class CDockSplitter;
-
-
-/**
- * DockAreaWidget manages multiple instances of DockWidgets.
- * It displays a title tab, which is clickable and will switch to
- * the contents associated to the title when clicked.
- */
-class ADS_EXPORT CDockAreaWidget : public QFrame
-{
- Q_OBJECT
-private:
- DockAreaWidgetPrivate* d; ///< private data (pimpl)
- friend struct DockAreaWidgetPrivate;
- friend class CDockContainerWidget;
- friend class DockContainerWidgetPrivate;
- friend class CDockWidgetTab;
- friend struct DockWidgetPrivate;
- friend class CDockWidget;
- friend struct DockManagerPrivate;
- friend class CDockManager;
- friend class CAutoHideDockContainer;
- void onDockWidgetFeaturesChanged();
-
-private Q_SLOTS:
- void onTabCloseRequested(int Index);
-
- /**
- * Reorder the index position of DockWidget at fromIndx to toIndex
- * if a tab in the tabbar is dragged from one index to another one
- */
- void reorderDockWidget(int fromIndex, int toIndex);
-
- /*
- * Update the auto hide button checked state based on if it's contained in an auto hide container or not
- */
- void updateAutoHideButtonCheckState();
-
- /*
- * Update the title bar button tooltips
- */
- void updateTitleBarButtonsToolTips();
-
- /**
- * Calculate the auto hide side bar location depending on the dock area
- * widget position in the container
- */
- SideBarLocation calculateSideTabBarArea() const;
-
-protected:
-
-#ifdef Q_OS_WIN
- /**
- * Reimplements QWidget::event to handle QEvent::PlatformSurface
- * This is here to fix issue #294 Tab refresh problem with a QGLWidget
- * that exists since Qt version 5.12.7. So this function is here to
- * work around a Qt issue.
- */
- virtual bool event(QEvent *event) override;
-#endif
-
- /**
- * Inserts a dock widget into dock area.
- * All dockwidgets in the dock area tabified in a stacked layout with tabs.
- * The index indicates the index of the new dockwidget in the tabbar and
- * in the stacked layout. If the Activate parameter is true, the new
- * DockWidget will be the active one in the stacked layout
- */
- void insertDockWidget(int index, CDockWidget* DockWidget, bool Activate = true);
-
- /**
- * Add a new dock widget to dock area.
- * All dockwidgets in the dock area tabified in a stacked layout with tabs
- */
- void addDockWidget(CDockWidget* DockWidget);
-
- /**
- * Removes the given dock widget from the dock area
- */
- void removeDockWidget(CDockWidget* DockWidget);
-
- /**
- * Called from dock widget if it is opened or closed
- */
- void toggleDockWidgetView(CDockWidget* DockWidget, bool Open);
-
- /**
- * This is a helper function to get the next open dock widget to activate
- * if the given DockWidget will be closed or removed.
- * The function returns the next widget that should be activated or
- * nullptr in case there are no more open widgets in this area.
- */
- CDockWidget* nextOpenDockWidget(CDockWidget* DockWidget) const;
-
- /**
- * Returns the index of the given DockWidget in the internal layout
- */
- int index(CDockWidget* DockWidget);
-
- /**
- * Call this function, if you already know, that the dock does not
- * contain any visible content (any open dock widgets).
- */
- void hideAreaWithNoVisibleContent();
-
- /**
- * Updates the dock area layout and components visibility
- */
- void updateTitleBarVisibility();
-
- /**
- * This is the internal private function for setting the current widget.
- * This function is called by the public setCurrentDockWidget() function
- * and by the dock manager when restoring the state
- */
- void internalSetCurrentDockWidget(CDockWidget* DockWidget);
-
- /**
- * Marks tabs menu to update
- */
- void markTitleBarMenuOutdated();
-
- /*
- * Update the title bar button visibility based on if it's top level or not
- */
- void updateTitleBarButtonVisibility(bool IsTopLevel) const;
-
-protected Q_SLOTS:
- void toggleView(bool Open);
-
-public:
- using Super = QFrame;
-
- /**
- * Dock area related flags
- */
- enum eDockAreaFlag
- {
- HideSingleWidgetTitleBar = 0x0001,
- DefaultFlags = 0x0000
- };
- Q_DECLARE_FLAGS(DockAreaFlags, eDockAreaFlag)
-
- /**
- * Default Constructor
- */
- CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent);
-
- /**
- * Virtual Destructor
- */
- virtual ~CDockAreaWidget();
-
- /**
- * Returns the dock manager object this dock area belongs to
- */
- CDockManager* dockManager() const;
-
- /**
- * Returns the dock container widget this dock area widget belongs to or 0
- * if there is no
- */
- CDockContainerWidget* dockContainer() const;
-
- /**
- * Returns the auto hide dock container widget this dock area widget belongs to or 0
- * if there is no
- */
- CAutoHideDockContainer* autoHideDockContainer() const;
-
- /**
- * Returns the parent splitter that contains this dock area
- */
- CDockSplitter* parentSplitter() const;
-
- /**
- * Returns true if the dock area is in an auto hide container
- */
- bool isAutoHide() const;
-
- /**
- * Sets the current auto hide dock container
- */
- void setAutoHideDockContainer(CAutoHideDockContainer* AutoHideDockContainer);
-
- /**
- * Returns the largest minimumSizeHint() of the dock widgets in this
- * area.
- * The minimum size hint is updated if a dock widget is removed or added.
- */
- virtual QSize minimumSizeHint() const override;
-
- /**
- * Returns the rectangle of the title area
- */
- QRect titleBarGeometry() const;
-
- /**
- * Returns the rectangle of the content
- */
- QRect contentAreaGeometry() const;
-
- /**
- * Returns the number of dock widgets in this area
- */
- int dockWidgetsCount() const;
-
- /**
- * Returns a list of all dock widgets in this dock area.
- * This list contains open and closed dock widgets.
- */
- QList<CDockWidget*> dockWidgets() const;
-
- /**
- * Returns the number of open dock widgets in this area
- */
- int openDockWidgetsCount() const;
-
- /**
- * Returns a list of dock widgets that are not closed.
- */
- QList<CDockWidget*> openedDockWidgets() const;
-
- /**
- * Returns a dock widget by its index
- */
- CDockWidget* dockWidget(int Index) const;
-
- /**
- * Returns the index of the current active dock widget or -1 if there
- * are is no active dock widget (ie.e if all dock widgets are closed)
- */
- int currentIndex() const;
-
- /**
- * Returns the index of the first open dock widgets in the list of
- * dock widgets.
- * This function is here for performance reasons. Normally it would
- * be possible to take the first dock widget from the list returned by
- * openedDockWidgets() function. But that function enumerates all
- * dock widgets while this functions stops after the first open dock widget.
- * If there are no open dock widgets, the function returns -1.
- */
- int indexOfFirstOpenDockWidget() const;
-
- /**
- * Returns the current active dock widget or a nullptr if there is no
- * active dock widget (i.e. if all dock widgets are closed)
- */
- CDockWidget* currentDockWidget() const;
-
- /**
- * Shows the tab with the given dock widget
- */
- void setCurrentDockWidget(CDockWidget* DockWidget);
-
- /**
- * Saves the state into the given stream
- */
- void saveState(QXmlStreamWriter& Stream) const;
-
- /**
- * Restores a dock area.
- * \see restoreChildNodes() for details
- */
- static bool restoreState(CDockingStateReader& Stream, CDockAreaWidget*& CreatedWidget,
- bool Testing, CDockContainerWidget* ParentContainer);
-
- /**
- * This functions returns the dock widget features of all dock widget in
- * this area.
- * A bitwise and is used to combine the flags of all dock widgets. That
- * means, if only one single dock widget does not support a certain flag,
- * the whole dock are does not support the flag. I.e. if one single
- * dock widget in this area is not closable, the whole dock are is not
- * closable.
- */
- CDockWidget::DockWidgetFeatures features(eBitwiseOperator Mode = BitwiseAnd) const;
-
- /**
- * Returns the title bar button corresponding to the given title bar
- * button identifier
- */
- QAbstractButton* titleBarButton(TitleBarButton which) const;
-
- /**
- * Update the close button if visibility changed
- */
- virtual void setVisible(bool Visible) override;
-
- /**
- * Configures the areas of this particular dock area that are allowed for docking
- */
- void setAllowedAreas(DockWidgetAreas areas);
-
- /**
- * Returns flags with all allowed drop areas of this particular dock area
- */
- DockWidgetAreas allowedAreas() const;
-
- /**
- * Returns the title bar of this dock area
- */
- CDockAreaTitleBar* titleBar() const;
-
- /**
- * Returns the dock area flags - a combination of flags that configure the
- * appearance and features of the dock area.
- * \see setDockAreaFlasg()
- */
- DockAreaFlags dockAreaFlags() const;
-
- /**
- * Sets the dock area flags - a combination of flags that configure the
- * appearance and features of the dock area
- */
- void setDockAreaFlags(DockAreaFlags Flags);
-
- /**
- * Sets the dock area flag Flag on this widget if on is true; otherwise
- * clears the flag.
- */
- void setDockAreaFlag(eDockAreaFlag Flag, bool On);
-
- /**
- * Returns true if the area has a single dock widget and contains the central widget of it's manager.
- */
- bool isCentralWidgetArea() const;
-
- /**
- * Returns true if the area contains the central widget of it's manager.
- */
- bool containsCentralWidget() const;
-
- /**
- * If this dock area is the one and only visible area in a container, then
- * this function returns true
- */
- bool isTopLevelArea() const;
-
-
-public Q_SLOTS:
- /**
- * This activates the tab for the given tab index.
- * If the dock widget for the given tab is not visible, the this function
- * call will make it visible.
- */
- void setCurrentIndex(int index);
-
- /**
- * Closes the dock area and all dock widgets in this area
- */
- void closeArea();
-
- /**
- * Sets the dock area into auto hide mode or into normal mode.
- * If the dock area is switched to auto hide mode, then all dock widgets
- * that are pinable will be added to the sidebar
- */
- void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone, int TabIndex = -1);
-
- /**
- * Switches the dock area to auto hide mode or vice versa depending on its
- * current state.
- */
- void toggleAutoHide(SideBarLocation Location = SideBarNone);
-
- /**
- * This function closes all other areas except of this area
- */
- void closeOtherAreas();
-
- /**
- * 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.
- */
- void tabBarClicked(int index);
-
- /**
- * This signal is emitted when the tab bar's current tab is about to be changed. The new
- * current has the given index, or -1 if there isn't a new one.
- * @param index
- */
- void currentChanging(int index);
-
- /**
- * This signal is emitted when the tab bar's current tab changes. The new
- * current has the given index, or -1 if there isn't a new one
- * @param index
- */
- void currentChanged(int index);
-
- /**
- * This signal is emitted if the visibility of this dock area is toggled
- * via toggle view function
- */
- void viewToggled(bool Open);
-}; // class DockAreaWidget
-} // namespace ads
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(ads::CDockAreaWidget::DockAreaFlags)
-//-----------------------------------------------------------------------------
-#endif // DockAreaWidgetH
+#ifndef DockAreaWidgetH
+#define DockAreaWidgetH
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockAreaWidget.h
+/// \author Uwe Kindler
+/// \date 24.02.2017
+/// \brief Declaration of CDockAreaWidget class
+//============================================================================
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include <QFrame>
+
+#include "ads_globals.h"
+#include "AutoHideTab.h"
+#include "DockWidget.h"
+
+QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
+QT_FORWARD_DECLARE_CLASS(QAbstractButton)
+QT_FORWARD_DECLARE_CLASS(QMenu)
+
+namespace ads
+{
+struct DockAreaWidgetPrivate;
+class CDockManager;
+class CDockContainerWidget;
+class DockContainerWidgetPrivate;
+class CDockAreaTitleBar;
+class CDockingStateReader;
+class CDockSplitter;
+
+
+/**
+ * DockAreaWidget manages multiple instances of DockWidgets.
+ * It displays a title tab, which is clickable and will switch to
+ * the contents associated to the title when clicked.
+ */
+class ADS_EXPORT CDockAreaWidget : public QFrame
+{
+ Q_OBJECT
+private:
+ DockAreaWidgetPrivate* d; ///< private data (pimpl)
+ friend struct DockAreaWidgetPrivate;
+ friend class CDockContainerWidget;
+ friend class DockContainerWidgetPrivate;
+ friend class CDockWidgetTab;
+ friend struct DockWidgetPrivate;
+ friend class CDockWidget;
+ friend struct DockManagerPrivate;
+ friend class CDockManager;
+ friend class CAutoHideDockContainer;
+ void onDockWidgetFeaturesChanged();
+
+private Q_SLOTS:
+ void onTabCloseRequested(int Index);
+
+ /**
+ * Reorder the index position of DockWidget at fromIndx to toIndex
+ * if a tab in the tabbar is dragged from one index to another one
+ */
+ void reorderDockWidget(int fromIndex, int toIndex);
+
+ /*
+ * Update the auto hide button checked state based on if it's contained in an auto hide container or not
+ */
+ void updateAutoHideButtonCheckState();
+
+ /*
+ * Update the title bar button tooltips
+ */
+ void updateTitleBarButtonsToolTips();
+
+ /**
+ * Calculate the auto hide side bar location depending on the dock area
+ * widget position in the container
+ */
+ SideBarLocation calculateSideTabBarArea() const;
+
+protected:
+
+#ifdef Q_OS_WIN
+ /**
+ * Reimplements QWidget::event to handle QEvent::PlatformSurface
+ * This is here to fix issue #294 Tab refresh problem with a QGLWidget
+ * that exists since Qt version 5.12.7. So this function is here to
+ * work around a Qt issue.
+ */
+ virtual bool event(QEvent *event) override;
+#endif
+
+ /**
+ * Inserts a dock widget into dock area.
+ * All dockwidgets in the dock area tabified in a stacked layout with tabs.
+ * The index indicates the index of the new dockwidget in the tabbar and
+ * in the stacked layout. If the Activate parameter is true, the new
+ * DockWidget will be the active one in the stacked layout
+ */
+ void insertDockWidget(int index, CDockWidget* DockWidget, bool Activate = true);
+
+ /**
+ * Add a new dock widget to dock area.
+ * All dockwidgets in the dock area tabified in a stacked layout with tabs
+ */
+ void addDockWidget(CDockWidget* DockWidget);
+
+ /**
+ * Removes the given dock widget from the dock area
+ */
+ void removeDockWidget(CDockWidget* DockWidget);
+
+ /**
+ * Called from dock widget if it is opened or closed
+ */
+ void toggleDockWidgetView(CDockWidget* DockWidget, bool Open);
+
+ /**
+ * This is a helper function to get the next open dock widget to activate
+ * if the given DockWidget will be closed or removed.
+ * The function returns the next widget that should be activated or
+ * nullptr in case there are no more open widgets in this area.
+ */
+ CDockWidget* nextOpenDockWidget(CDockWidget* DockWidget) const;
+
+ /**
+ * Returns the index of the given DockWidget in the internal layout
+ */
+ int index(CDockWidget* DockWidget);
+
+ /**
+ * Call this function, if you already know, that the dock does not
+ * contain any visible content (any open dock widgets).
+ */
+ void hideAreaWithNoVisibleContent();
+
+ /**
+ * Updates the dock area layout and components visibility
+ */
+ void updateTitleBarVisibility();
+
+ /**
+ * This is the internal private function for setting the current widget.
+ * This function is called by the public setCurrentDockWidget() function
+ * and by the dock manager when restoring the state
+ */
+ void internalSetCurrentDockWidget(CDockWidget* DockWidget);
+
+ /**
+ * Call this function to update the window title
+ */
+ void updateWindowTitle();
+
+ /**
+ * Marks tabs menu to update
+ */
+ void markTitleBarMenuOutdated();
+
+ /*
+ * Update the title bar button visibility based on if it's top level or not
+ */
+ void updateTitleBarButtonVisibility(bool IsTopLevel) const;
+
+protected Q_SLOTS:
+ void toggleView(bool Open);
+
+public:
+ using Super = QFrame;
+
+ /**
+ * Dock area related flags
+ */
+ enum eDockAreaFlag
+ {
+ HideSingleWidgetTitleBar = 0x0001,
+ DefaultFlags = 0x0000
+ };
+ Q_DECLARE_FLAGS(DockAreaFlags, eDockAreaFlag)
+
+ /**
+ * Default Constructor
+ */
+ CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent);
+
+ /**
+ * Virtual Destructor
+ */
+ ~CDockAreaWidget() override;
+
+ /**
+ * Returns the dock manager object this dock area belongs to
+ */
+ CDockManager* dockManager() const;
+
+ /**
+ * Returns the dock container widget this dock area widget belongs to or 0
+ * if there is no
+ */
+ CDockContainerWidget* dockContainer() const;
+
+ /**
+ * Returns the auto hide dock container widget this dock area widget belongs to or 0
+ * if there is no
+ */
+ CAutoHideDockContainer* autoHideDockContainer() const;
+
+ /**
+ * Returns the parent splitter that contains this dock area
+ */
+ CDockSplitter* parentSplitter() const;
+
+ /**
+ * Returns true if the dock area is in an auto hide container
+ */
+ bool isAutoHide() const;
+
+ /**
+ * Sets the current auto hide dock container
+ */
+ void setAutoHideDockContainer(CAutoHideDockContainer* AutoHideDockContainer);
+
+ /**
+ * Returns the largest minimumSizeHint() of the dock widgets in this
+ * area.
+ * The minimum size hint is updated if a dock widget is removed or added.
+ */
+ virtual QSize minimumSizeHint() const override;
+
+ /**
+ * Returns the rectangle of the title area
+ */
+ QRect titleBarGeometry() const;
+
+ /**
+ * Returns the rectangle of the content
+ */
+ QRect contentAreaGeometry() const;
+
+ /**
+ * Returns the number of dock widgets in this area
+ */
+ int dockWidgetsCount() const;
+
+ /**
+ * Returns a list of all dock widgets in this dock area.
+ * This list contains open and closed dock widgets.
+ */
+ QList<CDockWidget*> dockWidgets() const;
+
+ /**
+ * Returns the number of open dock widgets in this area
+ */
+ int openDockWidgetsCount() const;
+
+ /**
+ * Returns a list of dock widgets that are not closed.
+ */
+ QList<CDockWidget*> openedDockWidgets() const;
+
+ /**
+ * Returns a dock widget by its index
+ */
+ CDockWidget* dockWidget(int Index) const;
+
+ /**
+ * Returns the index of the current active dock widget or -1 if there
+ * are is no active dock widget (ie.e if all dock widgets are closed)
+ */
+ int currentIndex() const;
+
+ /**
+ * Returns the index of the first open dock widgets in the list of
+ * dock widgets.
+ * This function is here for performance reasons. Normally it would
+ * be possible to take the first dock widget from the list returned by
+ * openedDockWidgets() function. But that function enumerates all
+ * dock widgets while this functions stops after the first open dock widget.
+ * If there are no open dock widgets, the function returns -1.
+ */
+ int indexOfFirstOpenDockWidget() const;
+
+ /**
+ * Returns the current active dock widget or a nullptr if there is no
+ * active dock widget (i.e. if all dock widgets are closed)
+ */
+ CDockWidget* currentDockWidget() const;
+
+ /**
+ * Shows the tab with the given dock widget
+ */
+ void setCurrentDockWidget(CDockWidget* DockWidget);
+
+ /**
+ * Saves the state into the given stream
+ */
+ void saveState(QXmlStreamWriter& Stream) const;
+
+ /**
+ * Restores a dock area.
+ * \see restoreChildNodes() for details
+ */
+ static bool restoreState(CDockingStateReader& Stream, CDockAreaWidget*& CreatedWidget,
+ bool Testing, CDockContainerWidget* ParentContainer);
+
+ /**
+ * This functions returns the dock widget features of all dock widget in
+ * this area.
+ * A bitwise and is used to combine the flags of all dock widgets. That
+ * means, if only one single dock widget does not support a certain flag,
+ * the whole dock are does not support the flag. I.e. if one single
+ * dock widget in this area is not closable, the whole dock are is not
+ * closable.
+ */
+ CDockWidget::DockWidgetFeatures features(eBitwiseOperator Mode = BitwiseAnd) const;
+
+ /**
+ * Returns the title bar button corresponding to the given title bar
+ * button identifier
+ */
+ QAbstractButton* titleBarButton(TitleBarButton which) const;
+
+ /**
+ * Update the close button if visibility changed
+ */
+ virtual void setVisible(bool Visible) override;
+
+ /**
+ * Configures the areas of this particular dock area that are allowed for docking
+ */
+ void setAllowedAreas(DockWidgetAreas areas);
+
+ /**
+ * Returns flags with all allowed drop areas of this particular dock area
+ */
+ DockWidgetAreas allowedAreas() const;
+
+ /**
+ * Returns the title bar of this dock area
+ */
+ CDockAreaTitleBar* titleBar() const;
+
+ /**
+ * Returns the dock area flags - a combination of flags that configure the
+ * appearance and features of the dock area.
+ * \see setDockAreaFlasg()
+ */
+ DockAreaFlags dockAreaFlags() const;
+
+ /**
+ * Sets the dock area flags - a combination of flags that configure the
+ * appearance and features of the dock area
+ */
+ void setDockAreaFlags(DockAreaFlags Flags);
+
+ /**
+ * Sets the dock area flag Flag on this widget if on is true; otherwise
+ * clears the flag.
+ */
+ void setDockAreaFlag(eDockAreaFlag Flag, bool On);
+
+ /**
+ * Returns true if the area has a single dock widget and contains the central widget of it's manager.
+ */
+ bool isCentralWidgetArea() const;
+
+ /**
+ * Returns true if the area contains the central widget of it's manager.
+ */
+ bool containsCentralWidget() const;
+
+ /**
+ * If this dock area is the one and only visible area in a container, then
+ * this function returns true
+ */
+ bool isTopLevelArea() const;
+
+
+public Q_SLOTS:
+ /**
+ * This activates the tab for the given tab index.
+ * If the dock widget for the given tab is not visible, the this function
+ * call will make it visible.
+ */
+ void setCurrentIndex(int index);
+
+ /**
+ * Closes the dock area and all dock widgets in this area
+ */
+ void closeArea();
+
+ /**
+ * Sets the dock area into auto hide mode or into normal mode.
+ * If the dock area is switched to auto hide mode, then all dock widgets
+ * that are pinable will be added to the sidebar
+ */
+ void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone, int TabIndex = -1);
+
+ /**
+ * Switches the dock area to auto hide mode or vice versa depending on its
+ * current state.
+ */
+ void toggleAutoHide(SideBarLocation Location = SideBarNone);
+
+ /**
+ * This function closes all other areas except of this area
+ */
+ void closeOtherAreas();
+
+ /**
+ * 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.
+ */
+ void tabBarClicked(int index);
+
+ /**
+ * This signal is emitted when the tab bar's current tab is about to be changed. The new
+ * current has the given index, or -1 if there isn't a new one.
+ * @param index
+ */
+ void currentChanging(int index);
+
+ /**
+ * This signal is emitted when the tab bar's current tab changes. The new
+ * current has the given index, or -1 if there isn't a new one
+ * @param index
+ */
+ void currentChanged(int index);
+
+ /**
+ * This signal is emitted if the visibility of this dock area is toggled
+ * via toggle view function
+ */
+ void viewToggled(bool Open);
+}; // class DockAreaWidget
+} // namespace ads
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(ads::CDockAreaWidget::DockAreaFlags)
+//-----------------------------------------------------------------------------
+#endif // DockAreaWidgetH
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockComponentsFactory.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/DockComponentsFactory.cpp
index 05259d7b4..874bf111f 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockComponentsFactory.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockComponentsFactory.cpp
@@ -21,7 +21,8 @@
namespace ads
{
-static std::unique_ptr<CDockComponentsFactory> DefaultFactory(new CDockComponentsFactory());
+
+static QSharedPointer<ads::CDockComponentsFactory> DefaultFactory;
//============================================================================
@@ -52,9 +53,13 @@ CDockAreaTitleBar* CDockComponentsFactory::createDockAreaTitleBar(CDockAreaWidge
//============================================================================
-const CDockComponentsFactory* CDockComponentsFactory::factory()
+QSharedPointer<ads::CDockComponentsFactory> CDockComponentsFactory::factory()
{
- return DefaultFactory.get();
+ if (!DefaultFactory)
+ {
+ DefaultFactory.reset(new CDockComponentsFactory());
+ }
+ return DefaultFactory;
}
@@ -70,6 +75,7 @@ void CDockComponentsFactory::resetDefaultFactory()
{
DefaultFactory.reset(new CDockComponentsFactory());
}
+
} // namespace ads
//---------------------------------------------------------------------------
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockComponentsFactory.h b/scribus/third_party/Qt-Advanced-Docking-System/src/DockComponentsFactory.h
index 0d2b7d4c8..6ea881852 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockComponentsFactory.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockComponentsFactory.h
@@ -66,9 +66,11 @@ public:
virtual CDockAreaTitleBar* createDockAreaTitleBar(CDockAreaWidget* DockArea) const;
/**
- * Returns the default components factory
+ * This returns the default dock components factory instance.
+ * If no components factory is assigned to a specific dock manager, this
+ * global factory instance will be used.
*/
- static const CDockComponentsFactory* factory();
+ static QSharedPointer<ads::CDockComponentsFactory> factory();
/**
* Sets a new default factory for creation of GUI elements.
@@ -82,15 +84,6 @@ public:
static void resetDefaultFactory();
};
-
-/**
- * Convenience function to ease factory instance access
- */
-inline const CDockComponentsFactory* componentsFactory()
-{
- return CDockComponentsFactory::factory();
-}
-
} // namespace ads
//---------------------------------------------------------------------------
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockContainerWidget.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/DockContainerWidget.cpp
index 541893e5a..3d61d5c18 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockContainerWidget.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockContainerWidget.cpp
@@ -1,2290 +1,2503 @@
-/*******************************************************************************
-** Qt Advanced Docking System
-** Copyright (C) 2017 Uwe Kindler
-**
-** This library is free software; you can redistribute it and/or
-** modify it under the terms of the GNU Lesser General Public
-** License as published by the Free Software Foundation; either
-** version 2.1 of the License, or (at your option) any later version.
-**
-** This library is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-** Lesser General Public License for more details.
-**
-** You should have received a copy of the GNU Lesser General Public
-** License along with this library; If not, see <http://www.gnu.org/licenses/>.
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockContainerWidget.cpp
-/// \author Uwe Kindler
-/// \date 24.02.2017
-/// \brief Implementation of CDockContainerWidget class
-//============================================================================
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include "DockContainerWidget.h"
-
-#include <QEvent>
-#include <QList>
-#include <QGridLayout>
-#include <QPointer>
-#include <QVariant>
-#include <QDebug>
-#include <QXmlStreamWriter>
-#include <QAbstractButton>
-#include <QLabel>
-#include <QTimer>
-#include <QMetaObject>
-#include <QMetaType>
-#include <QApplication>
-
-#include "DockManager.h"
-#include "DockAreaWidget.h"
-#include "DockWidget.h"
-#include "DockingStateReader.h"
-#include "FloatingDockContainer.h"
-#include "DockOverlay.h"
-#include "ads_globals.h"
-#include "DockSplitter.h"
-#include "DockWidgetTab.h"
-#include "DockAreaTitleBar.h"
-#include "DockFocusController.h"
-#include "AutoHideDockContainer.h"
-#include "AutoHideSideBar.h"
-#include "AutoHideTab.h"
-
-#include <functional>
-#include <iostream>
-
-#if QT_VERSION < 0x050900
-
-inline char toHexLower(uint value)
-{
- return "0123456789abcdef"[value & 0xF];
-}
-
-QByteArray qByteArrayToHex(const QByteArray& src, char separator)
-{
- if(src.size() == 0)
- return QByteArray();
-
- const int length = separator ? (src.size() * 3 - 1) : (src.size() * 2);
- QByteArray hex(length, Qt::Uninitialized);
- char *hexData = hex.data();
- const uchar *data = reinterpret_cast<const uchar *>(src.data());
- for (int i = 0, o = 0; i < src.size(); ++i) {
- hexData[o++] = toHexLower(data[i] >> 4);
- hexData[o++] = toHexLower(data[i] & 0xf);
-
- if ((separator) && (o < length))
- hexData[o++] = separator;
- }
- return hex;
-}
-#endif
-
-namespace ads
-{
-static unsigned int zOrderCounter = 0;
-
-enum eDropMode
-{
- DropModeIntoArea,///< drop widget into a dock area
- DropModeIntoContainer,///< drop into container
- DropModeInvalid///< invalid mode - do not drop
-};
-
-/**
- * Converts dock area ID to an index for array access
- */
-static int areaIdToIndex(DockWidgetArea area)
-{
- switch (area)
- {
- case LeftDockWidgetArea: return 0;
- case RightDockWidgetArea: return 1;
- case TopDockWidgetArea: return 2;
- case BottomDockWidgetArea: return 3;
- case CenterDockWidgetArea: return 4;
- default:
- return 4;
- }
-}
-
-/**
- * Helper function to ease insertion of dock area into splitter
- */
-static void insertWidgetIntoSplitter(QSplitter* Splitter, QWidget* widget, bool Append)
-{
- if (Append)
- {
- Splitter->addWidget(widget);
- }
- else
- {
- Splitter->insertWidget(0, widget);
- }
-}
-
-/**
- * Private data class of CDockContainerWidget class (pimpl)
- */
-class DockContainerWidgetPrivate
-{
-public:
- CDockContainerWidget* _this;
- QPointer<CDockManager> DockManager;
- unsigned int zOrderIndex = 0;
- QList<QPointer<CDockAreaWidget>> DockAreas;
- QList<CAutoHideDockContainer*> AutoHideWidgets;
- QMap<SideBarLocation, CAutoHideSideBar*> SideTabBarWidgets;
- QGridLayout* Layout = nullptr;
- CDockSplitter* RootSplitter = nullptr;
- bool isFloating = false;
- CDockAreaWidget* LastAddedAreaCache[5];
- int VisibleDockAreaCount = -1;
- CDockAreaWidget* TopLevelDockArea = nullptr;
- QTimer DelayedAutoHideTimer;
- CAutoHideTab* DelayedAutoHideTab;
- bool DelayedAutoHideShow = false;
-
- /**
- * Private data constructor
- */
- DockContainerWidgetPrivate(CDockContainerWidget* _public);
-
- /**
- * Adds dock widget to container and returns the dock area that contains
- * the inserted dock widget
- */
- CDockAreaWidget* addDockWidgetToContainer(DockWidgetArea area, CDockWidget* Dockwidget);
-
- /**
- * Adds dock widget to a existing DockWidgetArea
- */
- CDockAreaWidget* addDockWidgetToDockArea(DockWidgetArea area, CDockWidget* Dockwidget,
- CDockAreaWidget* TargetDockArea, int Index = -1);
-
- /**
- * Add dock area to this container
- */
- void addDockArea(CDockAreaWidget* NewDockWidget, DockWidgetArea area = CenterDockWidgetArea);
-
- /**
- * Drop floating widget into container
- */
- 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, 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,
- int TabIndex = 0);
-
- /**
- * Moves the dock widget or dock area given in Widget parameter to a
- * a dock area in container
- */
- void moveToContainer(QWidget* Widgett, DockWidgetArea area);
-
- /**
- * Creates a new tab for a widget dropped into the center of a section
- */
- void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea, int TabIndex = 0);
-
- /**
- * Moves the dock widget or dock area given in Widget parameter to
- * a auto hide sidebar area
- */
- void moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area, int TabIndex = TabDefaultInsertIndex);
-
-
- /**
- * Adds new dock areas to the internal dock area list
- */
- void addDockAreasToList(const QList<CDockAreaWidget*> NewDockAreas);
-
- /**
- * Wrapper function for DockAreas append, that ensures that dock area signals
- * are properly connected to dock container slots
- */
- void appendDockAreas(const QList<CDockAreaWidget*> NewDockAreas);
-
- /**
- * Save state of child nodes
- */
- void saveChildNodesState(QXmlStreamWriter& Stream, QWidget* Widget);
-
- /**
- * Save state of auto hide widgets
- */
- void saveAutoHideWidgetsState(QXmlStreamWriter& Stream);
-
- /**
- * Restore state of child nodes.
- * \param[in] Stream The data stream that contains the serialized state
- * \param[out] CreatedWidget The widget created from parsed data or 0 if
- * the parsed widget was an empty splitter
- * \param[in] Testing If Testing is true, only the stream data is
- * parsed without modifying anything.
- */
- bool restoreChildNodes(CDockingStateReader& Stream, QWidget*& CreatedWidget,
- bool Testing);
-
- /**
- * Restores a splitter.
- * \see restoreChildNodes() for details
- */
- bool restoreSplitter(CDockingStateReader& Stream, QWidget*& CreatedWidget,
- bool Testing);
-
- /**
- * Restores a dock area.
- * \see restoreChildNodes() for details
- */
- bool restoreDockArea(CDockingStateReader& Stream, QWidget*& CreatedWidget,
- bool Testing);
-
- /**
- * Restores a auto hide side bar
- */
- bool restoreSideBar(CDockingStateReader& Stream, QWidget*& CreatedWidget,
- bool Testing);
-
- /**
- * Helper function for recursive dumping of layout
- */
- void dumpRecursive(int level, QWidget* widget);
-
- /**
- * Calculate the drop mode from the given target position
- */
- eDropMode getDropMode(const QPoint& TargetPos);
-
- /**
- * Initializes the visible dock area count variable if it is not initialized
- * yet
- */
- void initVisibleDockAreaCount()
- {
- if (VisibleDockAreaCount > -1)
- {
- return;
- }
-
- VisibleDockAreaCount = 0;
- for (auto DockArea : DockAreas)
- {
- if (!DockArea)
- {
- continue;
- }
- VisibleDockAreaCount += (DockArea->isHidden() ? 0 : 1);
- }
- }
-
- /**
- * Access function for the visible dock area counter
- */
- int& visibleDockAreaCount()
- {
- // Lazy initialisation - we initialize the VisibleDockAreaCount variable
- // on first use
- initVisibleDockAreaCount();
- return VisibleDockAreaCount;
- }
-
- /**
- * The visible dock area count changes, if dock areas are remove, added or
- * when its view is toggled
- */
- void onVisibleDockAreaCountChanged();
-
- void emitDockAreasRemoved()
- {
- onVisibleDockAreaCountChanged();
- Q_EMIT _this->dockAreasRemoved();
- }
-
- void emitDockAreasAdded()
- {
- onVisibleDockAreaCountChanged();
- Q_EMIT _this->dockAreasAdded();
- }
-
- /**
- * Helper function for creation of new splitter
- */
- CDockSplitter* newSplitter(Qt::Orientation orientation, QWidget* parent = nullptr)
- {
- CDockSplitter* s = new CDockSplitter(orientation, parent);
- s->setOpaqueResize(CDockManager::testConfigFlag(CDockManager::OpaqueSplitterResize));
- s->setChildrenCollapsible(false);
- return s;
- }
-
- /**
- * Ensures equal distribution of the sizes of a splitter if an dock widget
- * is inserted from code
- */
- void adjustSplitterSizesOnInsertion(QSplitter* Splitter, qreal LastRatio = 1.0)
- {
- int AreaSize = (Splitter->orientation() == Qt::Horizontal) ? Splitter->width() : Splitter->height();
- auto SplitterSizes = Splitter->sizes();
-
- qreal TotRatio = SplitterSizes.size() - 1.0 + LastRatio;
- for(int i = 0; i < SplitterSizes.size() -1; i++)
- {
- SplitterSizes[i] = AreaSize / TotRatio;
- }
- SplitterSizes.back() = AreaSize * LastRatio / TotRatio;
- Splitter->setSizes(SplitterSizes);
- }
-
- /**
- * This function forces the dock container widget to update handles of splitters
- * based if a central widget exists.
- */
- void updateSplitterHandles(QSplitter* splitter);
-
- /**
- * If no central widget exists, the widgets resize with the container.
- * If a central widget exists, the widgets surrounding the central widget
- * do not resize its height or width.
- */
- bool widgetResizesWithContainer(QWidget* widget);
-
-// private slots: ------------------------------------------------------------
- void onDockAreaViewToggled(bool Visible)
- {
- CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(_this->sender());
- VisibleDockAreaCount += Visible ? 1 : -1;
- onVisibleDockAreaCountChanged();
- Q_EMIT _this->dockAreaViewToggled(DockArea, Visible);
- }
-}; // struct DockContainerWidgetPrivate
-
-
-//============================================================================
-DockContainerWidgetPrivate::DockContainerWidgetPrivate(CDockContainerWidget* _public) :
- _this(_public)
-{
- std::fill(std::begin(LastAddedAreaCache),std::end(LastAddedAreaCache), nullptr);
- DelayedAutoHideTimer.setSingleShot(true);
- DelayedAutoHideTimer.setInterval(500);
- QObject::connect(&DelayedAutoHideTimer, &QTimer::timeout, [this](){
- auto GlobalPos = DelayedAutoHideTab->mapToGlobal(QPoint(0, 0));
- qApp->sendEvent(DelayedAutoHideTab, new QMouseEvent(QEvent::MouseButtonPress,
- QPoint(0, 0), GlobalPos, Qt::LeftButton, {Qt::LeftButton}, Qt::NoModifier));
- });
-}
-
-
-//============================================================================
-eDropMode DockContainerWidgetPrivate::getDropMode(const QPoint& TargetPos)
-{
- CDockAreaWidget* DockArea = _this->dockAreaAt(TargetPos);
- auto dropArea = InvalidDockWidgetArea;
- auto ContainerDropArea = DockManager->containerOverlay()->dropAreaUnderCursor();
-
- if (DockArea)
- {
- auto dropOverlay = DockManager->dockAreaOverlay();
- dropOverlay->setAllowedAreas(DockArea->allowedAreas());
- dropArea = dropOverlay->showOverlay(DockArea);
- if (ContainerDropArea != InvalidDockWidgetArea &&
- ContainerDropArea != dropArea)
- {
- dropArea = InvalidDockWidgetArea;
- }
-
- if (dropArea != InvalidDockWidgetArea)
- {
- ADS_PRINT("Dock Area Drop Content: " << dropArea);
- return DropModeIntoArea;
- }
- }
-
- // mouse is over container
- if (InvalidDockWidgetArea == dropArea)
- {
- dropArea = ContainerDropArea;
- ADS_PRINT("Container Drop Content: " << dropArea);
- if (dropArea != InvalidDockWidgetArea)
- {
- return DropModeIntoContainer;
- }
- }
-
- return DropModeInvalid;
-}
-
-
-//============================================================================
-void DockContainerWidgetPrivate::onVisibleDockAreaCountChanged()
-{
- auto TopLevelDockArea = _this->topLevelDockArea();
-
- if (TopLevelDockArea)
- {
- this->TopLevelDockArea = TopLevelDockArea;
- TopLevelDockArea->updateTitleBarButtonVisibility(true);
- }
- else if (this->TopLevelDockArea)
- {
- this->TopLevelDockArea->updateTitleBarButtonVisibility(false);
- this->TopLevelDockArea = nullptr;
- }
-}
-
-
-//============================================================================
-void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* FloatingWidget,
- DockWidgetArea area)
-{
- auto InsertParam = internal::dockAreaInsertParameters(area);
- CDockContainerWidget* FloatingDockContainer = FloatingWidget->dockContainer();
- auto NewDockAreas = FloatingDockContainer->findChildren<CDockAreaWidget*>(
- QString(), Qt::FindChildrenRecursively);
- auto Splitter = RootSplitter;
-
- if (DockAreas.count() <= 1)
- {
- Splitter->setOrientation(InsertParam.orientation());
- }
- else if (Splitter->orientation() != InsertParam.orientation())
- {
- auto NewSplitter = newSplitter(InsertParam.orientation());
- QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
- NewSplitter->addWidget(Splitter);
- updateSplitterHandles(NewSplitter);
- Splitter = NewSplitter;
- delete li;
- }
-
- // Now we can insert the floating widget content into this container
- auto FloatingSplitter = FloatingDockContainer->rootSplitter();
- if (FloatingSplitter->count() == 1)
- {
- insertWidgetIntoSplitter(Splitter, FloatingSplitter->widget(0), InsertParam.append());
- updateSplitterHandles(Splitter);
- }
- else if (FloatingSplitter->orientation() == InsertParam.orientation())
- {
- int InsertIndex = InsertParam.append() ? Splitter->count() : 0;
- while (FloatingSplitter->count())
- {
- Splitter->insertWidget(InsertIndex++, FloatingSplitter->widget(0));
- updateSplitterHandles(Splitter);
- }
- }
- else
- {
- insertWidgetIntoSplitter(Splitter, FloatingSplitter, InsertParam.append());
- }
-
- RootSplitter = Splitter;
- addDockAreasToList(NewDockAreas);
-
- // If we dropped the floating widget into the main dock container that does
- // not contain any dock widgets, then splitter is invisible and we need to
- // show it to display the docked widgets
- if (!Splitter->isVisible())
- {
- Splitter->show();
- }
- _this->dumpLayout();
-}
-
-
-//============================================================================
-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, 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
- // dock widget in the drop area.
- if (TopLevelDockArea)
- {
- NewCurrentIndex = TopLevelDockArea->currentIndex();
- }
-
- for (int i = 0; i < NewDockWidgets.count(); ++i)
- {
- CDockWidget* DockWidget = NewDockWidgets[i];
- 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.
- if (NewCurrentIndex < 0 && !DockWidget->isClosed())
- {
- NewCurrentIndex = i;
- }
- }
- TargetArea->setCurrentIndex(NewCurrentIndex + TabIndex);
- TargetArea->updateTitleBarVisibility();
- return;
-}
-
-
-//============================================================================
-void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* FloatingWidget,
- 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, TabIndex);
- return;
- }
-
- CDockContainerWidget* FloatingContainer = FloatingWidget->dockContainer();
- auto InsertParam = internal::dockAreaInsertParameters(area);
- auto NewDockAreas = FloatingContainer->findChildren<CDockAreaWidget*>(
- QString(), Qt::FindChildrenRecursively);
- auto TargetAreaSplitter = TargetArea->parentSplitter();
- int AreaIndex = TargetAreaSplitter->indexOf(TargetArea);
- auto FloatingSplitter = FloatingContainer->rootSplitter();
- if (TargetAreaSplitter->orientation() == InsertParam.orientation())
- {
- auto Sizes = TargetAreaSplitter->sizes();
- int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
- bool AdjustSplitterSizes = true;
- if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1)
- {
- TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), FloatingSplitter);
- updateSplitterHandles(TargetAreaSplitter);
- }
- else
- {
- AdjustSplitterSizes = (FloatingSplitter->count() == 1);
- int InsertIndex = AreaIndex + InsertParam.insertOffset();
- while (FloatingSplitter->count())
- {
- TargetAreaSplitter->insertWidget(InsertIndex++, FloatingSplitter->widget(0));
- updateSplitterHandles(TargetAreaSplitter);
- }
- }
-
- if (AdjustSplitterSizes)
- {
- int Size = (TargetAreaSize - TargetAreaSplitter->handleWidth()) / 2;
- Sizes[AreaIndex] = Size;
- Sizes.insert(AreaIndex, Size);
- TargetAreaSplitter->setSizes(Sizes);
- }
- }
- else
- {
- QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
- int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
- bool AdjustSplitterSizes = true;
- if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1)
- {
- NewSplitter->addWidget(FloatingSplitter);
- updateSplitterHandles(NewSplitter);
- }
- else
- {
- AdjustSplitterSizes = (FloatingSplitter->count() == 1);
- while (FloatingSplitter->count())
- {
- NewSplitter->addWidget(FloatingSplitter->widget(0));
- updateSplitterHandles(NewSplitter);
- }
- }
-
- // Save the sizes before insertion and restore it later to prevent
- // shrinking of existing area
- auto Sizes = TargetAreaSplitter->sizes();
- insertWidgetIntoSplitter(NewSplitter, TargetArea, !InsertParam.append());
- updateSplitterHandles(NewSplitter);
- if (AdjustSplitterSizes)
- {
- int Size = TargetAreaSize / 2;
- NewSplitter->setSizes({Size, Size});
- }
- TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter);
- TargetAreaSplitter->setSizes(Sizes);
- updateSplitterHandles(TargetAreaSplitter);
- }
-
- addDockAreasToList(NewDockAreas);
- _this->dumpLayout();
-}
-
-
-//============================================================================
-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();
- if (OldDockArea == TargetArea)
- {
- return;
- }
-
- if (OldDockArea)
- {
- OldDockArea->removeDockWidget(DroppedDockWidget);
- }
- TargetArea->insertDockWidget(TabIndex, DroppedDockWidget, true);
- }
- else
- {
- QList<CDockWidget*> NewDockWidgets = DroppedArea->dockWidgets();
- int NewCurrentIndex = DroppedArea->currentIndex();
- for (int i = 0; i < NewDockWidgets.count(); ++i)
- {
- CDockWidget* DockWidget = NewDockWidgets[i];
- TargetArea->insertDockWidget(TabIndex + i, DockWidget, false);
- }
- TargetArea->setCurrentIndex(TabIndex + NewCurrentIndex);
- DroppedArea->dockContainer()->removeDockArea(DroppedArea);
- DroppedArea->deleteLater();
- }
-
- TargetArea->updateTitleBarVisibility();
- return;
-}
-
-
-//============================================================================
-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, TabIndex);
- return;
- }
-
-
- CDockWidget* DroppedDockWidget = qobject_cast<CDockWidget*>(Widget);
- CDockAreaWidget* DroppedDockArea = qobject_cast<CDockAreaWidget*>(Widget);
- CDockAreaWidget* NewDockArea;
- if (DroppedDockWidget)
- {
- NewDockArea = new CDockAreaWidget(DockManager, _this);
- CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget();
- if (OldDockArea)
- {
- OldDockArea->removeDockWidget(DroppedDockWidget);
- }
- NewDockArea->addDockWidget(DroppedDockWidget);
- }
- else
- {
- DroppedDockArea->dockContainer()->removeDockArea(DroppedDockArea);
- NewDockArea = DroppedDockArea;
- }
-
- auto InsertParam = internal::dockAreaInsertParameters(area);
- auto TargetAreaSplitter = TargetArea->parentSplitter();
- int AreaIndex = TargetAreaSplitter->indexOf(TargetArea);
- auto Sizes = TargetAreaSplitter->sizes();
- if (TargetAreaSplitter->orientation() == InsertParam.orientation())
- {
- int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
- TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), NewDockArea);
- updateSplitterHandles(TargetAreaSplitter);
- int Size = (TargetAreaSize - TargetAreaSplitter->handleWidth()) / 2;
- Sizes[AreaIndex] = Size;
- Sizes.insert(AreaIndex, Size);
- }
- else
- {
- int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
- QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
- NewSplitter->addWidget(TargetArea);
- insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append());
- updateSplitterHandles(NewSplitter);
- int Size = TargetAreaSize / 2;
- NewSplitter->setSizes({Size, Size});
- TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter);
- updateSplitterHandles(TargetAreaSplitter);
- }
- TargetAreaSplitter->setSizes(Sizes);
-
- addDockAreasToList({NewDockArea});
-}
-
-
-//============================================================================
-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 )
-{
- if (!DockManager->centralWidget() || !splitter)
- {
- return;
- }
-
- for (int i = 0; i < splitter->count(); ++i)
- {
- splitter->setStretchFactor(i, widgetResizesWithContainer(splitter->widget(i)) ? 1 : 0);
- }
-}
-
-
-//============================================================================
-bool DockContainerWidgetPrivate::widgetResizesWithContainer(QWidget* widget)
-{
- if (!DockManager->centralWidget())
- {
- return true;
- }
-
- auto Area = qobject_cast<CDockAreaWidget*>(widget);
- if(Area)
- {
- return Area->isCentralWidgetArea();
- }
-
- auto innerSplitter = qobject_cast<CDockSplitter*>(widget);
- if (innerSplitter)
- {
- return innerSplitter->isResizingWithContainer();
- }
-
- return false;
-}
-
-
-
-//============================================================================
-void DockContainerWidgetPrivate::moveToContainer(QWidget* Widget, DockWidgetArea area)
-{
- CDockWidget* DroppedDockWidget = qobject_cast<CDockWidget*>(Widget);
- CDockAreaWidget* DroppedDockArea = qobject_cast<CDockAreaWidget*>(Widget);
- CDockAreaWidget* NewDockArea;
-
- if (DroppedDockWidget)
- {
- NewDockArea = new CDockAreaWidget(DockManager, _this);
- CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget();
- if (OldDockArea)
- {
- OldDockArea->removeDockWidget(DroppedDockWidget);
- }
- NewDockArea->addDockWidget(DroppedDockWidget);
- }
- else
- {
- // We check, if we insert the dropped widget into the same place that
- // it already has and do nothing, if it is the same place. It would
- // also work without this check, but it looks nicer with the check
- // because there will be no layout updates
- auto Splitter = DroppedDockArea->parentSplitter();
- auto InsertParam = internal::dockAreaInsertParameters(area);
- if (Splitter == RootSplitter && InsertParam.orientation() == Splitter->orientation())
- {
- if (InsertParam.append() && Splitter->lastWidget() == DroppedDockArea)
- {
- return;
- }
- else if (!InsertParam.append() && Splitter->firstWidget() == DroppedDockArea)
- {
- return;
- }
- }
- DroppedDockArea->dockContainer()->removeDockArea(DroppedDockArea);
- NewDockArea = DroppedDockArea;
- }
-
- addDockArea(NewDockArea, area);
- LastAddedAreaCache[areaIdToIndex(area)] = NewDockArea;
-}
-
-
-//============================================================================
-void DockContainerWidgetPrivate::addDockAreasToList(const QList<CDockAreaWidget*> NewDockAreas)
-{
- int CountBefore = DockAreas.count();
- int NewAreaCount = NewDockAreas.count();
- appendDockAreas(NewDockAreas);
- // If the user dropped a floating widget that contains only one single
- // visible dock area, then its title bar button TitleBarButtonUndock is
- // likely hidden. We need to ensure, that it is visible
- for (auto DockArea : NewDockAreas)
- {
- DockArea->titleBarButton(TitleBarButtonClose)->setVisible(true);
- DockArea->titleBarButton(TitleBarButtonAutoHide)->setVisible(true);
- }
-
- // We need to ensure, that the dock area title bar is visible. The title bar
- // is invisible, if the dock are is a single dock area in a floating widget.
- if (1 == CountBefore)
- {
- DockAreas.at(0)->updateTitleBarVisibility();
- }
-
- if (1 == NewAreaCount)
- {
- DockAreas.last()->updateTitleBarVisibility();
- }
-
- emitDockAreasAdded();
-}
-
-
-//============================================================================
-void DockContainerWidgetPrivate::appendDockAreas(const QList<CDockAreaWidget*> NewDockAreas)
-{
- for (auto *newDockArea : NewDockAreas)
- {
- DockAreas.append(newDockArea);
- }
- for (auto DockArea : NewDockAreas)
- {
- QObject::connect(DockArea,
- &CDockAreaWidget::viewToggled,
- _this,
- std::bind(&DockContainerWidgetPrivate::onDockAreaViewToggled, this, std::placeholders::_1));
- }
-}
-
-
-//============================================================================
-void DockContainerWidgetPrivate::saveChildNodesState(QXmlStreamWriter& s, QWidget* Widget)
-{
- QSplitter* Splitter = qobject_cast<QSplitter*>(Widget);
- if (Splitter)
- {
- s.writeStartElement("Splitter");
- s.writeAttribute("Orientation", (Splitter->orientation() == Qt::Horizontal) ? "|" : "-");
- s.writeAttribute("Count", QString::number(Splitter->count()));
- ADS_PRINT("NodeSplitter orient: " << Splitter->orientation()
- << " WidgetCont: " << Splitter->count());
- for (int i = 0; i < Splitter->count(); ++i)
- {
- saveChildNodesState(s, Splitter->widget(i));
- }
-
- s.writeStartElement("Sizes");
- for (auto Size : Splitter->sizes())
- {
- s.writeCharacters(QString::number(Size) + " ");
- }
- s.writeEndElement();
- s.writeEndElement();
- }
- else
- {
- CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(Widget);
- if (DockArea)
- {
- DockArea->saveState(s);
- }
- }
-}
-
-
-//============================================================================
-void DockContainerWidgetPrivate::saveAutoHideWidgetsState(QXmlStreamWriter& s)
-{
- for (const auto sideTabBar : SideTabBarWidgets.values())
- {
- if (!sideTabBar->count())
- {
- continue;
- }
-
- sideTabBar->saveState(s);
- }
-}
-
-
-//============================================================================
-bool DockContainerWidgetPrivate::restoreSplitter(CDockingStateReader& s,
- QWidget*& CreatedWidget, bool Testing)
-{
- bool Ok;
- QString OrientationStr = s.attributes().value("Orientation").toString();
-
- // Check if the orientation string is right
- if (!OrientationStr.startsWith("|") && !OrientationStr.startsWith("-"))
- {
- return false;
- }
-
- // The "|" shall indicate a vertical splitter handle which in turn means
- // a Horizontal orientation of the splitter layout.
- bool HorizontalSplitter = OrientationStr.startsWith("|");
- // In version 0 we had a small bug. The "|" indicated a vertical orientation,
- // but this is wrong, because only the splitter handle is vertical, the
- // layout of the splitter is a horizontal layout. We fix this here
- if (s.fileVersion() == 0)
- {
- HorizontalSplitter = !HorizontalSplitter;
- }
-
- int Orientation = HorizontalSplitter ? Qt::Horizontal : Qt::Vertical;
- int WidgetCount = s.attributes().value("Count").toInt(&Ok);
- if (!Ok)
- {
- return false;
- }
- ADS_PRINT("Restore NodeSplitter Orientation: " << Orientation <<
- " WidgetCount: " << WidgetCount);
- QSplitter* Splitter = nullptr;
- if (!Testing)
- {
- Splitter = newSplitter(static_cast<Qt::Orientation>(Orientation));
- }
- bool Visible = false;
- QList<int> Sizes;
- while (s.readNextStartElement())
- {
- QWidget* ChildNode = nullptr;
- bool Result = true;
- if (s.name() == QLatin1String("Splitter"))
- {
- Result = restoreSplitter(s, ChildNode, Testing);
- }
- else if (s.name() == QLatin1String("Area"))
- {
- Result = restoreDockArea(s, ChildNode, Testing);
- }
- else if (s.name() == QLatin1String("Sizes"))
- {
- QString sSizes = s.readElementText().trimmed();
- ADS_PRINT("Sizes: " << sSizes);
- QTextStream TextStream(&sSizes);
- while (!TextStream.atEnd())
- {
- int value;
- TextStream >> value;
- Sizes.append(value);
- }
- }
- else
- {
- s.skipCurrentElement();
- }
-
- if (!Result)
- {
- return false;
- }
-
- if (Testing || !ChildNode)
- {
- continue;
- }
-
- ADS_PRINT("ChildNode isVisible " << ChildNode->isVisible()
- << " isVisibleTo " << ChildNode->isVisibleTo(Splitter));
- Splitter->addWidget(ChildNode);
- Visible |= ChildNode->isVisibleTo(Splitter);
- }
- if(!Testing)
- {
- updateSplitterHandles(Splitter);
- }
-
- if (Sizes.count() != WidgetCount)
- {
- return false;
- }
-
- if (!Testing)
- {
- if (!Splitter->count())
- {
- delete Splitter;
- Splitter = nullptr;
- }
- else
- {
- Splitter->setSizes(Sizes);
- Splitter->setVisible(Visible);
- }
- CreatedWidget = Splitter;
- }
- else
- {
- CreatedWidget = nullptr;
- }
-
- return true;
-}
-
-
-//============================================================================
-bool DockContainerWidgetPrivate::restoreDockArea(CDockingStateReader& s,
- QWidget*& CreatedWidget, bool Testing)
-{
- CDockAreaWidget* DockArea = nullptr;
- auto Result = CDockAreaWidget::restoreState(s, DockArea, Testing, _this);
- if (Result && DockArea)
- {
- appendDockAreas({DockArea});
- }
- CreatedWidget = DockArea;
- return Result;
-}
-
-
-//============================================================================
-bool DockContainerWidgetPrivate::restoreSideBar(CDockingStateReader& s,
- QWidget*& CreatedWidget, bool Testing)
-{
- Q_UNUSED(CreatedWidget)
- // Simply ignore side bar auto hide widgets from saved state if
- // auto hide support is disabled
- if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
- {
- return true;
- }
-
- bool Ok;
- auto Area = (ads::SideBarLocation)s.attributes().value("Area").toInt(&Ok);
- if (!Ok)
- {
- return false;
- }
-
- while (s.readNextStartElement())
- {
- if (s.name() != QLatin1String("Widget"))
- {
- continue;
- }
-
- auto Name = s.attributes().value("Name");
- if (Name.isEmpty())
- {
- return false;
- }
-
- bool Ok;
- bool Closed = s.attributes().value("Closed").toInt(&Ok);
- if (!Ok)
- {
- return false;
- }
-
- int Size = s.attributes().value("Size").toInt(&Ok);
- if (!Ok)
- {
- return false;
- }
-
- s.skipCurrentElement();
- CDockWidget* DockWidget = DockManager->findDockWidget(Name.toString());
- if (!DockWidget || Testing)
- {
- continue;
- }
-
- auto SideBar = _this->autoHideSideBar(Area);
- CAutoHideDockContainer* AutoHideContainer;
- if (DockWidget->isAutoHide())
- {
- AutoHideContainer = DockWidget->autoHideDockContainer();
- if (AutoHideContainer->autoHideSideBar() != SideBar)
- {
- SideBar->addAutoHideWidget(AutoHideContainer);
- }
- }
- else
- {
- AutoHideContainer = SideBar->insertDockWidget(-1, DockWidget);
- }
- AutoHideContainer->setSize(Size);
- DockWidget->setProperty(internal::ClosedProperty, Closed);
- DockWidget->setProperty(internal::DirtyProperty, false);
- }
-
- return true;
-}
-
-
-//============================================================================
-bool DockContainerWidgetPrivate::restoreChildNodes(CDockingStateReader& s,
- QWidget*& CreatedWidget, bool Testing)
-{
- bool Result = true;
- while (s.readNextStartElement())
- {
- if (s.name() == QLatin1String("Splitter"))
- {
- Result = restoreSplitter(s, CreatedWidget, Testing);
- ADS_PRINT("Splitter");
- }
- else if (s.name() == QLatin1String("Area"))
- {
- Result = restoreDockArea(s, CreatedWidget, Testing);
- ADS_PRINT("DockAreaWidget");
- }
- else if (s.name() == QLatin1String("SideBar"))
- {
- Result = restoreSideBar(s, CreatedWidget, Testing);
- ADS_PRINT("SideBar");
- }
- else
- {
- s.skipCurrentElement();
- ADS_PRINT("Unknown element");
- }
- }
-
- return Result;
-}
-
-
-//============================================================================
-CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToContainer(DockWidgetArea area,
- CDockWidget* Dockwidget)
-{
- CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this);
- NewDockArea->addDockWidget(Dockwidget);
- addDockArea(NewDockArea, area);
- NewDockArea->updateTitleBarVisibility();
- LastAddedAreaCache[areaIdToIndex(area)] = NewDockArea;
- return NewDockArea;
-}
-
-
-//============================================================================
-void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockWidgetArea area)
-{
- auto InsertParam = internal::dockAreaInsertParameters(area);
- // As long as we have only one dock area in the splitter we can adjust
- // its orientation
- if (DockAreas.count() <= 1)
- {
- RootSplitter->setOrientation(InsertParam.orientation());
- }
-
- QSplitter* Splitter = RootSplitter;
- if (Splitter->orientation() == InsertParam.orientation())
- {
- insertWidgetIntoSplitter(Splitter, NewDockArea, InsertParam.append());
- updateSplitterHandles(Splitter);
- if (Splitter->isHidden())
- {
- Splitter->show();
- }
- }
- else
- {
- auto NewSplitter = newSplitter(InsertParam.orientation());
- if (InsertParam.append())
- {
- QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
- NewSplitter->addWidget(Splitter);
- NewSplitter->addWidget(NewDockArea);
- updateSplitterHandles(NewSplitter);
- delete li;
- }
- else
- {
- NewSplitter->addWidget(NewDockArea);
- QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
- NewSplitter->addWidget(Splitter);
- updateSplitterHandles(NewSplitter);
- delete li;
- }
- RootSplitter = NewSplitter;
- }
-
- addDockAreasToList({NewDockArea});
-}
-
-
-//============================================================================
-void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget)
-{
-#if defined(QT_DEBUG)
- QSplitter* Splitter = qobject_cast<QSplitter*>(widget);
- QByteArray buf;
- buf.fill(' ', level * 4);
- if (Splitter)
- {
-#ifdef ADS_DEBUG_PRINT
- qDebug("%sSplitter %s v: %s c: %s",
- (const char*)buf,
- (Splitter->orientation() == Qt::Vertical) ? "--" : "|",
- Splitter->isHidden() ? " " : "v",
- QString::number(Splitter->count()).toStdString().c_str());
- std::cout << (const char*)buf << "Splitter "
- << ((Splitter->orientation() == Qt::Vertical) ? "--" : "|") << " "
- << (Splitter->isHidden() ? " " : "v") << " "
- << QString::number(Splitter->count()).toStdString() << std::endl;
-#endif
- for (int i = 0; i < Splitter->count(); ++i)
- {
- dumpRecursive(level + 1, Splitter->widget(i));
- }
- }
- else
- {
- CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(widget);
- if (!DockArea)
- {
- return;
- }
-#ifdef ADS_DEBUG_PRINT
- qDebug("%sDockArea", (const char*)buf);
- std::cout << (const char*)buf
- << (DockArea->isHidden() ? " " : "v")
- << (DockArea->openDockWidgetsCount() > 0 ? " " : "c")
- << " DockArea " << "[hs: " << DockArea->sizePolicy().horizontalStretch() << ", vs: " << DockArea->sizePolicy().verticalStretch() << "]" << std::endl;
- buf.fill(' ', (level + 1) * 4);
- for (int i = 0; i < DockArea->dockWidgetsCount(); ++i)
- {
- std::cout << (const char*)buf << (i == DockArea->currentIndex() ? "*" : " ");
- CDockWidget* DockWidget = DockArea->dockWidget(i);
- std::cout << (DockWidget->isHidden() ? " " : "v");
- std::cout << (DockWidget->isClosed() ? "c" : " ") << " ";
- std::cout << DockWidget->windowTitle().toStdString() << std::endl;
- }
-#endif
- }
-#else
- Q_UNUSED(level);
- Q_UNUSED(widget);
-#endif
-}
-
-
-//============================================================================
-CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetArea area,
- CDockWidget* Dockwidget, CDockAreaWidget* TargetDockArea, int Index)
-{
- if (CenterDockWidgetArea == area)
- {
- TargetDockArea->insertDockWidget(Index, Dockwidget);
- TargetDockArea->updateTitleBarVisibility();
- return TargetDockArea;
- }
-
- CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this);
- NewDockArea->addDockWidget(Dockwidget);
- auto InsertParam = internal::dockAreaInsertParameters(area);
-
- auto TargetAreaSplitter = TargetDockArea->parentSplitter();
- int index = TargetAreaSplitter ->indexOf(TargetDockArea);
- if (TargetAreaSplitter->orientation() == InsertParam.orientation())
- {
- ADS_PRINT("TargetAreaSplitter->orientation() == InsertParam.orientation()");
- TargetAreaSplitter->insertWidget(index + InsertParam.insertOffset(), NewDockArea);
- updateSplitterHandles(TargetAreaSplitter);
- // do nothing, if flag is not enabled
- if (CDockManager::testConfigFlag(CDockManager::EqualSplitOnInsertion))
- {
- adjustSplitterSizesOnInsertion(TargetAreaSplitter);
- }
- }
- else
- {
- ADS_PRINT("TargetAreaSplitter->orientation() != InsertParam.orientation()");
- auto TargetAreaSizes = TargetAreaSplitter->sizes();
- auto NewSplitter = newSplitter(InsertParam.orientation());
- NewSplitter->addWidget(TargetDockArea);
-
- insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append());
- updateSplitterHandles(NewSplitter);
- TargetAreaSplitter->insertWidget(index, NewSplitter);
- updateSplitterHandles(TargetAreaSplitter);
- if (CDockManager::testConfigFlag(CDockManager::EqualSplitOnInsertion))
- {
- TargetAreaSplitter->setSizes(TargetAreaSizes);
- adjustSplitterSizesOnInsertion(NewSplitter);
- }
- }
-
- addDockAreasToList({NewDockArea});
- return NewDockArea;
-}
-
-
-//============================================================================
-CDockContainerWidget::CDockContainerWidget(CDockManager* DockManager, QWidget *parent) :
- QFrame(parent),
- d(new DockContainerWidgetPrivate(this))
-{
- d->DockManager = DockManager;
- d->isFloating = floatingWidget() != nullptr;
-
- d->Layout = new QGridLayout();
- d->Layout->setContentsMargins(0, 0, 0, 0);
- d->Layout->setSpacing(0);
- d->Layout->setColumnStretch(1, 1);
- d->Layout->setRowStretch(1, 1);
- setLayout(d->Layout);
-
- // The function d->newSplitter() accesses the config flags from dock
- // manager which in turn requires a properly constructed dock manager.
- // If this dock container is the dock manager, then it is not properly
- // constructed yet because this base class constructor is called before
- // the constructor of the DockManager private class
- if (DockManager != this)
- {
- d->DockManager->registerDockContainer(this);
- createRootSplitter();
- createSideTabBarWidgets();
- }
-}
-
-
-//============================================================================
-CDockContainerWidget::~CDockContainerWidget()
-{
- if (d->DockManager)
- {
- d->DockManager->removeDockContainer(this);
- }
-
- delete d;
-}
-
-
-//============================================================================
-CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
- CDockAreaWidget* DockAreaWidget, int Index)
-{
- auto TopLevelDockWidget = topLevelDockWidget();
- CDockAreaWidget* OldDockArea = Dockwidget->dockAreaWidget();
- if (OldDockArea)
- {
- OldDockArea->removeDockWidget(Dockwidget);
- }
-
- Dockwidget->setDockManager(d->DockManager);
- CDockAreaWidget* DockArea;
- if (DockAreaWidget)
- {
- DockArea = d->addDockWidgetToDockArea(area, Dockwidget, DockAreaWidget, Index);
- }
- else
- {
- DockArea = d->addDockWidgetToContainer(area, Dockwidget);
- }
-
- if (TopLevelDockWidget)
- {
- auto NewTopLevelDockWidget = topLevelDockWidget();
- // If the container contained only one visible dock widget, the we need
- // to emit a top level event for this widget because it is not the one and
- // only visible docked widget anymore
- if (!NewTopLevelDockWidget)
- {
- CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidget, false);
- }
- }
- return DockArea;
-}
-
-
-//============================================================================
-CAutoHideDockContainer* CDockContainerWidget::createAndSetupAutoHideContainer(
- SideBarLocation area, CDockWidget* DockWidget, int TabIndex)
-{
- if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
- {
- Q_ASSERT_X(false, "CDockContainerWidget::createAndInitializeDockWidgetOverlayContainer",
- "Requested area does not exist in config");
- return nullptr;
- }
- if (d->DockManager != DockWidget->dockManager())
- {
- DockWidget->setDockManager(d->DockManager); // Auto hide Dock Container needs a valid dock manager
- }
-
- return autoHideSideBar(area)->insertDockWidget(TabIndex, DockWidget);
-}
-
-
-//============================================================================
-void CDockContainerWidget::removeDockWidget(CDockWidget* Dockwidget)
-{
- CDockAreaWidget* Area = Dockwidget->dockAreaWidget();
- if (Area)
- {
- Area->removeDockWidget(Dockwidget);
- }
-}
-
-//============================================================================
-unsigned int CDockContainerWidget::zOrderIndex() const
-{
- return d->zOrderIndex;
-}
-
-
-//============================================================================
-bool CDockContainerWidget::isInFrontOf(CDockContainerWidget* Other) const
-{
- return this->zOrderIndex() > Other->zOrderIndex();
-}
-
-
-//============================================================================
-bool CDockContainerWidget::event(QEvent *e)
-{
- bool Result = QWidget::event(e);
- if (e->type() == QEvent::WindowActivate)
- {
- d->zOrderIndex = ++zOrderCounter;
- }
- else if (e->type() == QEvent::Show && !d->zOrderIndex)
- {
- d->zOrderIndex = ++zOrderCounter;
- }
-
- return Result;
-}
-
-
-//============================================================================
-QList<CAutoHideDockContainer*> CDockContainerWidget::autoHideWidgets() const
-{
- return d->AutoHideWidgets;
-}
-
-
-//============================================================================
-void CDockContainerWidget::addDockArea(CDockAreaWidget* DockAreaWidget,
- DockWidgetArea area)
-{
- CDockContainerWidget* Container = DockAreaWidget->dockContainer();
- if (Container && Container != this)
- {
- Container->removeDockArea(DockAreaWidget);
- }
-
- d->addDockArea(DockAreaWidget, area);
-}
-
-
-//============================================================================
-void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
-{
- ADS_PRINT("CDockContainerWidget::removeDockArea");
- // If it is an auto hide area, then there is nothing much to do
- if (area->isAutoHide())
- {
- area->setAutoHideDockContainer(nullptr);
- return;
- }
-
- area->disconnect(this);
- d->DockAreas.removeAll(area);
- auto Splitter = area->parentSplitter();
-
- // Remove are from parent splitter and recursively hide tree of parent
- // splitters if it has no visible content
- area->setParent(nullptr);
- internal::hideEmptyParentSplitters(Splitter);
-
- // Remove this area from cached areas
- auto p = std::find(std::begin(d->LastAddedAreaCache), std::end(d->LastAddedAreaCache), area);
- if (p != std::end(d->LastAddedAreaCache)) {
- *p = nullptr;
- }
-
- // If splitter has more than 1 widgets, we are finished and can leave
- if (Splitter->count() > 1)
- {
- goto emitAndExit;
- }
-
- // If this is the RootSplitter we need to remove empty splitters to
- // avoid too many empty splitters
- if (Splitter == d->RootSplitter)
- {
- ADS_PRINT("Removed from RootSplitter");
- // If splitter is empty, we are finished
- if (!Splitter->count())
- {
- Splitter->hide();
- goto emitAndExit;
- }
-
- QWidget* widget = Splitter->widget(0);
- 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)
- {
- goto emitAndExit;
- }
-
- // We replace the superfluous RootSplitter with the ChildSplitter
- ChildSplitter->setParent(nullptr);
- QLayoutItem* li = d->Layout->replaceWidget(Splitter, ChildSplitter);
- d->RootSplitter = ChildSplitter;
- delete li;
- ADS_PRINT("RootSplitter replaced by child splitter");
- }
- else if (Splitter->count() == 1)
- {
- ADS_PRINT("Replacing splitter with content");
- QSplitter* ParentSplitter = internal::findParent<QSplitter*>(Splitter);
- auto Sizes = ParentSplitter->sizes();
- QWidget* widget = Splitter->widget(0);
- widget->setParent(this);
- internal::replaceSplitterWidget(ParentSplitter, Splitter, widget);
- ParentSplitter->setSizes(Sizes);
- }
-
- delete Splitter;
- Splitter = nullptr;
-
-emitAndExit:
- updateSplitterHandles(Splitter);
- CDockWidget* TopLevelWidget = topLevelDockWidget();
-
- // Updated the title bar visibility of the dock widget if there is only
- // one single visible dock widget
- CDockWidget::emitTopLevelEventForWidget(TopLevelWidget, true);
- dumpLayout();
- d->emitDockAreasRemoved();
-}
-
-
-//============================================================================
-QList<QPointer<CDockAreaWidget>> CDockContainerWidget::removeAllDockAreas()
-{
- auto Result = d->DockAreas;
- d->DockAreas.clear();
- return Result;
-}
-
-
-//============================================================================
-CDockAreaWidget* CDockContainerWidget::dockAreaAt(const QPoint& GlobalPos) const
-{
- for (const auto& DockArea : d->DockAreas)
- {
- if (DockArea && DockArea->isVisible() && DockArea->rect().contains(DockArea->mapFromGlobal(GlobalPos)))
- {
- return DockArea;
- }
- }
-
- return nullptr;
-}
-
-
-//============================================================================
-CDockAreaWidget* CDockContainerWidget::dockArea(int Index) const
-{
- return (Index < dockAreaCount()) ? d->DockAreas[Index] : nullptr;
-}
-
-
-//============================================================================
-bool CDockContainerWidget::isFloating() const
-{
- return d->isFloating;
-}
-
-
-//============================================================================
-int CDockContainerWidget::dockAreaCount() const
-{
- return d->DockAreas.count();
-}
-
-
-//============================================================================
-int CDockContainerWidget::visibleDockAreaCount() const
-{
- int Result = 0;
- for (auto DockArea : d->DockAreas)
- {
- Result += (!DockArea || DockArea->isHidden()) ? 0 : 1;
- }
-
- return Result;
-
- // TODO Cache or precalculate this to speed it up because it is used during
- // movement of floating widget
- //return d->visibleDockAreaCount();
-}
-
-
-//============================================================================
-void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWidget,
- const QPoint& TargetPos)
-{
- ADS_PRINT("CDockContainerWidget::dropFloatingWidget");
- CDockWidget* SingleDroppedDockWidget = FloatingWidget->topLevelDockWidget();
- CDockWidget* SingleDockWidget = topLevelDockWidget();
- 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();
- dropOverlay->setAllowedAreas(DockArea->allowedAreas());
- dropArea = dropOverlay->showOverlay(DockArea);
- if (ContainerDropArea != InvalidDockWidgetArea &&
- ContainerDropArea != dropArea)
- {
- dropArea = InvalidDockWidgetArea;
- }
-
- if (dropArea != InvalidDockWidgetArea)
- {
- ADS_PRINT("Dock Area Drop Content: " << dropArea);
- int TabIndex = d->DockManager->dockAreaOverlay()->tabIndexUnderCursor();
- d->dropIntoSection(FloatingWidget, DockArea, dropArea, TabIndex);
- Dropped = true;
- }
- }
-
- // mouse is over container or auto hide side bar
- if (InvalidDockWidgetArea == dropArea && InvalidDockWidgetArea != ContainerDropArea)
- {
- 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 = autoHideSideBar(AutohideWidget->sideBarLocation());
- SideBar->addAutoHideWidget(AutohideWidget);
- }
-
- if (Dropped)
- {
- // Fix https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/351
- FloatingWidget->finishDropOperation();
-
- // If we dropped a floating widget with only one single dock widget, then we
- // drop a top level widget that changes from floating to docked now
- CDockWidget::emitTopLevelEventForWidget(SingleDroppedDockWidget, false);
-
- // If there was a top level widget before the drop, then it is not top
- // level widget anymore
- CDockWidget::emitTopLevelEventForWidget(SingleDockWidget, false);
- }
-
- window()->activateWindow();
- if (SingleDroppedDockWidget)
- {
- d->DockManager->notifyWidgetOrAreaRelocation(SingleDroppedDockWidget);
- }
- d->DockManager->notifyFloatingWidgetDrop(FloatingWidget);
-}
-
-
-//============================================================================
-void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget,
- int TabIndex)
-{
- CDockWidget* SingleDockWidget = topLevelDockWidget();
- if (TargetAreaWidget)
- {
- d->moveToNewSection(Widget, TargetAreaWidget, DropArea, TabIndex);
- }
- else if (internal::isSideBarArea(DropArea))
- {
- d->moveToAutoHideSideBar(Widget, DropArea, TabIndex);
- }
- else
- {
- d->moveToContainer(Widget, DropArea);
- }
-
- // If there was a top level widget before the drop, then it is not top
- // level widget anymore
- CDockWidget::emitTopLevelEventForWidget(SingleDockWidget, false);
-
- window()->activateWindow();
- d->DockManager->notifyWidgetOrAreaRelocation(Widget);
-}
-
-
-//============================================================================
-QList<CDockAreaWidget*> CDockContainerWidget::openedDockAreas() const
-{
- QList<CDockAreaWidget*> Result;
- for (auto DockArea : d->DockAreas)
- {
- if (DockArea && !DockArea->isHidden())
- {
- Result.append(DockArea);
- }
- }
-
- return Result;
-}
-
-
-//============================================================================
-QList<CDockWidget*> CDockContainerWidget::openedDockWidgets() const
-{
- QList<CDockWidget*> DockWidgetList;
- for (auto DockArea : d->DockAreas)
- {
- if (DockArea && !DockArea->isHidden())
- {
- DockWidgetList.append(DockArea->openedDockWidgets());
- }
- }
-
- return DockWidgetList;
-}
-
-
-//============================================================================
-bool CDockContainerWidget::hasOpenDockAreas() const
-{
- for (auto DockArea : d->DockAreas)
- {
- if (DockArea && !DockArea->isHidden())
- {
- return true;
- }
- }
-
- return false;
-}
-
-
-//============================================================================
-void CDockContainerWidget::saveState(QXmlStreamWriter& s) const
-{
- ADS_PRINT("CDockContainerWidget::saveState isFloating "
- << isFloating());
-
- s.writeStartElement("Container");
- s.writeAttribute("Floating", QString::number(isFloating() ? 1 : 0));
- if (isFloating())
- {
- CFloatingDockContainer* FloatingWidget = floatingWidget();
- QByteArray Geometry = FloatingWidget->saveGeometry();
-#if QT_VERSION < 0x050900
- s.writeTextElement("Geometry", qByteArrayToHex(Geometry, ' '));
-#else
- s.writeTextElement("Geometry", Geometry.toHex(' '));
-#endif
- }
- d->saveChildNodesState(s, d->RootSplitter);
- d->saveAutoHideWidgetsState(s);
- s.writeEndElement();
-}
-
-
-//============================================================================
-bool CDockContainerWidget::restoreState(CDockingStateReader& s, bool Testing)
-{
- bool IsFloating = s.attributes().value("Floating").toInt();
- ADS_PRINT("Restore CDockContainerWidget Floating" << IsFloating);
-
- QWidget* NewRootSplitter {};
- if (!Testing)
- {
- d->VisibleDockAreaCount = -1;// invalidate the dock area count
- d->DockAreas.clear();
- std::fill(std::begin(d->LastAddedAreaCache),std::end(d->LastAddedAreaCache), nullptr);
- }
-
- if (IsFloating)
- {
- ADS_PRINT("Restore floating widget");
- if (!s.readNextStartElement() || s.name() != QLatin1String("Geometry"))
- {
- return false;
- }
-
- QByteArray GeometryString = s.readElementText(CDockingStateReader::ErrorOnUnexpectedElement).toLocal8Bit();
- QByteArray Geometry = QByteArray::fromHex(GeometryString);
- if (Geometry.isEmpty())
- {
- return false;
- }
-
- if (!Testing)
- {
- CFloatingDockContainer* FloatingWidget = floatingWidget();
- if (FloatingWidget)
- {
- FloatingWidget->restoreGeometry(Geometry);
- }
- }
- }
-
- if (!d->restoreChildNodes(s, NewRootSplitter, Testing))
- {
- return false;
- }
-
- if (Testing)
- {
- return true;
- }
-
- // If the root splitter is empty, rostoreChildNodes returns a 0 pointer
- // and we need to create a new empty root splitter
- if (!NewRootSplitter)
- {
- NewRootSplitter = d->newSplitter(Qt::Horizontal);
- }
-
- QLayoutItem* li = d->Layout->replaceWidget(d->RootSplitter, NewRootSplitter);
- auto OldRoot = d->RootSplitter;
- d->RootSplitter = qobject_cast<CDockSplitter*>(NewRootSplitter);
- OldRoot->deleteLater();
- delete li;
-
- return true;
-}
-
-
-//============================================================================
-CDockSplitter* CDockContainerWidget::rootSplitter() const
-{
- return d->RootSplitter;
-}
-
-
-//============================================================================
-void CDockContainerWidget::createRootSplitter()
-{
- if (d->RootSplitter)
- {
- return;
- }
- d->RootSplitter = d->newSplitter(Qt::Horizontal);
- d->Layout->addWidget(d->RootSplitter, 1, 1); // Add it to the center - the 0 and 2 indexes are used for the SideTabBar widgets
-}
-
-
-//============================================================================
-void CDockContainerWidget::createSideTabBarWidgets()
-{
- if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
- {
- return;
- }
-
- {
- auto Area = SideBarLocation::SideBarLeft;
- d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area);
- d->Layout->addWidget(d->SideTabBarWidgets[Area], 1, 0);
- }
-
- {
- auto Area = SideBarLocation::SideBarRight;
- d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area);
- d->Layout->addWidget(d->SideTabBarWidgets[Area], 1, 2);
- }
-
- {
- auto Area = SideBarLocation::SideBarBottom;
- d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area);
- d->Layout->addWidget(d->SideTabBarWidgets[Area], 2, 1);
- }
-
- {
- auto Area = SideBarLocation::SideBarTop;
- d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area);
- d->Layout->addWidget(d->SideTabBarWidgets[Area], 0, 1);
- }
-}
-
-
-//============================================================================
-void CDockContainerWidget::dumpLayout()
-{
-#if (ADS_DEBUG_LEVEL > 0)
- qDebug("\n\nDumping layout --------------------------");
- std::cout << "\n\nDumping layout --------------------------" << std::endl;
- d->dumpRecursive(0, d->RootSplitter);
- qDebug("--------------------------\n\n");
- std::cout << "--------------------------\n\n" << std::endl;
-#endif
-}
-
-
-//============================================================================
-CDockAreaWidget* CDockContainerWidget::lastAddedDockAreaWidget(DockWidgetArea area) const
-{
- return d->LastAddedAreaCache[areaIdToIndex(area)];
-}
-
-
-//============================================================================
-bool CDockContainerWidget::hasTopLevelDockWidget() const
-{
- auto DockAreas = openedDockAreas();
- if (DockAreas.count() != 1)
- {
- return false;
- }
-
- return DockAreas[0]->openDockWidgetsCount() == 1;
-}
-
-
-//============================================================================
-CDockWidget* CDockContainerWidget::topLevelDockWidget() const
-{
- auto TopLevelDockArea = topLevelDockArea();
- if (!TopLevelDockArea)
- {
- return nullptr;
- }
-
- auto DockWidgets = TopLevelDockArea->openedDockWidgets();
- if (DockWidgets.count() != 1)
- {
- return nullptr;
- }
-
- return DockWidgets[0];
-
-}
-
-
-//============================================================================
-CDockAreaWidget* CDockContainerWidget::topLevelDockArea() const
-{
- auto DockAreas = openedDockAreas();
- if (DockAreas.count() != 1)
- {
- return nullptr;
- }
-
- return DockAreas[0];
-}
-
-
-//============================================================================
-QList<CDockWidget*> CDockContainerWidget::dockWidgets() const
-{
- QList<CDockWidget*> Result;
- for (const auto& DockArea : d->DockAreas)
- {
- if (!DockArea)
- {
- continue;
- }
- Result.append(DockArea->dockWidgets());
- }
-
- return Result;
-}
-
-//============================================================================
-void CDockContainerWidget::updateSplitterHandles(QSplitter* splitter)
-{
- d->updateSplitterHandles(splitter);
-}
-
-//============================================================================
-void CDockContainerWidget::registerAutoHideWidget(CAutoHideDockContainer* AutohideWidget)
-{
- d->AutoHideWidgets.append(AutohideWidget);
- Q_EMIT autoHideWidgetCreated(AutohideWidget);
- ADS_PRINT("d->AutoHideWidgets.count() " << d->AutoHideWidgets.count());
-}
-
-//============================================================================
-void CDockContainerWidget::removeAutoHideWidget(CAutoHideDockContainer* AutohideWidget)
-{
- d->AutoHideWidgets.removeAll(AutohideWidget);
-}
-
-//============================================================================
-CDockWidget::DockWidgetFeatures CDockContainerWidget::features() const
-{
- CDockWidget::DockWidgetFeatures Features(CDockWidget::AllDockWidgetFeatures);
- for (const auto& DockArea : d->DockAreas)
- {
- if (!DockArea)
- {
- continue;
- }
- Features &= DockArea->features();
- }
-
- return Features;
-}
-
-
-//============================================================================
-CFloatingDockContainer* CDockContainerWidget::floatingWidget() const
-{
- return internal::findParent<CFloatingDockContainer*>(this);
-}
-
-
-//============================================================================
-void CDockContainerWidget::closeOtherAreas(CDockAreaWidget* KeepOpenArea)
-{
- for (const auto& DockArea : d->DockAreas)
- {
- if (!DockArea || DockArea == KeepOpenArea)
- {
- continue;
- }
-
- if (!DockArea->features(BitwiseAnd).testFlag(CDockWidget::DockWidgetClosable))
- {
- continue;
- }
-
- // We do not close areas with widgets with custom close handling
- if (DockArea->features(BitwiseOr).testFlag(CDockWidget::CustomCloseHandling))
- {
- continue;
- }
-
- DockArea->closeArea();
- }
-}
-
-//============================================================================
-CAutoHideSideBar* CDockContainerWidget::autoHideSideBar(SideBarLocation area) const
-{
- return d->SideTabBarWidgets[area];
-}
-
-
-//============================================================================
-QRect CDockContainerWidget::contentRect() const
-{
- if (!d->RootSplitter)
- {
- return QRect();
- }
-
- 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;
- }
-}
-
-
-//===========================================================================
-QRect CDockContainerWidget::contentRectGlobal() const
-{
- if (!d->RootSplitter)
- {
- return QRect();
- }
- return internal::globalGeometry(d->RootSplitter);
-}
-
-
-//===========================================================================
-CDockManager* CDockContainerWidget::dockManager() const
-{
- return d->DockManager;
-}
-
-
-//===========================================================================
-void CDockContainerWidget::handleAutoHideWidgetEvent(QEvent* e, QWidget* w)
-{
- if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideShowOnMouseOver))
- {
- return;
- }
-
- if (dockManager()->isRestoringState())
- {
- return;
- }
-
- auto AutoHideTab = qobject_cast<CAutoHideTab*>(w);
- if (AutoHideTab)
- {
- switch (e->type())
- {
- case QEvent::Enter:
- if (!AutoHideTab->dockWidget()->isVisible())
- {
- d->DelayedAutoHideTab = AutoHideTab;
- d->DelayedAutoHideShow = true;
- d->DelayedAutoHideTimer.start();
- }
- else
- {
- d->DelayedAutoHideTimer.stop();
- }
- break;
-
- case QEvent::MouseButtonPress:
- d->DelayedAutoHideTimer.stop();
- break;
-
- case QEvent::Leave:
- if (AutoHideTab->dockWidget()->isVisible())
- {
- d->DelayedAutoHideTab = AutoHideTab;
- d->DelayedAutoHideShow = false;
- d->DelayedAutoHideTimer.start();
- }
- else
- {
- d->DelayedAutoHideTimer.stop();
- }
- break;
-
- default:
- break;
- }
- return;
- }
-
- auto AutoHideContainer = qobject_cast<CAutoHideDockContainer*>(w);
- if (AutoHideContainer)
- {
- switch (e->type())
- {
- case QEvent::Enter:
- case QEvent::Hide:
- d->DelayedAutoHideTimer.stop();
- break;
-
- case QEvent::Leave:
- if (AutoHideContainer->isVisible())
- {
- d->DelayedAutoHideTab = AutoHideContainer->autoHideTab();
- d->DelayedAutoHideShow = false;
- d->DelayedAutoHideTimer.start();
- }
- break;
-
- default:
- break;
- }
- return;
- return;
- }
-}
-} // namespace ads
-
-//---------------------------------------------------------------------------
-// EOF DockContainerWidget.cpp
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockContainerWidget.cpp
+/// \author Uwe Kindler
+/// \date 24.02.2017
+/// \brief Implementation of CDockContainerWidget class
+//============================================================================
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include "DockContainerWidget.h"
+
+#include <QEvent>
+#include <QList>
+#include <QGridLayout>
+#include <QPointer>
+#include <QVariant>
+#include <QDebug>
+#include <QXmlStreamWriter>
+#include <QAbstractButton>
+#include <QLabel>
+#include <QTimer>
+#include <QMetaObject>
+#include <QMetaType>
+#include <QMimeData>
+#include <QApplication>
+
+#include "DockManager.h"
+#include "DockAreaWidget.h"
+#include "DockWidget.h"
+#include "DockingStateReader.h"
+#include "FloatingDockContainer.h"
+#include "DockOverlay.h"
+#include "ads_globals.h"
+#include "DockSplitter.h"
+#include "DockWidgetTab.h"
+#include "DockAreaTitleBar.h"
+#include "DockFocusController.h"
+#include "AutoHideDockContainer.h"
+#include "AutoHideSideBar.h"
+#include "AutoHideTab.h"
+
+#include <functional>
+#include <iostream>
+
+#if QT_VERSION < 0x050900
+
+inline char toHexLower(uint value)
+{
+ return "0123456789abcdef"[value & 0xF];
+}
+
+QByteArray qByteArrayToHex(const QByteArray& src, char separator)
+{
+ if(src.size() == 0)
+ return QByteArray();
+
+ const int length = separator ? (src.size() * 3 - 1) : (src.size() * 2);
+ QByteArray hex(length, Qt::Uninitialized);
+ char *hexData = hex.data();
+ const uchar *data = reinterpret_cast<const uchar *>(src.data());
+ for (int i = 0, o = 0; i < src.size(); ++i) {
+ hexData[o++] = toHexLower(data[i] >> 4);
+ hexData[o++] = toHexLower(data[i] & 0xf);
+
+ if ((separator) && (o < length))
+ hexData[o++] = separator;
+ }
+ return hex;
+}
+#endif
+
+namespace ads
+{
+static unsigned int zOrderCounter = 0;
+
+enum eDropMode
+{
+ DropModeIntoArea,///< drop widget into a dock area
+ DropModeIntoContainer,///< drop into container
+ DropModeInvalid///< invalid mode - do not drop
+};
+
+/**
+ * Converts dock area ID to an index for array access
+ */
+static int areaIdToIndex(DockWidgetArea area)
+{
+ switch (area)
+ {
+ case LeftDockWidgetArea: return 0;
+ case RightDockWidgetArea: return 1;
+ case TopDockWidgetArea: return 2;
+ case BottomDockWidgetArea: return 3;
+ case CenterDockWidgetArea: return 4;
+ default:
+ return 4;
+ }
+}
+
+/**
+ * Helper function to ease insertion of dock area into splitter
+ */
+static void insertWidgetIntoSplitter(QSplitter* Splitter, QWidget* widget, bool Append)
+{
+ if (Append)
+ {
+ Splitter->addWidget(widget);
+ }
+ else
+ {
+ Splitter->insertWidget(0, widget);
+ }
+}
+
+/**
+ * Private data class of CDockContainerWidget class (pimpl)
+ */
+class DockContainerWidgetPrivate
+{
+public:
+ CDockContainerWidget* _this;
+ QPointer<CDockManager> DockManager;
+ unsigned int zOrderIndex = 0;
+ QList<QPointer<CDockAreaWidget>> DockAreas;
+ QList<CAutoHideDockContainer*> AutoHideWidgets;
+ QMap<SideBarLocation, CAutoHideSideBar*> SideTabBarWidgets;
+ QGridLayout* Layout = nullptr;
+ CDockSplitter* RootSplitter = nullptr;
+ bool isFloating = false;
+ CDockAreaWidget* LastAddedAreaCache[5];
+ int VisibleDockAreaCount = -1;
+ CDockAreaWidget* TopLevelDockArea = nullptr;
+ QTimer DelayedAutoHideTimer;
+ CAutoHideTab* DelayedAutoHideTab;
+ bool DelayedAutoHideShow = false;
+
+ /**
+ * Private data constructor
+ */
+ DockContainerWidgetPrivate(CDockContainerWidget* _public);
+
+ /**
+ * Adds dock widget to container and returns the dock area that contains
+ * the inserted dock widget
+ */
+ CDockAreaWidget* addDockWidgetToContainer(DockWidgetArea area, CDockWidget* Dockwidget);
+
+ /**
+ * Adds dock widget to a existing DockWidgetArea
+ */
+ CDockAreaWidget* addDockWidgetToDockArea(DockWidgetArea area, CDockWidget* Dockwidget,
+ CDockAreaWidget* TargetDockArea, int Index = -1);
+
+ /**
+ * Add dock area to this container
+ */
+ void addDockArea(CDockAreaWidget* NewDockWidget, DockWidgetArea area = CenterDockWidgetArea);
+
+ /**
+ * Drop floating widget into container
+ */
+ void dropIntoContainer(CFloatingDockContainer* FloatingWidget, DockWidgetArea area);
+
+ /**
+ * Drop floating widget into auto hide side bar
+ */
+ void dropIntoAutoHideSideBar(CFloatingDockContainer* FloatingWidget, DockWidgetArea area);
+
+ /**
+ * Shows the drop overlays for the given floating widget that is dragged
+ * over this container by a drag and drop operation (Wayland platform
+ * drag)
+ */
+ void updateDropOverlays(const QPoint& GlobalPos, CFloatingDockContainer* FloatingWidget);
+
+ /**
+ * 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, 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,
+ int TabIndex = 0);
+
+ /**
+ * Moves the dock widget or dock area given in Widget parameter to a
+ * a dock area in container
+ */
+ void moveToContainer(QWidget* Widgett, DockWidgetArea area);
+
+ /**
+ * Creates a new tab for a widget dropped into the center of a section
+ */
+ void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea, int TabIndex = 0);
+
+ /**
+ * Moves the dock widget or dock area given in Widget parameter to
+ * a auto hide sidebar area
+ */
+ void moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area, int TabIndex = TabDefaultInsertIndex);
+
+
+ /**
+ * Adds new dock areas to the internal dock area list
+ */
+ void addDockAreasToList(const QList<CDockAreaWidget*> NewDockAreas);
+
+ /**
+ * Wrapper function for DockAreas append, that ensures that dock area signals
+ * are properly connected to dock container slots
+ */
+ void appendDockAreas(const QList<CDockAreaWidget*> NewDockAreas);
+
+ /**
+ * Save state of child nodes
+ */
+ void saveChildNodesState(QXmlStreamWriter& Stream, QWidget* Widget);
+
+ /**
+ * Save state of auto hide widgets
+ */
+ void saveAutoHideWidgetsState(QXmlStreamWriter& Stream);
+
+ /**
+ * Restore state of child nodes.
+ * \param[in] Stream The data stream that contains the serialized state
+ * \param[out] CreatedWidget The widget created from parsed data or 0 if
+ * the parsed widget was an empty splitter
+ * \param[in] Testing If Testing is true, only the stream data is
+ * parsed without modifying anything.
+ */
+ bool restoreChildNodes(CDockingStateReader& Stream, QWidget*& CreatedWidget,
+ bool Testing);
+
+ /**
+ * Restores a splitter.
+ * \see restoreChildNodes() for details
+ */
+ bool restoreSplitter(CDockingStateReader& Stream, QWidget*& CreatedWidget,
+ bool Testing);
+
+ /**
+ * Restores a dock area.
+ * \see restoreChildNodes() for details
+ */
+ bool restoreDockArea(CDockingStateReader& Stream, QWidget*& CreatedWidget,
+ bool Testing);
+
+ /**
+ * Restores a auto hide side bar
+ */
+ bool restoreSideBar(CDockingStateReader& Stream, QWidget*& CreatedWidget,
+ bool Testing);
+
+ /**
+ * Helper function for recursive dumping of layout
+ */
+ void dumpRecursive(int level, QWidget* widget);
+
+ /**
+ * Calculate the drop mode from the given target position
+ */
+ eDropMode getDropMode(const QPoint& TargetPos);
+
+ /**
+ * Initializes the visible dock area count variable if it is not initialized
+ * yet
+ */
+ void initVisibleDockAreaCount()
+ {
+ if (VisibleDockAreaCount > -1)
+ {
+ return;
+ }
+
+ VisibleDockAreaCount = 0;
+ for (auto DockArea : DockAreas)
+ {
+ if (!DockArea)
+ {
+ continue;
+ }
+ VisibleDockAreaCount += (DockArea->isHidden() ? 0 : 1);
+ }
+ }
+
+ /**
+ * Access function for the visible dock area counter
+ */
+ int& visibleDockAreaCount()
+ {
+ // Lazy initialisation - we initialize the VisibleDockAreaCount variable
+ // on first use
+ initVisibleDockAreaCount();
+ return VisibleDockAreaCount;
+ }
+
+ /**
+ * The visible dock area count changes, if dock areas are remove, added or
+ * when its view is toggled
+ */
+ void onVisibleDockAreaCountChanged();
+
+ void emitDockAreasRemoved()
+ {
+ onVisibleDockAreaCountChanged();
+ Q_EMIT _this->dockAreasRemoved();
+ }
+
+ void emitDockAreasAdded()
+ {
+ onVisibleDockAreaCountChanged();
+ Q_EMIT _this->dockAreasAdded();
+ }
+
+ /**
+ * Helper function for creation of new splitter
+ */
+ CDockSplitter* newSplitter(Qt::Orientation orientation, QWidget* parent = nullptr)
+ {
+ CDockSplitter* s = new CDockSplitter(orientation, parent);
+ s->setOpaqueResize(CDockManager::testConfigFlag(CDockManager::OpaqueSplitterResize));
+ s->setChildrenCollapsible(false);
+ return s;
+ }
+
+ /**
+ * Ensures equal distribution of the sizes of a splitter if an dock widget
+ * is inserted from code
+ */
+ void adjustSplitterSizesOnInsertion(QSplitter* Splitter, qreal LastRatio = 1.0)
+ {
+ int AreaSize = (Splitter->orientation() == Qt::Horizontal) ? Splitter->width() : Splitter->height();
+ auto SplitterSizes = Splitter->sizes();
+
+ qreal TotRatio = SplitterSizes.size() - 1.0 + LastRatio;
+ for(int i = 0; i < SplitterSizes.size() -1; i++)
+ {
+ SplitterSizes[i] = AreaSize / TotRatio;
+ }
+ SplitterSizes.back() = AreaSize * LastRatio / TotRatio;
+ Splitter->setSizes(SplitterSizes);
+ }
+
+ /**
+ * This function forces the dock container widget to update handles of splitters
+ * based if a central widget exists.
+ */
+ void updateSplitterHandles(QSplitter* splitter);
+
+ /**
+ * If no central widget exists, the widgets resize with the container.
+ * If a central widget exists, the widgets surrounding the central widget
+ * do not resize its height or width.
+ */
+ bool widgetResizesWithContainer(QWidget* widget);
+
+// private slots: ------------------------------------------------------------
+ void onDockAreaViewToggled(bool Visible)
+ {
+ CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(_this->sender());
+ VisibleDockAreaCount += Visible ? 1 : -1;
+ onVisibleDockAreaCountChanged();
+ Q_EMIT _this->dockAreaViewToggled(DockArea, Visible);
+ }
+}; // struct DockContainerWidgetPrivate
+
+
+//============================================================================
+DockContainerWidgetPrivate::DockContainerWidgetPrivate(CDockContainerWidget* _public) :
+ _this(_public)
+{
+ std::fill(std::begin(LastAddedAreaCache),std::end(LastAddedAreaCache), nullptr);
+ DelayedAutoHideTimer.setSingleShot(true);
+ DelayedAutoHideTimer.setInterval(500);
+ QObject::connect(&DelayedAutoHideTimer, &QTimer::timeout, [this](){
+ auto GlobalPos = DelayedAutoHideTab->mapToGlobal(QPoint(0, 0));
+ qApp->sendEvent(DelayedAutoHideTab, new QMouseEvent(QEvent::MouseButtonPress,
+ QPoint(0, 0), GlobalPos, Qt::LeftButton, {Qt::LeftButton}, Qt::NoModifier));
+ });
+}
+
+
+//============================================================================
+eDropMode DockContainerWidgetPrivate::getDropMode(const QPoint& TargetPos)
+{
+ CDockAreaWidget* DockArea = _this->dockAreaAt(TargetPos);
+ auto dropArea = InvalidDockWidgetArea;
+ auto ContainerDropArea = DockManager->containerOverlay()->dropAreaUnderCursor();
+
+ if (DockArea)
+ {
+ auto dropOverlay = DockManager->dockAreaOverlay();
+ dropOverlay->setAllowedAreas(DockArea->allowedAreas());
+ dropArea = dropOverlay->showOverlay(DockArea);
+ if (ContainerDropArea != InvalidDockWidgetArea &&
+ ContainerDropArea != dropArea)
+ {
+ dropArea = InvalidDockWidgetArea;
+ }
+
+ if (dropArea != InvalidDockWidgetArea)
+ {
+ ADS_PRINT("Dock Area Drop Content: " << dropArea);
+ return DropModeIntoArea;
+ }
+ }
+
+ // mouse is over container
+ if (InvalidDockWidgetArea == dropArea)
+ {
+ dropArea = ContainerDropArea;
+ ADS_PRINT("Container Drop Content: " << dropArea);
+ if (dropArea != InvalidDockWidgetArea)
+ {
+ return DropModeIntoContainer;
+ }
+ }
+
+ return DropModeInvalid;
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::onVisibleDockAreaCountChanged()
+{
+ auto TopLevelDockArea = _this->topLevelDockArea();
+
+ if (TopLevelDockArea)
+ {
+ this->TopLevelDockArea = TopLevelDockArea;
+ TopLevelDockArea->updateTitleBarButtonVisibility(true);
+ }
+ else if (this->TopLevelDockArea)
+ {
+ this->TopLevelDockArea->updateTitleBarButtonVisibility(false);
+ this->TopLevelDockArea = nullptr;
+ }
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* FloatingWidget,
+ DockWidgetArea area)
+{
+ auto InsertParam = internal::dockAreaInsertParameters(area);
+ CDockContainerWidget* FloatingDockContainer = FloatingWidget->dockContainer();
+ auto NewDockAreas = FloatingDockContainer->findChildren<CDockAreaWidget*>(
+ QString(), Qt::FindChildrenRecursively);
+ auto Splitter = RootSplitter;
+
+ if (DockAreas.count() <= 1)
+ {
+ Splitter->setOrientation(InsertParam.orientation());
+ }
+ else if (Splitter->orientation() != InsertParam.orientation())
+ {
+ auto NewSplitter = newSplitter(InsertParam.orientation());
+ QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
+ NewSplitter->addWidget(Splitter);
+ updateSplitterHandles(NewSplitter);
+ Splitter = NewSplitter;
+ delete li;
+ }
+
+ // Now we can insert the floating widget content into this container
+ auto FloatingSplitter = FloatingDockContainer->rootSplitter();
+ if (FloatingSplitter->count() == 1)
+ {
+ insertWidgetIntoSplitter(Splitter, FloatingSplitter->widget(0), InsertParam.append());
+ updateSplitterHandles(Splitter);
+ }
+ else if (FloatingSplitter->orientation() == InsertParam.orientation())
+ {
+ int InsertIndex = InsertParam.append() ? Splitter->count() : 0;
+ while (FloatingSplitter->count())
+ {
+ Splitter->insertWidget(InsertIndex++, FloatingSplitter->widget(0));
+ updateSplitterHandles(Splitter);
+ }
+ }
+ else
+ {
+ insertWidgetIntoSplitter(Splitter, FloatingSplitter, InsertParam.append());
+ }
+
+ RootSplitter = Splitter;
+ addDockAreasToList(NewDockAreas);
+
+ // If we dropped the floating widget into the main dock container that does
+ // not contain any dock widgets, then splitter is invisible and we need to
+ // show it to display the docked widgets
+ if (!Splitter->isVisible())
+ {
+ Splitter->show();
+ }
+ _this->dumpLayout();
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::updateDropOverlays(const QPoint& GlobalPos,
+ CFloatingDockContainer* FloatingWidget)
+{
+ if (!DockManager)
+ {
+ return;
+ }
+
+ // This container received the drag move event, so it is the drop target -
+ // unlike the mouse tracked dragging, there is no need to search the
+ // container under the cursor
+ bool ContentPinnable = FloatingWidget->dockContainer()->features().testFlag(
+ CDockWidget::DockWidgetPinnable);
+ CDockContainerWidget::showDropOverlays(DockManager, _this, GlobalPos, ContentPinnable);
+}
+
+
+//============================================================================
+void CDockContainerWidget::showDropOverlays(CDockManager* DockManager,
+ CDockContainerWidget* TopContainer, const QPoint& GlobalPos,
+ bool ContentPinnable)
+{
+ auto ContainerOverlay = DockManager->containerOverlay();
+ auto DockAreaOverlay = DockManager->dockAreaOverlay();
+ int VisibleDockAreas = TopContainer->visibleDockAreaCount();
+ 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 (ContentPinnable)
+ {
+ AllowedContainerAreas |= AutoHideDockAreas;
+ }
+
+ ContainerOverlay->setAllowedAreas(AllowedContainerAreas);
+
+ DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer, GlobalPos);
+ ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea);
+ if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0)
+ {
+ DockAreaOverlay->enableDropPreview(true);
+ DockAreaOverlay->setAllowedAreas(
+ (VisibleDockAreas == 1) ? NoDockWidgetArea : DockArea->allowedAreas());
+ DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea, GlobalPos);
+
+ // A CenterDockWidgetArea for the dockAreaOverlay() indicates that
+ // the mouse is in the title bar. If the ContainerArea is valid
+ // then we ignore the dock area of the dockAreaOverlay() and disable
+ // the drop preview
+ if ((Area == CenterDockWidgetArea)
+ && (ContainerArea != InvalidDockWidgetArea))
+ {
+ DockAreaOverlay->enableDropPreview(false);
+ ContainerOverlay->enableDropPreview(true);
+ }
+ else
+ {
+ ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area);
+ }
+ }
+ else
+ {
+ DockAreaOverlay->hideOverlay();
+ }
+}
+
+
+//============================================================================
+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, 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
+ // dock widget in the drop area.
+ if (TopLevelDockArea)
+ {
+ NewCurrentIndex = TopLevelDockArea->currentIndex();
+ }
+
+ for (int i = 0; i < NewDockWidgets.count(); ++i)
+ {
+ CDockWidget* DockWidget = NewDockWidgets[i];
+ 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.
+ if (NewCurrentIndex < 0 && !DockWidget->isClosed())
+ {
+ NewCurrentIndex = i;
+ }
+ }
+ TargetArea->setCurrentIndex(NewCurrentIndex + TabIndex);
+ TargetArea->updateTitleBarVisibility();
+ return;
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* FloatingWidget,
+ 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, TabIndex);
+ return;
+ }
+
+ CDockContainerWidget* FloatingContainer = FloatingWidget->dockContainer();
+ auto InsertParam = internal::dockAreaInsertParameters(area);
+ auto NewDockAreas = FloatingContainer->findChildren<CDockAreaWidget*>(
+ QString(), Qt::FindChildrenRecursively);
+ auto TargetAreaSplitter = TargetArea->parentSplitter();
+ int AreaIndex = TargetAreaSplitter->indexOf(TargetArea);
+ auto FloatingSplitter = FloatingContainer->rootSplitter();
+ if (TargetAreaSplitter->orientation() == InsertParam.orientation())
+ {
+ auto Sizes = TargetAreaSplitter->sizes();
+ int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
+ bool AdjustSplitterSizes = true;
+ if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1)
+ {
+ TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), FloatingSplitter);
+ updateSplitterHandles(TargetAreaSplitter);
+ }
+ else
+ {
+ AdjustSplitterSizes = (FloatingSplitter->count() == 1);
+ int InsertIndex = AreaIndex + InsertParam.insertOffset();
+ while (FloatingSplitter->count())
+ {
+ TargetAreaSplitter->insertWidget(InsertIndex++, FloatingSplitter->widget(0));
+ updateSplitterHandles(TargetAreaSplitter);
+ }
+ }
+
+ if (AdjustSplitterSizes)
+ {
+ int Size = (TargetAreaSize - TargetAreaSplitter->handleWidth()) / 2;
+ Sizes[AreaIndex] = Size;
+ Sizes.insert(AreaIndex, Size);
+ TargetAreaSplitter->setSizes(Sizes);
+ }
+ }
+ else
+ {
+ QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
+ int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
+ bool AdjustSplitterSizes = true;
+ if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1)
+ {
+ NewSplitter->addWidget(FloatingSplitter);
+ updateSplitterHandles(NewSplitter);
+ }
+ else
+ {
+ AdjustSplitterSizes = (FloatingSplitter->count() == 1);
+ while (FloatingSplitter->count())
+ {
+ NewSplitter->addWidget(FloatingSplitter->widget(0));
+ updateSplitterHandles(NewSplitter);
+ }
+ }
+
+ // Save the sizes before insertion and restore it later to prevent
+ // shrinking of existing area
+ auto Sizes = TargetAreaSplitter->sizes();
+ insertWidgetIntoSplitter(NewSplitter, TargetArea, !InsertParam.append());
+ updateSplitterHandles(NewSplitter);
+ if (AdjustSplitterSizes)
+ {
+ int Size = TargetAreaSize / 2;
+ NewSplitter->setSizes({Size, Size});
+ }
+ TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter);
+ TargetAreaSplitter->setSizes(Sizes);
+ updateSplitterHandles(TargetAreaSplitter);
+ }
+
+ addDockAreasToList(NewDockAreas);
+ _this->dumpLayout();
+}
+
+
+//============================================================================
+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();
+ if (OldDockArea == TargetArea)
+ {
+ return;
+ }
+
+ if (OldDockArea)
+ {
+ OldDockArea->removeDockWidget(DroppedDockWidget);
+ }
+ TargetArea->insertDockWidget(TabIndex, DroppedDockWidget, true);
+ }
+ else
+ {
+ QList<CDockWidget*> NewDockWidgets = DroppedArea->dockWidgets();
+ int NewCurrentIndex = DroppedArea->currentIndex();
+ for (int i = 0; i < NewDockWidgets.count(); ++i)
+ {
+ CDockWidget* DockWidget = NewDockWidgets[i];
+ TargetArea->insertDockWidget(TabIndex + i, DockWidget, false);
+ }
+ TargetArea->setCurrentIndex(TabIndex + NewCurrentIndex);
+ DroppedArea->dockContainer()->removeDockArea(DroppedArea);
+ DroppedArea->deleteLater();
+ }
+
+ TargetArea->updateTitleBarVisibility();
+ return;
+}
+
+
+//============================================================================
+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, TabIndex);
+ return;
+ }
+
+
+ CDockWidget* DroppedDockWidget = qobject_cast<CDockWidget*>(Widget);
+ CDockAreaWidget* DroppedDockArea = qobject_cast<CDockAreaWidget*>(Widget);
+ CDockAreaWidget* NewDockArea;
+ if (DroppedDockWidget)
+ {
+ NewDockArea = new CDockAreaWidget(DockManager, _this);
+ CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget();
+ if (OldDockArea)
+ {
+ OldDockArea->removeDockWidget(DroppedDockWidget);
+ }
+ NewDockArea->addDockWidget(DroppedDockWidget);
+ }
+ else
+ {
+ DroppedDockArea->dockContainer()->removeDockArea(DroppedDockArea);
+ NewDockArea = DroppedDockArea;
+ }
+
+ auto InsertParam = internal::dockAreaInsertParameters(area);
+ auto TargetAreaSplitter = TargetArea->parentSplitter();
+ int AreaIndex = TargetAreaSplitter->indexOf(TargetArea);
+ auto Sizes = TargetAreaSplitter->sizes();
+ if (TargetAreaSplitter->orientation() == InsertParam.orientation())
+ {
+ int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
+ TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), NewDockArea);
+ updateSplitterHandles(TargetAreaSplitter);
+ int Size = (TargetAreaSize - TargetAreaSplitter->handleWidth()) / 2;
+ Sizes[AreaIndex] = Size;
+ Sizes.insert(AreaIndex, Size);
+ }
+ else
+ {
+ int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
+ QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
+ NewSplitter->addWidget(TargetArea);
+ insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append());
+ updateSplitterHandles(NewSplitter);
+ int Size = TargetAreaSize / 2;
+ NewSplitter->setSizes({Size, Size});
+ TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter);
+ updateSplitterHandles(TargetAreaSplitter);
+ }
+ TargetAreaSplitter->setSizes(Sizes);
+
+ addDockAreasToList({NewDockArea});
+}
+
+
+//============================================================================
+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 )
+{
+ if (!DockManager->centralWidget() || !splitter)
+ {
+ return;
+ }
+
+ for (int i = 0; i < splitter->count(); ++i)
+ {
+ splitter->setStretchFactor(i, widgetResizesWithContainer(splitter->widget(i)) ? 1 : 0);
+ }
+}
+
+
+//============================================================================
+bool DockContainerWidgetPrivate::widgetResizesWithContainer(QWidget* widget)
+{
+ if (!DockManager->centralWidget())
+ {
+ return true;
+ }
+
+ auto Area = qobject_cast<CDockAreaWidget*>(widget);
+ if(Area)
+ {
+ return Area->isCentralWidgetArea();
+ }
+
+ auto innerSplitter = qobject_cast<CDockSplitter*>(widget);
+ if (innerSplitter)
+ {
+ return innerSplitter->isResizingWithContainer();
+ }
+
+ return false;
+}
+
+
+
+//============================================================================
+void DockContainerWidgetPrivate::moveToContainer(QWidget* Widget, DockWidgetArea area)
+{
+ CDockWidget* DroppedDockWidget = qobject_cast<CDockWidget*>(Widget);
+ CDockAreaWidget* DroppedDockArea = qobject_cast<CDockAreaWidget*>(Widget);
+ CDockAreaWidget* NewDockArea;
+
+ if (DroppedDockWidget)
+ {
+ NewDockArea = new CDockAreaWidget(DockManager, _this);
+ CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget();
+ if (OldDockArea)
+ {
+ OldDockArea->removeDockWidget(DroppedDockWidget);
+ }
+ NewDockArea->addDockWidget(DroppedDockWidget);
+ }
+ else
+ {
+ // We check, if we insert the dropped widget into the same place that
+ // it already has and do nothing, if it is the same place. It would
+ // also work without this check, but it looks nicer with the check
+ // because there will be no layout updates
+ auto Splitter = DroppedDockArea->parentSplitter();
+ auto InsertParam = internal::dockAreaInsertParameters(area);
+ if (Splitter == RootSplitter && InsertParam.orientation() == Splitter->orientation())
+ {
+ if (InsertParam.append() && Splitter->lastWidget() == DroppedDockArea)
+ {
+ return;
+ }
+ else if (!InsertParam.append() && Splitter->firstWidget() == DroppedDockArea)
+ {
+ return;
+ }
+ }
+ DroppedDockArea->dockContainer()->removeDockArea(DroppedDockArea);
+ NewDockArea = DroppedDockArea;
+ }
+
+ addDockArea(NewDockArea, area);
+ LastAddedAreaCache[areaIdToIndex(area)] = NewDockArea;
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::addDockAreasToList(const QList<CDockAreaWidget*> NewDockAreas)
+{
+ int CountBefore = DockAreas.count();
+ int NewAreaCount = NewDockAreas.count();
+ appendDockAreas(NewDockAreas);
+ // If the user dropped a floating widget that contains only one single
+ // visible dock area, then its title bar button TitleBarButtonUndock is
+ // likely hidden. We need to ensure, that it is visible
+ for (auto DockArea : NewDockAreas)
+ {
+ DockArea->titleBarButton(TitleBarButtonClose)->setVisible(true);
+ DockArea->titleBarButton(TitleBarButtonAutoHide)->setVisible(true);
+ DockArea->titleBarButton(TitleBarButtonUndock)->setVisible(true);
+ }
+
+ // We need to ensure, that the dock area title bar is visible. The title bar
+ // is invisible, if the dock are is a single dock area in a floating widget.
+ if (1 == CountBefore)
+ {
+ DockAreas.at(0)->updateTitleBarVisibility();
+ }
+
+ if (1 == NewAreaCount)
+ {
+ DockAreas.last()->updateTitleBarVisibility();
+ }
+
+ emitDockAreasAdded();
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::appendDockAreas(const QList<CDockAreaWidget*> NewDockAreas)
+{
+ for (auto *newDockArea : NewDockAreas)
+ {
+ DockAreas.append(newDockArea);
+ }
+ for (auto DockArea : NewDockAreas)
+ {
+ QObject::connect(DockArea,
+ &CDockAreaWidget::viewToggled,
+ _this,
+ std::bind(&DockContainerWidgetPrivate::onDockAreaViewToggled, this, std::placeholders::_1));
+ }
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::saveChildNodesState(QXmlStreamWriter& s, QWidget* Widget)
+{
+ QSplitter* Splitter = qobject_cast<QSplitter*>(Widget);
+ if (Splitter)
+ {
+ s.writeStartElement("Splitter");
+ s.writeAttribute("Orientation", (Splitter->orientation() == Qt::Horizontal) ? "|" : "-");
+ s.writeAttribute("Count", QString::number(Splitter->count()));
+ ADS_PRINT("NodeSplitter orient: " << Splitter->orientation()
+ << " WidgetCont: " << Splitter->count());
+ for (int i = 0; i < Splitter->count(); ++i)
+ {
+ saveChildNodesState(s, Splitter->widget(i));
+ }
+
+ s.writeStartElement("Sizes");
+ for (auto Size : Splitter->sizes())
+ {
+ s.writeCharacters(QString::number(Size) + " ");
+ }
+ s.writeEndElement();
+ s.writeEndElement();
+ }
+ else
+ {
+ CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(Widget);
+ if (DockArea)
+ {
+ DockArea->saveState(s);
+ }
+ }
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::saveAutoHideWidgetsState(QXmlStreamWriter& s)
+{
+ for (const auto sideTabBar : SideTabBarWidgets.values())
+ {
+ if (!sideTabBar->count())
+ {
+ continue;
+ }
+
+ sideTabBar->saveState(s);
+ }
+}
+
+
+//============================================================================
+bool DockContainerWidgetPrivate::restoreSplitter(CDockingStateReader& s,
+ QWidget*& CreatedWidget, bool Testing)
+{
+ bool Ok;
+ QString OrientationStr = s.attributes().value("Orientation").toString();
+
+ // Check if the orientation string is right
+ if (!OrientationStr.startsWith("|") && !OrientationStr.startsWith("-"))
+ {
+ return false;
+ }
+
+ // The "|" shall indicate a vertical splitter handle which in turn means
+ // a Horizontal orientation of the splitter layout.
+ bool HorizontalSplitter = OrientationStr.startsWith("|");
+ // In version 0 we had a small bug. The "|" indicated a vertical orientation,
+ // but this is wrong, because only the splitter handle is vertical, the
+ // layout of the splitter is a horizontal layout. We fix this here
+ if (s.fileVersion() == 0)
+ {
+ HorizontalSplitter = !HorizontalSplitter;
+ }
+
+ int Orientation = HorizontalSplitter ? Qt::Horizontal : Qt::Vertical;
+ int WidgetCount = s.attributes().value("Count").toInt(&Ok);
+ if (!Ok)
+ {
+ return false;
+ }
+ ADS_PRINT("Restore NodeSplitter Orientation: " << Orientation <<
+ " WidgetCount: " << WidgetCount);
+ QSplitter* Splitter = nullptr;
+ if (!Testing)
+ {
+ Splitter = newSplitter(static_cast<Qt::Orientation>(Orientation));
+ }
+ bool Visible = false;
+ QList<int> Sizes;
+ while (s.readNextStartElement())
+ {
+ QWidget* ChildNode = nullptr;
+ bool Result = true;
+ if (s.name() == QLatin1String("Splitter"))
+ {
+ Result = restoreSplitter(s, ChildNode, Testing);
+ }
+ else if (s.name() == QLatin1String("Area"))
+ {
+ Result = restoreDockArea(s, ChildNode, Testing);
+ }
+ else if (s.name() == QLatin1String("Sizes"))
+ {
+ QString sSizes = s.readElementText().trimmed();
+ ADS_PRINT("Sizes: " << sSizes);
+ QTextStream TextStream(&sSizes);
+ while (!TextStream.atEnd())
+ {
+ int value;
+ TextStream >> value;
+ Sizes.append(value);
+ }
+ }
+ else
+ {
+ s.skipCurrentElement();
+ }
+
+ if (!Result)
+ {
+ return false;
+ }
+
+ if (Testing || !ChildNode)
+ {
+ continue;
+ }
+
+ ADS_PRINT("ChildNode isVisible " << ChildNode->isVisible()
+ << " isVisibleTo " << ChildNode->isVisibleTo(Splitter));
+ Splitter->addWidget(ChildNode);
+ Visible |= ChildNode->isVisibleTo(Splitter);
+ }
+ if(!Testing)
+ {
+ updateSplitterHandles(Splitter);
+ }
+
+ if (Sizes.count() != WidgetCount)
+ {
+ return false;
+ }
+
+ if (!Testing)
+ {
+ if (!Splitter->count())
+ {
+ delete Splitter;
+ Splitter = nullptr;
+ }
+ else
+ {
+ Splitter->setSizes(Sizes);
+ Splitter->setVisible(Visible);
+ }
+ CreatedWidget = Splitter;
+ }
+ else
+ {
+ CreatedWidget = nullptr;
+ }
+
+ return true;
+}
+
+
+//============================================================================
+bool DockContainerWidgetPrivate::restoreDockArea(CDockingStateReader& s,
+ QWidget*& CreatedWidget, bool Testing)
+{
+ CDockAreaWidget* DockArea = nullptr;
+ auto Result = CDockAreaWidget::restoreState(s, DockArea, Testing, _this);
+ if (Result && DockArea)
+ {
+ appendDockAreas({DockArea});
+ }
+ CreatedWidget = DockArea;
+ return Result;
+}
+
+
+//============================================================================
+bool DockContainerWidgetPrivate::restoreSideBar(CDockingStateReader& s,
+ QWidget*& CreatedWidget, bool Testing)
+{
+ Q_UNUSED(CreatedWidget)
+ // Simply ignore side bar auto hide widgets from saved state if
+ // auto hide support is disabled
+ if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
+ {
+ return true;
+ }
+
+ bool Ok;
+ auto Area = (ads::SideBarLocation)s.attributes().value("Area").toInt(&Ok);
+ if (!Ok)
+ {
+ return false;
+ }
+
+ while (s.readNextStartElement())
+ {
+ if (s.name() != QLatin1String("Widget"))
+ {
+ continue;
+ }
+
+ auto Name = s.attributes().value("Name");
+ if (Name.isEmpty())
+ {
+ return false;
+ }
+
+ bool Ok;
+ bool Closed = s.attributes().value("Closed").toInt(&Ok);
+ if (!Ok)
+ {
+ return false;
+ }
+
+ int Size = s.attributes().value("Size").toInt(&Ok);
+ if (!Ok)
+ {
+ return false;
+ }
+
+ s.skipCurrentElement();
+ CDockWidget* DockWidget = DockManager->findDockWidget(Name.toString());
+ if (!DockWidget || Testing)
+ {
+ continue;
+ }
+
+ auto SideBar = _this->autoHideSideBar(Area);
+ CAutoHideDockContainer* AutoHideContainer;
+ if (DockWidget->isAutoHide())
+ {
+ AutoHideContainer = DockWidget->autoHideDockContainer();
+ if (AutoHideContainer->autoHideSideBar() != SideBar)
+ {
+ SideBar->addAutoHideWidget(AutoHideContainer);
+ }
+ }
+ else
+ {
+ AutoHideContainer = SideBar->insertDockWidget(-1, DockWidget);
+ }
+ AutoHideContainer->setSize(Size);
+ DockWidget->setProperty(internal::ClosedProperty, Closed);
+ DockWidget->setProperty(internal::DirtyProperty, false);
+ }
+
+ return true;
+}
+
+
+//============================================================================
+bool DockContainerWidgetPrivate::restoreChildNodes(CDockingStateReader& s,
+ QWidget*& CreatedWidget, bool Testing)
+{
+ bool Result = true;
+ while (s.readNextStartElement())
+ {
+ if (s.name() == QLatin1String("Splitter"))
+ {
+ Result = restoreSplitter(s, CreatedWidget, Testing);
+ ADS_PRINT("Splitter");
+ }
+ else if (s.name() == QLatin1String("Area"))
+ {
+ Result = restoreDockArea(s, CreatedWidget, Testing);
+ ADS_PRINT("DockAreaWidget");
+ }
+ else if (s.name() == QLatin1String("SideBar"))
+ {
+ Result = restoreSideBar(s, CreatedWidget, Testing);
+ ADS_PRINT("SideBar");
+ }
+ else
+ {
+ s.skipCurrentElement();
+ ADS_PRINT("Unknown element");
+ }
+ }
+
+ return Result;
+}
+
+
+//============================================================================
+CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToContainer(DockWidgetArea area,
+ CDockWidget* Dockwidget)
+{
+ CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this);
+ NewDockArea->addDockWidget(Dockwidget);
+ addDockArea(NewDockArea, area);
+ NewDockArea->updateTitleBarVisibility();
+ LastAddedAreaCache[areaIdToIndex(area)] = NewDockArea;
+ return NewDockArea;
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockWidgetArea area)
+{
+ auto InsertParam = internal::dockAreaInsertParameters(area);
+ // As long as we have only one dock area in the splitter we can adjust
+ // its orientation
+ if (DockAreas.count() <= 1)
+ {
+ RootSplitter->setOrientation(InsertParam.orientation());
+ }
+
+ QSplitter* Splitter = RootSplitter;
+ if (Splitter->orientation() == InsertParam.orientation())
+ {
+ insertWidgetIntoSplitter(Splitter, NewDockArea, InsertParam.append());
+ updateSplitterHandles(Splitter);
+ if (Splitter->isHidden())
+ {
+ Splitter->show();
+ }
+ }
+ else
+ {
+ auto NewSplitter = newSplitter(InsertParam.orientation());
+ if (InsertParam.append())
+ {
+ QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
+ NewSplitter->addWidget(Splitter);
+ NewSplitter->addWidget(NewDockArea);
+ updateSplitterHandles(NewSplitter);
+ delete li;
+ }
+ else
+ {
+ NewSplitter->addWidget(NewDockArea);
+ QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
+ NewSplitter->addWidget(Splitter);
+ updateSplitterHandles(NewSplitter);
+ delete li;
+ }
+ RootSplitter = NewSplitter;
+ }
+
+ addDockAreasToList({NewDockArea});
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget)
+{
+#if defined(QT_DEBUG)
+ QSplitter* Splitter = qobject_cast<QSplitter*>(widget);
+ QByteArray buf;
+ buf.fill(' ', level * 4);
+ if (Splitter)
+ {
+#ifdef ADS_DEBUG_PRINT
+ qDebug("%sSplitter %s v: %s c: %s",
+ (const char*)buf,
+ (Splitter->orientation() == Qt::Vertical) ? "--" : "|",
+ Splitter->isHidden() ? " " : "v",
+ QString::number(Splitter->count()).toStdString().c_str());
+ std::cout << (const char*)buf << "Splitter "
+ << ((Splitter->orientation() == Qt::Vertical) ? "--" : "|") << " "
+ << (Splitter->isHidden() ? " " : "v") << " "
+ << QString::number(Splitter->count()).toStdString() << std::endl;
+#endif
+ for (int i = 0; i < Splitter->count(); ++i)
+ {
+ dumpRecursive(level + 1, Splitter->widget(i));
+ }
+ }
+ else
+ {
+ CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(widget);
+ if (!DockArea)
+ {
+ return;
+ }
+#ifdef ADS_DEBUG_PRINT
+ qDebug("%sDockArea", (const char*)buf);
+ std::cout << (const char*)buf
+ << (DockArea->isHidden() ? " " : "v")
+ << (DockArea->openDockWidgetsCount() > 0 ? " " : "c")
+ << " DockArea " << "[hs: " << DockArea->sizePolicy().horizontalStretch() << ", vs: " << DockArea->sizePolicy().verticalStretch() << "]" << std::endl;
+ buf.fill(' ', (level + 1) * 4);
+ for (int i = 0; i < DockArea->dockWidgetsCount(); ++i)
+ {
+ std::cout << (const char*)buf << (i == DockArea->currentIndex() ? "*" : " ");
+ CDockWidget* DockWidget = DockArea->dockWidget(i);
+ std::cout << (DockWidget->isHidden() ? " " : "v");
+ std::cout << (DockWidget->isClosed() ? "c" : " ") << " ";
+ std::cout << DockWidget->windowTitle().toStdString() << std::endl;
+ }
+#endif
+ }
+#else
+ Q_UNUSED(level);
+ Q_UNUSED(widget);
+#endif
+}
+
+
+//============================================================================
+CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetArea area,
+ CDockWidget* Dockwidget, CDockAreaWidget* TargetDockArea, int Index)
+{
+ if (CenterDockWidgetArea == area)
+ {
+ TargetDockArea->insertDockWidget(Index, Dockwidget);
+ TargetDockArea->updateTitleBarVisibility();
+ return TargetDockArea;
+ }
+
+ CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this);
+ NewDockArea->addDockWidget(Dockwidget);
+ auto InsertParam = internal::dockAreaInsertParameters(area);
+
+ auto TargetAreaSplitter = TargetDockArea->parentSplitter();
+ int index = TargetAreaSplitter ->indexOf(TargetDockArea);
+ if (TargetAreaSplitter->orientation() == InsertParam.orientation())
+ {
+ ADS_PRINT("TargetAreaSplitter->orientation() == InsertParam.orientation()");
+ TargetAreaSplitter->insertWidget(index + InsertParam.insertOffset(), NewDockArea);
+ updateSplitterHandles(TargetAreaSplitter);
+ // do nothing, if flag is not enabled
+ if (CDockManager::testConfigFlag(CDockManager::EqualSplitOnInsertion))
+ {
+ adjustSplitterSizesOnInsertion(TargetAreaSplitter);
+ }
+ }
+ else
+ {
+ ADS_PRINT("TargetAreaSplitter->orientation() != InsertParam.orientation()");
+ auto TargetAreaSizes = TargetAreaSplitter->sizes();
+ auto NewSplitter = newSplitter(InsertParam.orientation());
+ NewSplitter->addWidget(TargetDockArea);
+
+ insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append());
+ updateSplitterHandles(NewSplitter);
+ TargetAreaSplitter->insertWidget(index, NewSplitter);
+ updateSplitterHandles(TargetAreaSplitter);
+ if (CDockManager::testConfigFlag(CDockManager::EqualSplitOnInsertion))
+ {
+ TargetAreaSplitter->setSizes(TargetAreaSizes);
+ adjustSplitterSizesOnInsertion(NewSplitter);
+ }
+ }
+
+ addDockAreasToList({NewDockArea});
+ return NewDockArea;
+}
+
+
+//============================================================================
+CDockContainerWidget::CDockContainerWidget(CDockManager* DockManager, QWidget *parent) :
+ QFrame(parent),
+ d(new DockContainerWidgetPrivate(this))
+{
+ d->DockManager = DockManager;
+ d->isFloating = floatingWidget() != nullptr;
+
+ d->Layout = new QGridLayout();
+ d->Layout->setContentsMargins(0, 0, 0, 0);
+ d->Layout->setSpacing(0);
+ d->Layout->setColumnStretch(1, 1);
+ d->Layout->setRowStretch(1, 1);
+ setLayout(d->Layout);
+
+ // The function d->newSplitter() accesses the config flags from dock
+ // manager which in turn requires a properly constructed dock manager.
+ // If this dock container is the dock manager, then it is not properly
+ // constructed yet because this base class constructor is called before
+ // the constructor of the DockManager private class
+ if (DockManager != this)
+ {
+ d->DockManager->registerDockContainer(this);
+ createRootSplitter();
+ createSideTabBarWidgets();
+ }
+
+ // On Wayland, floating widgets are docked via drag and drop events
+ // because the mouse tracked dragging that is used on the other platforms
+ // requires the global cursor position, which Wayland does not provide
+ if (internal::isWayland())
+ {
+ setAcceptDrops(true);
+ }
+}
+
+
+//============================================================================
+CDockContainerWidget::~CDockContainerWidget()
+{
+ if (d->DockManager)
+ {
+ d->DockManager->removeDockContainer(this);
+ }
+
+ delete d;
+}
+
+
+//============================================================================
+CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
+ CDockAreaWidget* DockAreaWidget, int Index)
+{
+ auto TopLevelDockWidget = topLevelDockWidget();
+ CDockAreaWidget* OldDockArea = Dockwidget->dockAreaWidget();
+ if (OldDockArea)
+ {
+ OldDockArea->removeDockWidget(Dockwidget);
+ }
+
+ Dockwidget->setDockManager(d->DockManager);
+ CDockAreaWidget* DockArea;
+ if (DockAreaWidget)
+ {
+ DockArea = d->addDockWidgetToDockArea(area, Dockwidget, DockAreaWidget, Index);
+ }
+ else
+ {
+ DockArea = d->addDockWidgetToContainer(area, Dockwidget);
+ }
+
+ if (TopLevelDockWidget)
+ {
+ auto NewTopLevelDockWidget = topLevelDockWidget();
+ // If the container contained only one visible dock widget, the we need
+ // to emit a top level event for this widget because it is not the one and
+ // only visible docked widget anymore
+ if (!NewTopLevelDockWidget)
+ {
+ CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidget, false);
+ }
+ }
+ return DockArea;
+}
+
+
+//============================================================================
+CAutoHideDockContainer* CDockContainerWidget::createAndSetupAutoHideContainer(
+ SideBarLocation area, CDockWidget* DockWidget, int TabIndex)
+{
+ if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
+ {
+ Q_ASSERT_X(false, "CDockContainerWidget::createAndInitializeDockWidgetOverlayContainer",
+ "Requested area does not exist in config");
+ return nullptr;
+ }
+ if (d->DockManager != DockWidget->dockManager())
+ {
+ DockWidget->setDockManager(d->DockManager); // Auto hide Dock Container needs a valid dock manager
+ }
+
+ return autoHideSideBar(area)->insertDockWidget(TabIndex, DockWidget);
+}
+
+
+//============================================================================
+void CDockContainerWidget::removeDockWidget(CDockWidget* Dockwidget)
+{
+ CDockAreaWidget* Area = Dockwidget->dockAreaWidget();
+ if (Area)
+ {
+ Area->removeDockWidget(Dockwidget);
+ }
+}
+
+//============================================================================
+unsigned int CDockContainerWidget::zOrderIndex() const
+{
+ return d->zOrderIndex;
+}
+
+
+//============================================================================
+bool CDockContainerWidget::isInFrontOf(CDockContainerWidget* Other) const
+{
+ return this->zOrderIndex() > Other->zOrderIndex();
+}
+
+
+//============================================================================
+bool CDockContainerWidget::event(QEvent *e)
+{
+ bool Result = QWidget::event(e);
+ if (e->type() == QEvent::WindowActivate)
+ {
+ d->zOrderIndex = ++zOrderCounter;
+ }
+ else if (e->type() == QEvent::Show && !d->zOrderIndex)
+ {
+ d->zOrderIndex = ++zOrderCounter;
+ }
+
+ return Result;
+}
+
+
+//============================================================================
+/**
+ * Returns the drop position of the given drop event in global coordinates
+ */
+static QPoint dropEventGlobalPos(QDropEvent* e, QWidget* Widget)
+{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ return Widget->mapToGlobal(e->position().toPoint());
+#else
+ return Widget->mapToGlobal(e->pos());
+#endif
+}
+
+
+//============================================================================
+CFloatingDockContainer* CDockContainerWidget::floatingWidgetFromDropEvent(
+ QDropEvent* e, CDockManager* DockManager)
+{
+ auto FloatingWidget = CFloatingDockContainer::floatingWidgetFromMimeData(e->mimeData());
+ if (!FloatingWidget || !DockManager
+ || !DockManager->floatingWidgets().contains(FloatingWidget))
+ {
+ return nullptr;
+ }
+
+ return FloatingWidget;
+}
+
+
+//============================================================================
+void CDockContainerWidget::dragEnterEvent(QDragEnterEvent* e)
+{
+ auto FloatingWidget = floatingWidgetFromDropEvent(e, d->DockManager);
+ if (!FloatingWidget || FloatingWidget->dockContainer() == this)
+ {
+ QFrame::dragEnterEvent(e);
+ return;
+ }
+
+ e->acceptProposedAction();
+}
+
+
+//============================================================================
+void CDockContainerWidget::dragMoveEvent(QDragMoveEvent* e)
+{
+ auto FloatingWidget = floatingWidgetFromDropEvent(e, d->DockManager);
+ if (!FloatingWidget || FloatingWidget->dockContainer() == this)
+ {
+ QFrame::dragMoveEvent(e);
+ return;
+ }
+
+ e->acceptProposedAction();
+ const QPoint GlobalPos = dropEventGlobalPos(e, this);
+ d->updateDropOverlays(GlobalPos, FloatingWidget);
+
+ // Record the drop candidate so the drag source can dock the floating
+ // widget if the compositor does not deliver a drop event (see
+ // CFloatingDockContainer::startPlatformDrag)
+ bool ValidDropArea =
+ (d->DockManager->containerOverlay()->visibleDropAreaUnderCursor(GlobalPos) != InvalidDockWidgetArea)
+ || (d->DockManager->dockAreaOverlay()->visibleDropAreaUnderCursor(GlobalPos) != InvalidDockWidgetArea);
+ CFloatingDockContainer::platformDragUpdateDropCandidate(this, GlobalPos, ValidDropArea);
+}
+
+
+//============================================================================
+void CDockContainerWidget::dragLeaveEvent(QDragLeaveEvent* e)
+{
+ Q_UNUSED(e)
+ if (!d->DockManager)
+ {
+ return;
+ }
+
+ d->DockManager->containerOverlay()->hideOverlay();
+ d->DockManager->dockAreaOverlay()->hideOverlay();
+}
+
+
+//============================================================================
+void CDockContainerWidget::dropEvent(QDropEvent* e)
+{
+ auto FloatingWidget = floatingWidgetFromDropEvent(e, d->DockManager);
+ if (!FloatingWidget || FloatingWidget->dockContainer() == this)
+ {
+ QFrame::dropEvent(e);
+ return;
+ }
+
+ CFloatingDockContainer::platformDragNotifyDropHandled();
+ dropFloatingWidget(FloatingWidget, dropEventGlobalPos(e, this));
+ d->DockManager->containerOverlay()->hideOverlay();
+ d->DockManager->dockAreaOverlay()->hideOverlay();
+ e->acceptProposedAction();
+}
+
+
+//============================================================================
+QList<CAutoHideDockContainer*> CDockContainerWidget::autoHideWidgets() const
+{
+ return d->AutoHideWidgets;
+}
+
+
+//============================================================================
+void CDockContainerWidget::addDockArea(CDockAreaWidget* DockAreaWidget,
+ DockWidgetArea area)
+{
+ CDockContainerWidget* Container = DockAreaWidget->dockContainer();
+ if (Container && Container != this)
+ {
+ Container->removeDockArea(DockAreaWidget);
+ }
+
+ d->addDockArea(DockAreaWidget, area);
+}
+
+
+//============================================================================
+void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
+{
+ ADS_PRINT("CDockContainerWidget::removeDockArea");
+ // If it is an auto hide area, then there is nothing much to do
+ if (area->isAutoHide())
+ {
+ area->setAutoHideDockContainer(nullptr);
+ return;
+ }
+
+ area->disconnect(this);
+ d->DockAreas.removeAll(area);
+ auto Splitter = area->parentSplitter();
+
+ // Remove area from parent splitter and recursively hide tree of parent
+ // splitters if it has no visible content.
+ // Use internalWinId() rather than testAttribute(WA_NativeWindow) because
+ // WA_NativeWindow is only set when a widget is *explicitly* made native
+ // (e.g. winId() called directly on it). Widgets that became native through
+ // propagation from a child calling winId() (e.g. a VTK/OpenGL widget) also
+ // hold a real native window handle but may not have WA_NativeWindow set.
+ // Setting the parent of such a native window to nullptr would make it an
+ // invisible top-level OS window, causing drawing artifacts. Reparent to
+ // the dock manager instead so the window stays off-screen but within the
+ // application's window hierarchy.
+ if (area->internalWinId())
+ area->setParent(d->DockManager);
+ else
+ area->setParent(nullptr);
+ internal::hideEmptyParentSplitters(Splitter);
+
+ // Remove this area from cached areas
+ auto p = std::find(std::begin(d->LastAddedAreaCache), std::end(d->LastAddedAreaCache), area);
+ if (p != std::end(d->LastAddedAreaCache)) {
+ *p = nullptr;
+ }
+
+ // If splitter has more than 1 widgets, we are finished and can leave
+ if (Splitter->count() > 1)
+ {
+ goto emitAndExit;
+ }
+
+ // If this is the RootSplitter we need to remove empty splitters to
+ // avoid too many empty splitters
+ if (Splitter == d->RootSplitter)
+ {
+ ADS_PRINT("Removed from RootSplitter");
+ // If splitter is empty, we are finished
+ if (!Splitter->count())
+ {
+ Splitter->hide();
+ goto emitAndExit;
+ }
+
+ QWidget* widget = Splitter->widget(0);
+ 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)
+ {
+ goto emitAndExit;
+ }
+
+ // We replace the superfluous RootSplitter with the ChildSplitter
+ ChildSplitter->setParent(nullptr);
+ QLayoutItem* li = d->Layout->replaceWidget(Splitter, ChildSplitter);
+ d->RootSplitter = ChildSplitter;
+ delete li;
+ ADS_PRINT("RootSplitter replaced by child splitter");
+ }
+ else if (Splitter->count() == 1)
+ {
+ ADS_PRINT("Replacing splitter with content");
+ QSplitter* ParentSplitter = internal::findParent<QSplitter*>(Splitter);
+ auto Sizes = ParentSplitter->sizes();
+ QWidget* widget = Splitter->widget(0);
+ widget->setParent(this);
+ internal::replaceSplitterWidget(ParentSplitter, Splitter, widget);
+ ParentSplitter->setSizes(Sizes);
+ }
+
+ delete Splitter;
+ Splitter = nullptr;
+
+emitAndExit:
+ updateSplitterHandles(Splitter);
+ CDockWidget* TopLevelWidget = topLevelDockWidget();
+
+ // Updated the title bar visibility of the dock widget if there is only
+ // one single visible dock widget
+ CDockWidget::emitTopLevelEventForWidget(TopLevelWidget, true);
+ dumpLayout();
+ d->emitDockAreasRemoved();
+}
+
+
+//============================================================================
+QList<QPointer<CDockAreaWidget>> CDockContainerWidget::removeAllDockAreas()
+{
+ auto Result = d->DockAreas;
+ d->DockAreas.clear();
+ return Result;
+}
+
+
+//============================================================================
+CDockAreaWidget* CDockContainerWidget::dockAreaAt(const QPoint& GlobalPos) const
+{
+ for (const auto& DockArea : d->DockAreas)
+ {
+ if (DockArea && DockArea->isVisible() && DockArea->rect().contains(DockArea->mapFromGlobal(GlobalPos)))
+ {
+ return DockArea;
+ }
+ }
+
+ return nullptr;
+}
+
+
+//============================================================================
+CDockAreaWidget* CDockContainerWidget::dockArea(int Index) const
+{
+ return (Index < dockAreaCount()) ? d->DockAreas[Index] : nullptr;
+}
+
+
+//============================================================================
+bool CDockContainerWidget::isFloating() const
+{
+ return d->isFloating;
+}
+
+
+//============================================================================
+int CDockContainerWidget::dockAreaCount() const
+{
+ return d->DockAreas.count();
+}
+
+
+//============================================================================
+int CDockContainerWidget::visibleDockAreaCount() const
+{
+ int Result = 0;
+ for (auto DockArea : d->DockAreas)
+ {
+ Result += (!DockArea || DockArea->isHidden()) ? 0 : 1;
+ }
+
+ return Result;
+
+ // TODO Cache or precalculate this to speed it up because it is used during
+ // movement of floating widget
+ //return d->visibleDockAreaCount();
+}
+
+
+//============================================================================
+void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWidget,
+ const QPoint& TargetPos)
+{
+ ADS_PRINT("CDockContainerWidget::dropFloatingWidget");
+ CDockWidget* SingleDroppedDockWidget = FloatingWidget->topLevelDockWidget();
+ CDockWidget* SingleDockWidget = topLevelDockWidget();
+ auto dropArea = InvalidDockWidgetArea;
+ auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(TargetPos);
+ bool Dropped = false;
+
+ CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
+ // mouse is over dock area
+ if (DockArea)
+ {
+ auto dropOverlay = d->DockManager->dockAreaOverlay();
+ dropOverlay->setAllowedAreas(DockArea->allowedAreas());
+ dropArea = dropOverlay->showOverlay(DockArea, TargetPos);
+ if (ContainerDropArea != InvalidDockWidgetArea &&
+ ContainerDropArea != dropArea)
+ {
+ dropArea = InvalidDockWidgetArea;
+ }
+
+ if (dropArea != InvalidDockWidgetArea)
+ {
+ ADS_PRINT("Dock Area Drop Content: " << dropArea);
+ int TabIndex = d->DockManager->dockAreaOverlay()->tabIndexUnderCursor();
+ d->dropIntoSection(FloatingWidget, DockArea, dropArea, TabIndex);
+ Dropped = true;
+ }
+ }
+
+ // mouse is over container or auto hide side bar
+ if (InvalidDockWidgetArea == dropArea && InvalidDockWidgetArea != ContainerDropArea)
+ {
+ 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 = autoHideSideBar(AutohideWidget->sideBarLocation());
+ SideBar->addAutoHideWidget(AutohideWidget);
+ }
+
+ if (Dropped)
+ {
+ // Fix https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/351
+ FloatingWidget->finishDropOperation();
+
+ // If we dropped a floating widget with only one single dock widget, then we
+ // drop a top level widget that changes from floating to docked now
+ CDockWidget::emitTopLevelEventForWidget(SingleDroppedDockWidget, false);
+
+ // If there was a top level widget before the drop, then it is not top
+ // level widget anymore
+ CDockWidget::emitTopLevelEventForWidget(SingleDockWidget, false);
+ }
+
+ window()->activateWindow();
+ if (SingleDroppedDockWidget)
+ {
+ d->DockManager->notifyWidgetOrAreaRelocation(SingleDroppedDockWidget);
+ }
+ d->DockManager->notifyFloatingWidgetDrop(FloatingWidget);
+}
+
+
+//============================================================================
+void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget,
+ int TabIndex)
+{
+ CDockWidget* SingleDockWidget = topLevelDockWidget();
+ if (TargetAreaWidget)
+ {
+ d->moveToNewSection(Widget, TargetAreaWidget, DropArea, TabIndex);
+ }
+ else if (internal::isSideBarArea(DropArea))
+ {
+ d->moveToAutoHideSideBar(Widget, DropArea, TabIndex);
+ }
+ else
+ {
+ d->moveToContainer(Widget, DropArea);
+ }
+
+ // If there was a top level widget before the drop, then it is not top
+ // level widget anymore
+ CDockWidget::emitTopLevelEventForWidget(SingleDockWidget, false);
+
+ window()->activateWindow();
+ d->DockManager->notifyWidgetOrAreaRelocation(Widget);
+}
+
+
+//============================================================================
+QList<CDockAreaWidget*> CDockContainerWidget::openedDockAreas() const
+{
+ QList<CDockAreaWidget*> Result;
+ for (auto DockArea : d->DockAreas)
+ {
+ if (DockArea && !DockArea->isHidden())
+ {
+ Result.append(DockArea);
+ }
+ }
+
+ return Result;
+}
+
+
+//============================================================================
+QList<CDockWidget*> CDockContainerWidget::openedDockWidgets() const
+{
+ QList<CDockWidget*> DockWidgetList;
+ for (auto DockArea : d->DockAreas)
+ {
+ if (DockArea && !DockArea->isHidden())
+ {
+ DockWidgetList.append(DockArea->openedDockWidgets());
+ }
+ }
+
+ return DockWidgetList;
+}
+
+
+//============================================================================
+bool CDockContainerWidget::hasOpenDockAreas() const
+{
+ for (auto DockArea : d->DockAreas)
+ {
+ if (DockArea && !DockArea->isHidden())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+//============================================================================
+void CDockContainerWidget::saveState(QXmlStreamWriter& s) const
+{
+ ADS_PRINT("CDockContainerWidget::saveState isFloating "
+ << isFloating());
+
+ s.writeStartElement("Container");
+ s.writeAttribute("Floating", QString::number(isFloating() ? 1 : 0));
+ if (isFloating())
+ {
+ CFloatingDockContainer* FloatingWidget = floatingWidget();
+ QByteArray Geometry = FloatingWidget->saveGeometry();
+#if QT_VERSION < 0x050900
+ s.writeTextElement("Geometry", qByteArrayToHex(Geometry, ' '));
+#else
+ s.writeTextElement("Geometry", Geometry.toHex(' '));
+#endif
+ }
+ d->saveChildNodesState(s, d->RootSplitter);
+ d->saveAutoHideWidgetsState(s);
+ s.writeEndElement();
+}
+
+
+//============================================================================
+bool CDockContainerWidget::restoreState(CDockingStateReader& s, bool Testing)
+{
+ bool IsFloating = s.attributes().value("Floating").toInt();
+ ADS_PRINT("Restore CDockContainerWidget Floating" << IsFloating);
+
+ QWidget* NewRootSplitter {};
+ if (!Testing)
+ {
+ d->VisibleDockAreaCount = -1;// invalidate the dock area count
+ d->DockAreas.clear();
+ std::fill(std::begin(d->LastAddedAreaCache),std::end(d->LastAddedAreaCache), nullptr);
+ }
+
+ if (IsFloating)
+ {
+ ADS_PRINT("Restore floating widget");
+ if (!s.readNextStartElement() || s.name() != QLatin1String("Geometry"))
+ {
+ return false;
+ }
+
+ QByteArray GeometryString = s.readElementText(CDockingStateReader::ErrorOnUnexpectedElement).toLocal8Bit();
+ QByteArray Geometry = QByteArray::fromHex(GeometryString);
+ if (Geometry.isEmpty())
+ {
+ return false;
+ }
+
+ if (!Testing)
+ {
+ CFloatingDockContainer* FloatingWidget = floatingWidget();
+ if (FloatingWidget)
+ {
+ FloatingWidget->restoreGeometry(Geometry);
+ }
+ }
+ }
+
+ if (!d->restoreChildNodes(s, NewRootSplitter, Testing))
+ {
+ return false;
+ }
+
+ if (Testing)
+ {
+ return true;
+ }
+
+ // If the root splitter is empty, rostoreChildNodes returns a 0 pointer
+ // and we need to create a new empty root splitter
+ if (!NewRootSplitter)
+ {
+ NewRootSplitter = d->newSplitter(Qt::Horizontal);
+ }
+
+ QLayoutItem* li = d->Layout->replaceWidget(d->RootSplitter, NewRootSplitter);
+ auto OldRoot = d->RootSplitter;
+ d->RootSplitter = qobject_cast<CDockSplitter*>(NewRootSplitter);
+ OldRoot->deleteLater();
+ delete li;
+
+ return true;
+}
+
+
+//============================================================================
+CDockSplitter* CDockContainerWidget::rootSplitter() const
+{
+ return d->RootSplitter;
+}
+
+
+//============================================================================
+void CDockContainerWidget::createRootSplitter()
+{
+ if (d->RootSplitter)
+ {
+ return;
+ }
+ d->RootSplitter = d->newSplitter(Qt::Horizontal);
+ d->Layout->addWidget(d->RootSplitter, 1, 1); // Add it to the center - the 0 and 2 indexes are used for the SideTabBar widgets
+}
+
+
+//============================================================================
+void CDockContainerWidget::createSideTabBarWidgets()
+{
+ if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
+ {
+ return;
+ }
+
+ {
+ auto Area = SideBarLocation::SideBarLeft;
+ d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area);
+ d->Layout->addWidget(d->SideTabBarWidgets[Area], 1, 0);
+ }
+
+ {
+ auto Area = SideBarLocation::SideBarRight;
+ d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area);
+ d->Layout->addWidget(d->SideTabBarWidgets[Area], 1, 2);
+ }
+
+ {
+ auto Area = SideBarLocation::SideBarBottom;
+ d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area);
+ d->Layout->addWidget(d->SideTabBarWidgets[Area], 2, 1);
+ }
+
+ {
+ auto Area = SideBarLocation::SideBarTop;
+ d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area);
+ d->Layout->addWidget(d->SideTabBarWidgets[Area], 0, 1);
+ }
+}
+
+
+//============================================================================
+void CDockContainerWidget::dumpLayout()
+{
+#if (ADS_DEBUG_LEVEL > 0)
+ qDebug("\n\nDumping layout --------------------------");
+ std::cout << "\n\nDumping layout --------------------------" << std::endl;
+ d->dumpRecursive(0, d->RootSplitter);
+ qDebug("--------------------------\n\n");
+ std::cout << "--------------------------\n\n" << std::endl;
+#endif
+}
+
+
+//============================================================================
+CDockAreaWidget* CDockContainerWidget::lastAddedDockAreaWidget(DockWidgetArea area) const
+{
+ return d->LastAddedAreaCache[areaIdToIndex(area)];
+}
+
+
+//============================================================================
+bool CDockContainerWidget::hasTopLevelDockWidget() const
+{
+ auto DockAreas = openedDockAreas();
+ if (DockAreas.count() != 1)
+ {
+ return false;
+ }
+
+ return DockAreas[0]->openDockWidgetsCount() == 1;
+}
+
+
+//============================================================================
+CDockWidget* CDockContainerWidget::topLevelDockWidget() const
+{
+ auto TopLevelDockArea = topLevelDockArea();
+ if (!TopLevelDockArea)
+ {
+ return nullptr;
+ }
+
+ auto DockWidgets = TopLevelDockArea->openedDockWidgets();
+ if (DockWidgets.count() != 1)
+ {
+ return nullptr;
+ }
+
+ return DockWidgets[0];
+
+}
+
+
+//============================================================================
+CDockAreaWidget* CDockContainerWidget::topLevelDockArea() const
+{
+ auto DockAreas = openedDockAreas();
+ if (DockAreas.count() != 1)
+ {
+ return nullptr;
+ }
+
+ return DockAreas[0];
+}
+
+
+//============================================================================
+QList<CDockWidget*> CDockContainerWidget::dockWidgets() const
+{
+ QList<CDockWidget*> Result;
+ for (const auto& DockArea : d->DockAreas)
+ {
+ if (!DockArea)
+ {
+ continue;
+ }
+ Result.append(DockArea->dockWidgets());
+ }
+
+ return Result;
+}
+
+//============================================================================
+void CDockContainerWidget::updateSplitterHandles(QSplitter* splitter)
+{
+ d->updateSplitterHandles(splitter);
+}
+
+//============================================================================
+void CDockContainerWidget::registerAutoHideWidget(CAutoHideDockContainer* AutohideWidget)
+{
+ d->AutoHideWidgets.append(AutohideWidget);
+ Q_EMIT autoHideWidgetCreated(AutohideWidget);
+ ADS_PRINT("d->AutoHideWidgets.count() " << d->AutoHideWidgets.count());
+}
+
+//============================================================================
+void CDockContainerWidget::removeAutoHideWidget(CAutoHideDockContainer* AutohideWidget)
+{
+ d->AutoHideWidgets.removeAll(AutohideWidget);
+}
+
+//============================================================================
+CDockWidget::DockWidgetFeatures CDockContainerWidget::features() const
+{
+ CDockWidget::DockWidgetFeatures Features(CDockWidget::AllDockWidgetFeatures);
+ for (const auto& DockArea : d->DockAreas)
+ {
+ if (!DockArea)
+ {
+ continue;
+ }
+ Features &= DockArea->features();
+ }
+
+ return Features;
+}
+
+
+//============================================================================
+CFloatingDockContainer* CDockContainerWidget::floatingWidget() const
+{
+ return internal::findParent<CFloatingDockContainer*>(this);
+}
+
+
+//============================================================================
+void CDockContainerWidget::closeOtherAreas(CDockAreaWidget* KeepOpenArea)
+{
+ for (const auto& DockArea : d->DockAreas)
+ {
+ if (!DockArea || DockArea == KeepOpenArea)
+ {
+ continue;
+ }
+
+ if (!DockArea->features(BitwiseAnd).testFlag(CDockWidget::DockWidgetClosable))
+ {
+ continue;
+ }
+
+ // We do not close areas with widgets with custom close handling
+ if (DockArea->features(BitwiseOr).testFlag(CDockWidget::CustomCloseHandling))
+ {
+ continue;
+ }
+
+ DockArea->closeArea();
+ }
+}
+
+//============================================================================
+CAutoHideSideBar* CDockContainerWidget::autoHideSideBar(SideBarLocation area) const
+{
+ return d->SideTabBarWidgets[area];
+}
+
+
+//============================================================================
+QRect CDockContainerWidget::contentRect() const
+{
+ if (!d->RootSplitter)
+ {
+ return QRect();
+ }
+
+ 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;
+ }
+}
+
+
+//===========================================================================
+QRect CDockContainerWidget::contentRectGlobal() const
+{
+ if (!d->RootSplitter)
+ {
+ return QRect();
+ }
+ return internal::globalGeometry(d->RootSplitter);
+}
+
+
+//===========================================================================
+CDockManager* CDockContainerWidget::dockManager() const
+{
+ return d->DockManager;
+}
+
+
+//===========================================================================
+void CDockContainerWidget::removeFromDockManager()
+{
+ if (d->DockManager)
+ {
+ d->DockManager->removeDockContainer(this);
+ d->DockManager.clear();
+ }
+}
+
+
+//===========================================================================
+void CDockContainerWidget::handleAutoHideWidgetEvent(QEvent* e, QWidget* w)
+{
+ if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideShowOnMouseOver))
+ {
+ return;
+ }
+
+ if (dockManager()->isRestoringState())
+ {
+ return;
+ }
+
+ auto AutoHideTab = qobject_cast<CAutoHideTab*>(w);
+ if (AutoHideTab)
+ {
+ switch (e->type())
+ {
+ case QEvent::Enter:
+ if (!AutoHideTab->dockWidget()->isVisible())
+ {
+ d->DelayedAutoHideTab = AutoHideTab;
+ d->DelayedAutoHideShow = true;
+ d->DelayedAutoHideTimer.start();
+ }
+ else
+ {
+ d->DelayedAutoHideTimer.stop();
+ }
+ break;
+
+ case QEvent::MouseButtonPress:
+ d->DelayedAutoHideTimer.stop();
+ break;
+
+ case QEvent::Leave:
+ if (AutoHideTab->dockWidget()->isVisible())
+ {
+ d->DelayedAutoHideTab = AutoHideTab;
+ d->DelayedAutoHideShow = false;
+ d->DelayedAutoHideTimer.start();
+ }
+ else
+ {
+ d->DelayedAutoHideTimer.stop();
+ }
+ break;
+
+ default:
+ break;
+ }
+ return;
+ }
+
+ auto AutoHideContainer = qobject_cast<CAutoHideDockContainer*>(w);
+ if (AutoHideContainer)
+ {
+ switch (e->type())
+ {
+ case QEvent::Enter:
+ case QEvent::Hide:
+ d->DelayedAutoHideTimer.stop();
+ break;
+
+ case QEvent::Leave:
+ if (AutoHideContainer->isVisible())
+ {
+ d->DelayedAutoHideTab = AutoHideContainer->autoHideTab();
+ d->DelayedAutoHideShow = false;
+ d->DelayedAutoHideTimer.start();
+ }
+ break;
+
+ default:
+ break;
+ }
+ return;
+ return;
+ }
+}
+} // namespace ads
+
+//---------------------------------------------------------------------------
+// EOF DockContainerWidget.cpp
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockContainerWidget.h b/scribus/third_party/Qt-Advanced-Docking-System/src/DockContainerWidget.h
index 2c80f6cd8..177127ce9 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockContainerWidget.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockContainerWidget.h
@@ -1,385 +1,436 @@
-#ifndef DockContainerWidgetH
-#define DockContainerWidgetH
-/*******************************************************************************
-** Qt Advanced Docking System
-** Copyright (C) 2017 Uwe Kindler
-**
-** This library is free software; you can redistribute it and/or
-** modify it under the terms of the GNU Lesser General Public
-** License as published by the Free Software Foundation; either
-** version 2.1 of the License, or (at your option) any later version.
-**
-** This library is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-** Lesser General Public License for more details.
-**
-** You should have received a copy of the GNU Lesser General Public
-** License along with this library; If not, see <http://www.gnu.org/licenses/>.
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockContainerWidget.h
-/// \author Uwe Kindler
-/// \date 24.02.2017
-/// \brief Declaration of CDockContainerWidget class
-//============================================================================
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include <QFrame>
-
-#include "ads_globals.h"
-#include "AutoHideTab.h"
-#include "DockWidget.h"
-
-QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
-
-
-namespace ads
-{
-class DockContainerWidgetPrivate;
-class CDockAreaWidget;
-class CDockWidget;
-class CDockManager;
-struct DockManagerPrivate;
-class CFloatingDockContainer;
-struct FloatingDockContainerPrivate;
-class CFloatingDragPreview;
-struct FloatingDragPreviewPrivate;
-class CDockingStateReader;
-class CAutoHideSideBar;
-class CAutoHideTab;
-class CDockSplitter;
-struct AutoHideTabPrivate;
-struct AutoHideDockContainerPrivate;
-
-
-/**
- * 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 contain a
- * DockContainerWidget instance.
- */
-class ADS_EXPORT CDockContainerWidget : public QFrame
-{
- Q_OBJECT
-private:
- DockContainerWidgetPrivate* d; ///< private data (pimpl)
- friend class DockContainerWidgetPrivate;
- friend class CDockManager;
- friend struct DockManagerPrivate;
- friend class CDockAreaWidget;
- friend struct DockAreaWidgetPrivate;
- friend class CFloatingDockContainer;
- friend struct FloatingDockContainerPrivate;
- friend class CDockWidget;
- friend class CFloatingDragPreview;
- friend struct FloatingDragPreviewPrivate;
- friend CAutoHideDockContainer;
- friend CAutoHideTab;
- friend AutoHideTabPrivate;
- friend AutoHideDockContainerPrivate;
- friend CAutoHideSideBar;
-
-protected:
- /**
- * Handles activation events to update zOrderIndex
- */
- virtual bool event(QEvent *e) override;
-
- /**
- * Access function for the internal root splitter
- */
- CDockSplitter* rootSplitter() const;
-
- /**
- * Creates and initializes a dockwidget auto hide container into the given area.
- * Initializing inserts the tabs into the side tab widget and hides it
- * Returns nullptr if you try and insert into an area where the configuration is not enabled
- */
- CAutoHideDockContainer* createAndSetupAutoHideContainer(SideBarLocation area, CDockWidget* DockWidget, int TabIndex = -1);
-
- /**
- * Helper function for creation of the root splitter
- */
- void createRootSplitter();
-
- /**
- * Helper function for creation of the side tab bar widgets
- */
- void createSideTabBarWidgets();
-
- /**
- * Drop floating widget into the container
- */
- void dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos);
-
- /**
- * Drop a dock area or a dock widget given in widget parameter.
- * If the TargetAreaWidget is a nullptr, then the DropArea indicates
- * the drop area for the container. If the given TargetAreaWidget is not
- * a nullptr, then the DropArea indicates the drop area in the given
- * 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 = ads::CenterDockWidgetArea);
-
- /**
- * Removes the given dock area from this container
- */
- void removeDockArea(CDockAreaWidget* area);
-
- /**
- * Remove all dock areas and returns the list of removed dock areas
- */
- QList<QPointer<CDockAreaWidget>> removeAllDockAreas();
-
- /**
- * Saves the state into the given stream
- */
- void saveState(QXmlStreamWriter& Stream) const;
-
- /**
- * Restores the state from given stream.
- * If Testing is true, the function only parses the data from the given
- * stream but does not restore anything. You can use this check for
- * faulty files before you start restoring the state
- */
- bool restoreState(CDockingStateReader& Stream, bool Testing);
-
- /**
- * This function returns the last added dock area widget for the given
- * area identifier or 0 if no dock area widget has been added for the given
- * area
- */
- CDockAreaWidget* lastAddedDockAreaWidget(DockWidgetArea area) const;
-
- /**
- * If hasSingleVisibleDockWidget() returns true, this function returns the
- * one and only visible dock widget. Otherwise it returns a nullptr.
- */
- CDockWidget* topLevelDockWidget() const;
-
- /**
- * If the container has only one single visible dock area, then this
- * functions returns this top level dock area
- */
- CDockAreaWidget* topLevelDockArea() const;
-
- /**
- * This function returns a list of all dock widgets in this floating widget.
- * It may be possible, depending on the implementation, that dock widgets,
- * that are not visible to the user have no parent widget. Therefore simply
- * calling findChildren() would not work here. Therefore this function
- * iterates over all dock areas and creates a list that contains all
- * dock widgets returned from all dock areas.
- */
- QList<CDockWidget*> dockWidgets() const;
-
- /**
- * This function forces the dock container widget to update handles of splitters
- * based on resize modes of dock widgets contained in the container.
- */
- void updateSplitterHandles(QSplitter* splitter);
-
- /**
- * Registers the given floating widget in the internal list of
- * auto hide widgets
- */
- void registerAutoHideWidget(CAutoHideDockContainer* AutoHideWidget);
-
- /**
- * Remove the given auto hide widget from the list of registered auto hide
- * widgets
- */
- void removeAutoHideWidget(CAutoHideDockContainer* AutoHideWidget);
-
- /**
- * Handles widget events of auto hide widgets to trigger delayed show
- * or hide actions for auto hide container on auto hide tab mouse over
- */
- void handleAutoHideWidgetEvent(QEvent* e, QWidget* w);
-
-public:
- /**
- * Default Constructor
- */
- CDockContainerWidget(CDockManager* DockManager, QWidget* parent = 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
- */
- CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
- CDockAreaWidget* DockAreaWidget = nullptr, int Index = -1);
-
- /**
- * Removes dockwidget
- */
- void removeDockWidget(CDockWidget* Dockwidget);
-
- /**
- * 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(CDockContainerWidget* Other) const;
-
- /**
- * Returns the dock area at the given global position or 0 if there is no
- * dock area at this position
- */
- CDockAreaWidget* dockAreaAt(const QPoint& GlobalPos) const;
-
- /**
- * Returns the dock area at the given Index or 0 if the index is out of
- * range
- */
- 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<CDockAreaWidget*> openedDockAreas() const;
-
- /**
- * Returns a list for all open dock widgets in all open dock areas
- */
- QList<CDockWidget*> openedDockWidgets() const;
-
- /**
- * This function returns true, if the container has open dock areas.
- * This functions is a little bit faster than calling openedDockAreas().isEmpty()
- * because it returns as soon as it finds an open dock area
- */
- bool hasOpenDockAreas() const;
-
- /**
- * This function returns true if this dock area has only one single
- * visible dock widget.
- * A top level widget is a real floating widget. Only the isFloating()
- * function of top level widgets may returns true.
- */
- 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.
- */
- CDockWidget::DockWidgetFeatures features() const;
-
- /**
- * If this dock container is in a floating widget, this function returns
- * the floating widget.
- * Else, it returns a nullptr.
- */
- CFloatingDockContainer* floatingWidget() const;
-
- /**
- * Call this function to close all dock areas except the KeepOpenArea
- */
- void closeOtherAreas(CDockAreaWidget* KeepOpenArea);
-
- /**
- * Returns the side tab widget for the given area
- */
- CAutoHideSideBar* autoHideSideBar(SideBarLocation area) const;
-
-
- /**
- * Access function for auto hide widgets
- */
- QList<CAutoHideDockContainer*> autoHideWidgets() const;
-
- /**
- * Returns the content rectangle without the autohide side bars
- */
- QRect contentRect() const;
-
- /**
- * Returns the content rectangle mapped to global space.
- * The content rectangle is the rectangle of the dock manager widget minus
- * the auto hide side bars. So that means, it is the geometry of the
- * internal root splitter mapped to global space.
- */
- QRect contentRectGlobal() const;
-
- /**
- * Returns the dock manager that owns this container
- */
- CDockManager* dockManager() const;
-
-
-Q_SIGNALS:
- /**
- * This signal is emitted if one or multiple dock areas has been added to
- * 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 a new auto hide widget has been created.
- */
- void autoHideWidgetCreated(ads::CAutoHideDockContainer* AutoHideWidget);
-
- /**
- * This signal is emitted if one or multiple dock areas has been removed
- */
- 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
-//-----------------------------------------------------------------------------
-#endif // DockContainerWidgetH
+#ifndef DockContainerWidgetH
+#define DockContainerWidgetH
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockContainerWidget.h
+/// \author Uwe Kindler
+/// \date 24.02.2017
+/// \brief Declaration of CDockContainerWidget class
+//============================================================================
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include <QFrame>
+
+#include "ads_globals.h"
+#include "AutoHideTab.h"
+#include "DockWidget.h"
+
+QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
+
+
+namespace ads
+{
+class DockContainerWidgetPrivate;
+class CDockAreaWidget;
+class CDockWidget;
+class CDockManager;
+struct DockManagerPrivate;
+class CFloatingDockContainer;
+struct FloatingDockContainerPrivate;
+class CFloatingDragPreview;
+struct FloatingDragPreviewPrivate;
+class CDockingStateReader;
+class CAutoHideSideBar;
+class CAutoHideTab;
+class CDockSplitter;
+struct AutoHideTabPrivate;
+struct AutoHideDockContainerPrivate;
+
+
+/**
+ * Container that manages a number of dock areas with single dock widgets
+ * or tabified dock widgets in each area.
+ * Each window that support docking has a DockContainerWidget. That means
+ * the main application window and all floating windows contain a
+ * DockContainerWidget instance.
+ */
+class ADS_EXPORT CDockContainerWidget : public QFrame
+{
+ Q_OBJECT
+private:
+ DockContainerWidgetPrivate* d; ///< private data (pimpl)
+ friend class DockContainerWidgetPrivate;
+ friend class CDockManager;
+ friend struct DockManagerPrivate;
+ friend class CDockAreaWidget;
+ friend struct DockAreaWidgetPrivate;
+ friend class CFloatingDockContainer;
+ friend struct FloatingDockContainerPrivate;
+ friend class CDockWidget;
+ friend class CFloatingDragPreview;
+ friend struct FloatingDragPreviewPrivate;
+ friend CAutoHideDockContainer;
+ friend CAutoHideTab;
+ friend AutoHideTabPrivate;
+ friend AutoHideDockContainerPrivate;
+ friend CAutoHideSideBar;
+
+private Q_SLOTS:
+ void removeFromDockManager();
+
+protected:
+ /**
+ * Handles activation events to update zOrderIndex
+ */
+ virtual bool event(QEvent *e) override;
+
+ /**
+ * The drag and drop events below implement docking of floating widgets
+ * on Wayland, where CFloatingDockContainer::startPlatformDrag() executes
+ * a compositor driven drag instead of the mouse tracked dragging that is
+ * used on the other platforms.
+ * Accepts the drag, if it transports a floating widget of the same
+ * dock manager
+ */
+ virtual void dragEnterEvent(QDragEnterEvent* e) override;
+
+ /**
+ * Updates the drop overlays for the drag position
+ */
+ virtual void dragMoveEvent(QDragMoveEvent* e) override;
+
+ /**
+ * Hides the drop overlays, if the drag leaves this container
+ */
+ virtual void dragLeaveEvent(QDragLeaveEvent* e) override;
+
+ /**
+ * Docks the dragged floating widget into the drop area under the drop
+ * position
+ */
+ virtual void dropEvent(QDropEvent* e) override;
+
+ /**
+ * Returns the floating widget transported by the given platform drag
+ * and drop event, if the drag was started by this application and the
+ * floating widget belongs to the given dock manager; otherwise nullptr.
+ * The floating widget pointer from the mime data is only dereferenced
+ * after it was found in the dock manager floating widget list, so drags
+ * from other applications cannot inject an invalid pointer
+ */
+ static CFloatingDockContainer* floatingWidgetFromDropEvent(QDropEvent* e,
+ CDockManager* DockManager);
+
+ /**
+ * Configures and shows the container and dock area drop overlays for a
+ * drag that hovers over TopContainer at the given global position.
+ * Shared by the mouse tracked dragging (CFloatingDragPreview /
+ * CFloatingDockContainer) and the Wayland platform drag and drop.
+ * ContentPinnable is true, if the dragged content can be auto hidden.
+ */
+ static void showDropOverlays(CDockManager* DockManager,
+ CDockContainerWidget* TopContainer, const QPoint& GlobalPos,
+ bool ContentPinnable);
+
+ /**
+ * Access function for the internal root splitter
+ */
+ CDockSplitter* rootSplitter() const;
+
+ /**
+ * Creates and initializes a dockwidget auto hide container into the given area.
+ * Initializing inserts the tabs into the side tab widget and hides it
+ * Returns nullptr if you try and insert into an area where the configuration is not enabled
+ */
+ CAutoHideDockContainer* createAndSetupAutoHideContainer(SideBarLocation area, CDockWidget* DockWidget, int TabIndex = -1);
+
+ /**
+ * Helper function for creation of the root splitter
+ */
+ void createRootSplitter();
+
+ /**
+ * Helper function for creation of the side tab bar widgets
+ */
+ void createSideTabBarWidgets();
+
+ /**
+ * Drop floating widget into the container
+ */
+ void dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos);
+
+ /**
+ * Drop a dock area or a dock widget given in widget parameter.
+ * If the TargetAreaWidget is a nullptr, then the DropArea indicates
+ * the drop area for the container. If the given TargetAreaWidget is not
+ * a nullptr, then the DropArea indicates the drop area in the given
+ * 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 = ads::CenterDockWidgetArea);
+
+ /**
+ * Removes the given dock area from this container
+ */
+ void removeDockArea(CDockAreaWidget* area);
+
+ /**
+ * Remove all dock areas and returns the list of removed dock areas
+ */
+ QList<QPointer<CDockAreaWidget>> removeAllDockAreas();
+
+ /**
+ * Saves the state into the given stream
+ */
+ void saveState(QXmlStreamWriter& Stream) const;
+
+ /**
+ * Restores the state from given stream.
+ * If Testing is true, the function only parses the data from the given
+ * stream but does not restore anything. You can use this check for
+ * faulty files before you start restoring the state
+ */
+ bool restoreState(CDockingStateReader& Stream, bool Testing);
+
+ /**
+ * This function returns the last added dock area widget for the given
+ * area identifier or 0 if no dock area widget has been added for the given
+ * area
+ */
+ CDockAreaWidget* lastAddedDockAreaWidget(DockWidgetArea area) const;
+
+ /**
+ * If hasSingleVisibleDockWidget() returns true, this function returns the
+ * one and only visible dock widget. Otherwise it returns a nullptr.
+ */
+ CDockWidget* topLevelDockWidget() const;
+
+ /**
+ * If the container has only one single visible dock area, then this
+ * functions returns this top level dock area
+ */
+ CDockAreaWidget* topLevelDockArea() const;
+
+ /**
+ * This function returns a list of all dock widgets in this floating widget.
+ * It may be possible, depending on the implementation, that dock widgets,
+ * that are not visible to the user have no parent widget. Therefore simply
+ * calling findChildren() would not work here. Therefore this function
+ * iterates over all dock areas and creates a list that contains all
+ * dock widgets returned from all dock areas.
+ */
+ QList<CDockWidget*> dockWidgets() const;
+
+ /**
+ * This function forces the dock container widget to update handles of splitters
+ * based on resize modes of dock widgets contained in the container.
+ */
+ void updateSplitterHandles(QSplitter* splitter);
+
+ /**
+ * Registers the given floating widget in the internal list of
+ * auto hide widgets
+ */
+ void registerAutoHideWidget(CAutoHideDockContainer* AutoHideWidget);
+
+ /**
+ * Remove the given auto hide widget from the list of registered auto hide
+ * widgets
+ */
+ void removeAutoHideWidget(CAutoHideDockContainer* AutoHideWidget);
+
+ /**
+ * Handles widget events of auto hide widgets to trigger delayed show
+ * or hide actions for auto hide container on auto hide tab mouse over
+ */
+ void handleAutoHideWidgetEvent(QEvent* e, QWidget* w);
+
+public:
+ /**
+ * Default Constructor
+ */
+ CDockContainerWidget(CDockManager* DockManager, QWidget* parent = 0);
+
+ /**
+ * Virtual Destructor
+ */
+ ~CDockContainerWidget() override;
+
+ /**
+ * 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
+ */
+ CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
+ CDockAreaWidget* DockAreaWidget = nullptr, int Index = -1);
+
+ /**
+ * Removes dockwidget
+ */
+ void removeDockWidget(CDockWidget* Dockwidget);
+
+ /**
+ * 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(CDockContainerWidget* Other) const;
+
+ /**
+ * Returns the dock area at the given global position or 0 if there is no
+ * dock area at this position
+ */
+ CDockAreaWidget* dockAreaAt(const QPoint& GlobalPos) const;
+
+ /**
+ * Returns the dock area at the given Index or 0 if the index is out of
+ * range
+ */
+ 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<CDockAreaWidget*> openedDockAreas() const;
+
+ /**
+ * Returns a list for all open dock widgets in all open dock areas
+ */
+ QList<CDockWidget*> openedDockWidgets() const;
+
+ /**
+ * This function returns true, if the container has open dock areas.
+ * This functions is a little bit faster than calling openedDockAreas().isEmpty()
+ * because it returns as soon as it finds an open dock area
+ */
+ bool hasOpenDockAreas() const;
+
+ /**
+ * This function returns true if this dock area has only one single
+ * visible dock widget.
+ * A top level widget is a real floating widget. Only the isFloating()
+ * function of top level widgets may returns true.
+ */
+ 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.
+ */
+ CDockWidget::DockWidgetFeatures features() const;
+
+ /**
+ * If this dock container is in a floating widget, this function returns
+ * the floating widget.
+ * Else, it returns a nullptr.
+ */
+ CFloatingDockContainer* floatingWidget() const;
+
+ /**
+ * Call this function to close all dock areas except the KeepOpenArea
+ */
+ void closeOtherAreas(CDockAreaWidget* KeepOpenArea);
+
+ /**
+ * Returns the side tab widget for the given area
+ */
+ CAutoHideSideBar* autoHideSideBar(SideBarLocation area) const;
+
+
+ /**
+ * Access function for auto hide widgets
+ */
+ QList<CAutoHideDockContainer*> autoHideWidgets() const;
+
+ /**
+ * Returns the content rectangle without the autohide side bars
+ */
+ QRect contentRect() const;
+
+ /**
+ * Returns the content rectangle mapped to global space.
+ * The content rectangle is the rectangle of the dock manager widget minus
+ * the auto hide side bars. So that means, it is the geometry of the
+ * internal root splitter mapped to global space.
+ */
+ QRect contentRectGlobal() const;
+
+ /**
+ * Returns the dock manager that owns this container
+ */
+ CDockManager* dockManager() const;
+
+
+Q_SIGNALS:
+ /**
+ * This signal is emitted if one or multiple dock areas has been added to
+ * 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 a new auto hide widget has been created.
+ */
+ void autoHideWidgetCreated(ads::CAutoHideDockContainer* AutoHideWidget);
+
+ /**
+ * This signal is emitted if one or multiple dock areas has been removed
+ */
+ 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
+//-----------------------------------------------------------------------------
+#endif // DockContainerWidgetH
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockFocusController.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/DockFocusController.cpp
index 27acc4a4d..57112c785 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockFocusController.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockFocusController.cpp
@@ -423,6 +423,13 @@ CDockWidget* CDockFocusController::focusedDockWidget() const
}
+//==========================================================================
+CDockAreaWidget* CDockFocusController::focusedDockArea() const
+{
+ return d->FocusedArea.data();
+}
+
+
//==========================================================================
void CDockFocusController::setDockWidgetTabPressed(bool Value)
{
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockFocusController.h b/scribus/third_party/Qt-Advanced-Docking-System/src/DockFocusController.h
index 27d9fc143..80f0c2af4 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockFocusController.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockFocusController.h
@@ -69,6 +69,12 @@ public:
*/
CDockWidget* focusedDockWidget() const;
+ /**
+ * Returns the dock area that contains the focusedDockWidget() or nullptr if
+ * the focused dock widget is not in this area.
+ */
+ CDockAreaWidget* focusedDockArea() const;
+
/**
* Request focus highlighting for the given dock widget assigned to the tab
* given in Tab parameter
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockManager.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/DockManager.cpp
index 06ed8cd25..1d65bf225 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockManager.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockManager.cpp
@@ -41,6 +41,7 @@
#include <QVariant>
#include <QDebug>
#include <QFile>
+#include <QDialog>
#include <QAction>
#include <QXmlStreamWriter>
#include <QSettings>
@@ -48,6 +49,8 @@
#include <QApplication>
#include <QWindow>
#include <QWindowStateChangeEvent>
+#include <QVector>
+#include <QStyleHints>
#include "FloatingDockContainer.h"
#include "DockOverlay.h"
@@ -59,6 +62,8 @@
#include "DockAreaTitleBar.h"
#include "DockFocusController.h"
#include "DockSplitter.h"
+#include "DockComponentsFactory.h"
+
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
#include "linux/FloatingWidgetTitleBar.h"
@@ -94,6 +99,7 @@ enum eStateFileVersion
static CDockManager::ConfigFlags StaticConfigFlags = CDockManager::DefaultNonOpaqueConfig;
static CDockManager::AutoHideFlags StaticAutoHideConfigFlags; // auto hide feature is disabled by default
+static QVector<QVariant> StaticConfigParams(CDockManager::ConfigParamCount);
static QString FloatingContainersTitle;
@@ -113,6 +119,7 @@ struct DockManagerPrivate
QMap<QString, QMenu*> ViewMenuGroups;
QMenu* ViewMenu;
CDockManager::eViewMenuInsertionOrder MenuInsertionOrder = CDockManager::MenuAlphabeticallySorted;
+ CDockManager::ColorSchemeMode ColorSchemeMode = CDockManager::ColorSchemeMode::FollowPalette;
bool RestoringState = false;
QVector<CFloatingDockContainer*> UninitializedFloatingWidgets;
CDockFocusController* FocusController = nullptr;
@@ -123,6 +130,8 @@ struct DockManagerPrivate
QSize ToolBarIconSizeDocked = QSize(16, 16);
QSize ToolBarIconSizeFloating = QSize(24, 24);
CDockWidget::DockWidgetFeatures LockedDockWidgetFeatures;
+ QSharedPointer<ads::CDockComponentsFactory> ComponentFactory {ads::CDockComponentsFactory::factory()};
+ bool CurrentStylesheetDark;
/**
* Private data constructor
@@ -197,6 +206,10 @@ DockManagerPrivate::DockManagerPrivate(CDockManager* _public) :
//============================================================================
void DockManagerPrivate::loadStylesheet()
{
+ if (CDockManager::testConfigFlag(CDockManager::DisableStylesheet))
+ {
+ return;
+ }
initResource();
QString Result;
QString FileName = ":ads/stylesheets/";
@@ -205,6 +218,12 @@ void DockManagerPrivate::loadStylesheet()
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
FileName += "_linux";
#endif
+ if (_this->isDesiredStylesheetDark()) {
+ CurrentStylesheetDark = true;
+ FileName += "_dark";
+ }
+ else
+ CurrentStylesheetDark = false;
FileName += ".css";
QFile StyleSheetFile(FileName);
StyleSheetFile.open(QIODevice::ReadOnly);
@@ -339,7 +358,12 @@ bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int versi
{
CFloatingDockContainer* floatingWidget = FloatingWidgets[i];
if (!floatingWidget) continue;
- _this->removeDockContainer(floatingWidget->dockContainer());
+ // Use removeFromDockManager() (introduced in upstream commit 544c624) instead
+ // of removeDockContainer() so the container's back-pointer to the manager is
+ // cleared. Otherwise ~CDockContainerWidget() (called when deleteLater() fires)
+ // would try to remove this container a second time, tripping the
+ // Q_ASSERT(removed == 1) check in CDockManager::removeDockContainer().
+ floatingWidget->dockContainer()->removeFromDockManager();
floatingWidget->deleteLater();
}
}
@@ -525,14 +549,45 @@ CDockManager::CDockManager(QWidget *parent) :
window()->installEventFilter(this);
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
- connect(qApp, &QApplication::focusWindowChanged, [](QWindow* focusWindow)
+ connect(qApp, &QApplication::focusWindowChanged, this, [this](QWindow* focusWindow)
{
- // bring modal dialogs to foreground to ensure that they are in front of any
- // floating dock widget
- if (focusWindow && focusWindow->isModal())
+ if (!focusWindow)
+ {
+ return;
+ }
+
+ auto widget = QWidget::find(focusWindow->winId());
+ if (!widget)
+ {
+ return;
+ }
+
+ // Only restack windows while a floating dock widget is actively being dragged.
+ // Reacting to ordinary focus changes makes this handler raise() multiple
+ // top-level windows, which can transfer focus and re-emit focusWindowChanged,
+ // re-entering this handler in a self-sustaining loop that never settles -
+ // visible as constant flicker on Linux/X11. Gating on an
+ // active drag breaks that loop: outside a drag we do nothing.
+ const bool draggingActive = std::any_of(
+ d->FloatingWidgets.begin(), d->FloatingWidgets.end(),
+ [](CFloatingDockContainer* fw){ return fw && fw->isDraggingActive(); });
+ if (!draggingActive)
+ {
+ return;
+ }
+
+ this->raise();
+ for (auto FloatingWidget : d->FloatingWidgets)
{
- focusWindow->raise();
+ if (FloatingWidget)
+ {
+ FloatingWidget->raise();
+ }
}
+
+ // ensure that the dragged floating window is in front of the main application window
+ // and any other floating widget - this will also ensure that modal dialogs come to foreground
+ focusWindow->raise();
});
#endif
}
@@ -550,7 +605,7 @@ CDockManager::~CDockManager()
{
if (!area || area->dockManager() != this) continue;
- // QPointer delete safety - just in case some dock wigdet in destruction
+ // QPointer delete safety - just in case some dock widget in destruction
// deletes another related/twin or child dock widget.
std::vector<QPointer<QWidget>> deleteWidgets;
for ( auto widget : area->dockWidgets() )
@@ -579,15 +634,50 @@ CDockManager::~CDockManager()
delete d;
}
+
+//============================================================================
+CDockWidget* CDockManager::createDockWidget(const QString &title, QWidget* parent)
+{
+ return new CDockWidget(this, title, parent);
+}
+
+
+//============================================================================
+QSharedPointer<ads::CDockComponentsFactory> CDockManager::componentsFactory() const
+{
+ return d->ComponentFactory;
+}
+
+
+//============================================================================
+void CDockManager::setComponentsFactory(ads::CDockComponentsFactory* factory)
+{
+ setComponentsFactory(QSharedPointer<ads::CDockComponentsFactory>(factory));
+}
+
+
+//============================================================================
+void CDockManager::setComponentsFactory(QSharedPointer<ads::CDockComponentsFactory> factory)
+{
+ d->ComponentFactory = factory;
+}
+
+
//============================================================================
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
bool CDockManager::eventFilter(QObject *obj, QEvent *e)
{
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
// Emulate Qt:Tool behaviour.
// Required because on some WMs Tool windows can't be maximized.
+ // Wayland: skip the stays-on-top emulation. The compositor owns the
+ // window stacking, and changing the window flags of a shown window
+ // recreates its surface, which would detach a running platform drag.
+ // The minimize synchronization below does not change window flags and
+ // is kept.
+
// Window always on top of the MainWindow.
- if (e->type() == QEvent::WindowActivate)
+ if (!internal::isWayland() && e->type() == QEvent::WindowActivate)
{
for (auto _window : d->FloatingWidgets)
{
@@ -609,7 +699,7 @@ bool CDockManager::eventFilter(QObject *obj, QEvent *e)
}
}
}
- else if (e->type() == QEvent::WindowDeactivate)
+ else if (!internal::isWayland() && e->type() == QEvent::WindowDeactivate)
{
for (auto _window : d->FloatingWidgets)
{
@@ -655,12 +745,7 @@ bool CDockManager::eventFilter(QObject *obj, QEvent *e)
QApplication::setActiveWindow(window());
}
}
- return Super::eventFilter(obj, e);
-}
#else
-//============================================================================
-bool CDockManager::eventFilter(QObject *obj, QEvent *e)
-{
if (e->type() == QEvent::WindowStateChange)
{
QWindowStateChangeEvent* ev = static_cast<QWindowStateChangeEvent*>(e);
@@ -670,9 +755,15 @@ bool CDockManager::eventFilter(QObject *obj, QEvent *e)
QMetaObject::invokeMethod(this, "endLeavingMinimizedState", Qt::QueuedConnection);
}
}
+#endif
+ if (e->type() == QEvent::ApplicationPaletteChange && d->ColorSchemeMode == CDockManager::ColorSchemeMode::FollowPalette)
+ {
+ if (d->CurrentStylesheetDark != isDesiredStylesheetDark()) {
+ d->loadStylesheet();
+ }
+ }
return Super::eventFilter(obj, e);
}
-#endif
//============================================================================
@@ -702,7 +793,8 @@ void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget
//============================================================================
void CDockManager::removeFloatingWidget(CFloatingDockContainer* FloatingWidget)
{
- d->FloatingWidgets.removeAll(FloatingWidget);
+ int removed = d->FloatingWidgets.removeAll(FloatingWidget);
+ Q_ASSERT(removed == 1);
}
//============================================================================
@@ -717,7 +809,8 @@ void CDockManager::removeDockContainer(CDockContainerWidget* DockContainer)
{
if (this != DockContainer)
{
- d->Containers.removeAll(DockContainer);
+ int removed = d->Containers.removeAll(DockContainer);
+ Q_ASSERT(removed == 1);
}
}
@@ -878,6 +971,35 @@ void CDockManager::showEvent(QShowEvent *event)
}
+//============================================================================
+void CDockManager::changeEvent(QEvent *event)
+{
+ Super::changeEvent(event);
+
+ // Wayland: floating widgets have no parent widget, so a style sheet set on
+ // this dock manager or one of its ancestors does not reach them through the
+ // widget hierarchy (an application wide qApp style sheet is still applied
+ // automatically by Qt). A QEvent::StyleChange on the dock manager fires both
+ // for its own style sheet and - because the change propagates down to
+ // descendants - for an ancestor's, so re-apply the inherited style sheet to
+ // every floating widget here to keep them matching the docked content.
+ // Re-applying cannot recurse: the floating widgets are not children of this
+ // dock manager, so it does not receive their StyleChange events.
+ if (event->type() == QEvent::StyleChange && internal::isWayland())
+ {
+ const QString StyleSheet =
+ CFloatingDockContainer::waylandInheritedStyleSheet(this);
+ for (auto FloatingWidget : d->FloatingWidgets)
+ {
+ if (FloatingWidget)
+ {
+ FloatingWidget->setStyleSheet(StyleSheet);
+ }
+ }
+ }
+}
+
+
//============================================================================
void CDockManager::restoreHiddenFloatingWidgets()
{
@@ -1189,6 +1311,18 @@ void CDockManager::setViewMenuInsertionOrder(eViewMenuInsertionOrder Order)
}
+//============================================================================
+void CDockManager::setColorSchemeMode(ColorSchemeMode Mode)
+{
+ d->ColorSchemeMode = Mode;
+
+ if (d->CurrentStylesheetDark != isDesiredStylesheetDark()) {
+ d->loadStylesheet();
+ ensurePolished();
+ }
+}
+
+
//===========================================================================
bool CDockManager::isRestoringState() const
{
@@ -1475,6 +1609,52 @@ CDockWidget::DockWidgetFeatures CDockManager::globallyLockedDockWidgetFeatures()
}
+//===========================================================================
+void CDockManager::setConfigParam(CDockManager::eConfigParam Param, QVariant Value)
+{
+ StaticConfigParams[Param] = Value;
+}
+
+
+//===========================================================================
+QVariant CDockManager::configParam(eConfigParam Param, QVariant Default)
+{
+ return StaticConfigParams[Param].isValid() ? StaticConfigParams[Param] : Default;
+}
+
+
+//===========================================================================
+void CDockManager::raise()
+{
+ if (parentWidget())
+ {
+ parentWidget()->raise();
+ }
+}
+
+
+//============================================================================
+bool CDockManager::isApplicationPaletteDark()
+{
+ QPalette appPalette = QGuiApplication::palette();
+
+ // Extract the background and foreground colors
+ QColor windowColor = appPalette.color(QPalette::Window);
+ QColor textColor = appPalette.color(QPalette::WindowText);
+
+ // Check lightness values (0.0 = black, 1.0 = white)
+ // If text is lighter than the background, the app palette is dark
+ return textColor.lightnessF() > windowColor.lightnessF();
+}
+
+
+//============================================================================
+bool CDockManager::isDesiredStylesheetDark()
+{
+ return ((isApplicationPaletteDark() && d->ColorSchemeMode == ColorSchemeMode::FollowPalette) || d->ColorSchemeMode == ColorSchemeMode::Dark);
+}
+
+
} // namespace ads
//---------------------------------------------------------------------------
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockManager.h b/scribus/third_party/Qt-Advanced-Docking-System/src/DockManager.h
index dcb2356c7..f0a12ebf6 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockManager.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockManager.h
@@ -64,8 +64,13 @@ struct AutoHideTabPrivate;
* of the docking system. The dock manager uses an internal stylesheet to
* style its components like splitters, tabs and buttons. If you want to
* disable this stylesheet because your application uses its own,
- * just call the function for settings the stylesheet with an empty
- * string.
+ * you can either set the DisableStylesheet config flag before creating
+ * the dock manager:
+ * \code
+ * CDockManager::setConfigFlag(CDockManager::DisableStylesheet, true);
+ * \endcode
+ * Or call the function for settings the stylesheet with an empty string
+ * after creating the dock manager:
* \code
* DockManager->setStyleSheet("");
* \endcode
@@ -153,6 +158,14 @@ protected:
*/
virtual void showEvent(QShowEvent *event) override;
+ /**
+ * Wayland: re-applies the inherited style sheet to all floating widgets
+ * when this dock manager or one of its ancestors changes its style sheet.
+ * Floating widgets have no parent widget on Wayland, so they do not
+ * receive style sheet changes that propagate down the widget hierarchy.
+ */
+ virtual void changeEvent(QEvent *event) override;
+
/**
* Access for the internal dock focus controller.
* This function only returns a valid object, if the FocusHighlighting
@@ -174,6 +187,13 @@ public:
MenuAlphabeticallySorted
};
+ enum class ColorSchemeMode
+ {
+ Light,
+ Dark,
+ FollowPalette
+ };
+
/**
* These global configuration flags configure some global dock manager
* settings.
@@ -215,6 +235,11 @@ public:
MiddleMouseButtonClosesTab = 0x2000000, //! If the flag is set, the user can use the mouse middle button to close the tab under the mouse
DisableTabTextEliding = 0x4000000, //! Set this flag to disable eliding of tab texts in dock area tabs
ShowTabTextOnlyForActiveTab =0x8000000, //! Set this flag to show label texts in dock area tabs only for active tabs
+ DoubleClickUndocksWidget = 0x10000000, //!< If the flag is set, a double click on a tab undocks the widget
+ TabsAtBottom = 0x20000000, //!< If the flag is set, tabs will be shown at the bottom instead of in the title bar.
+ UseNativeWindows = 0x40000000, //!< If the flag is set, windows for the dock and area widgets will be native.
+ DisableStylesheet = 0x80000000, //!< If the flag is set, the dock manager will not apply the default stylesheet
+
DefaultDockAreaButtons = DockAreaHasCloseButton
| DockAreaHasUndockButton
@@ -223,7 +248,8 @@ public:
DefaultBaseConfig = DefaultDockAreaButtons
| ActiveTabHasCloseButton
| XmlCompressionEnabled
- | FloatingContainerHasWidgetTitle, ///< default base configuration settings
+ | FloatingContainerHasWidgetTitle
+ | DoubleClickUndocksWidget, ///< default base configuration settings
DefaultOpaqueConfig = DefaultBaseConfig
| OpaqueSplitterResize
@@ -254,14 +280,26 @@ public:
AutoHideCloseButtonCollapsesDock = 0x40, ///< Close button of an auto hide container collapses the dock instead of hiding it completely
AutoHideHasCloseButton = 0x80, //< If the flag is set an auto hide title bar has a close button
AutoHideHasMinimizeButton = 0x100, ///< if this flag is set, the auto hide title bar has a minimize button to collapse the dock widget
+ AutoHideOpenOnDragHover = 0x200, ///< if this flag is set, dragging hover the tab bar will open the dock
+ AutoHideCloseOnOutsideMouseClick = 0x400, ///< if this flag is set, the auto hide dock container will collapse if the user clicks outside of the container, if not set, the auto hide container can be closed only via click on sidebar tab
DefaultAutoHideConfig = AutoHideFeatureEnabled
| DockAreaHasAutoHideButton
| AutoHideHasMinimizeButton
+ | AutoHideCloseOnOutsideMouseClick
};
Q_DECLARE_FLAGS(AutoHideFlags, eAutoHideFlag)
+ /**
+ * Global configuration parameters that you can set via setConfigParam()
+ */
+ enum eConfigParam
+ {
+ AutoHideOpenOnDragHoverDelay_ms, ///< Delay in ms before the dock opens on drag hover if AutoHideOpenOnDragHover flag is set
+ ConfigParamCount // just a delimiter to count number of config params
+ };
+
/**
* Default Constructor.
@@ -277,6 +315,39 @@ public:
*/
virtual ~CDockManager() override;
+ /**
+ * Creates a new dock widget with the specified title and optional parent
+ * widget.
+ *
+ * The new dock widget will be managed by the dock manager, and its lifetime
+ * will be tied to the dock manager. If a parent widget is provided, the dock
+ * widget will be created as a child of the parent widget. If no parent widget
+ * is provided, the dock widget will be created as a top-level widget.
+ *
+ * @param title The title of the dock widget.
+ * @param parent The parent widget, if any. Defaults to nullptr.
+ * @return Returns a pointer to the created CDockWidget.
+ */
+ CDockWidget *createDockWidget(const QString &title, QWidget* parent = nullptr);
+
+ /**
+ * Returns the dock manager specific factory for creating components of
+ * fock widgets
+ */
+ QSharedPointer<ads::CDockComponentsFactory> componentsFactory() const;
+
+ /**
+ * Sets a custom factory for creating components of dock widgets.
+ * The pointer is stored internally into a shared pointer so you should not
+ * delete the given factory object as long as it is used by the dock manager.
+ */
+ void setComponentsFactory(ads::CDockComponentsFactory* Factory);
+
+ /**
+ * Sets a custom factory for creating components of dock widgets.
+ */
+ void setComponentsFactory(QSharedPointer<ads::CDockComponentsFactory>);
+
/**
* This function returns the global configuration flags
*/
@@ -323,6 +394,17 @@ public:
*/
static bool testAutoHideConfigFlag(eAutoHideFlag Flag);
+ /**
+ * Sets the value for the given config parameter
+ */
+ static void setConfigParam(eConfigParam Param, QVariant Value);
+
+ /**
+ * Returns the value for the given config parameter or the default value
+ * if the parameter is not set.
+ */
+ static QVariant configParam(eConfigParam Param, QVariant Default);
+
/**
* Returns the global icon provider.
* The icon provider enables the use of custom icons in case using
@@ -330,6 +412,16 @@ public:
*/
static CIconProvider& iconProvider();
+ /**
+ * Returns if current application palette is dark
+ */
+ static bool isApplicationPaletteDark();
+
+ /**
+ * Returns if currently applied stylesheet is supposed to be dark
+ */
+ bool isDesiredStylesheetDark();
+
/**
* Adds dockwidget into the given area.
* If DockAreaWidget is not null, then the area parameter indicates the area
@@ -550,6 +642,17 @@ public:
*/
void setViewMenuInsertionOrder(eViewMenuInsertionOrder Order);
+ /**
+ * Define the behavior of stylesheet color scheme selection.
+ * The stylesheet can be fixed to either light or dark scheme,
+ * or it can follow the current application palette (default).
+ * Note: The fixed settings implement legacy behavior (before
+ * dark scheme was implemented) including problems like missing
+ * palette change propagation. They are implemented solely
+ * for compatibility reasons and manual stylesheet switching.
+ */
+ void setColorSchemeMode(ColorSchemeMode Mode);
+
/**
* This function returns true between the restoringState() and
* stateRestored() signals.
@@ -711,6 +814,12 @@ public Q_SLOTS:
*/
void hideManagerAndFloatingWidgets();
+ /**
+ * Calls raise() for the widget that hosts this dock manager.
+ * This will bring the widget in front of any other application that is running
+ */
+ void raise();
+
Q_SIGNALS:
/**
* This signal is emitted if the list of perspectives changed.
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockOverlay.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/DockOverlay.cpp
index 5b19dd92e..86dd2519e 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockOverlay.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockOverlay.cpp
@@ -1,984 +1,1126 @@
-/*******************************************************************************
-** Qt Advanced Docking System
-** Copyright (C) 2017 Uwe Kindler
-**
-** This library is free software; you can redistribute it and/or
-** modify it under the terms of the GNU Lesser General Public
-** License as published by the Free Software Foundation; either
-** version 2.1 of the License, or (at your option) any later version.
-**
-** This library is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-** Lesser General Public License for more details.
-**
-** You should have received a copy of the GNU Lesser General Public
-** License along with this library; If not, see <http://www.gnu.org/licenses/>.
-******************************************************************************/
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include "DockOverlay.h"
-
-#include <QPointer>
-#include <QPaintEvent>
-#include <QResizeEvent>
-#include <QMoveEvent>
-#include <QPainter>
-#include <QGridLayout>
-#include <QCursor>
-#include <QIcon>
-#include <QLabel>
-#include <QtGlobal>
-#include <QDebug>
-#include <QMap>
-#include <QWindow>
-
-#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
- */
-struct DockOverlayPrivate
-{
- CDockOverlay* _this;
- DockWidgetAreas AllowedAreas = InvalidDockWidgetArea;
- CDockOverlayCross* Cross;
- QPointer<QWidget> TargetWidget;
- DockWidgetArea LastLocation = InvalidDockWidgetArea;
- 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);
-};
-
-/**
- * Private data of CDockOverlayCross class
- */
-struct DockOverlayCrossPrivate
-{
- CDockOverlayCross* _this;
- CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay;
- CDockOverlay* DockOverlay;
- QHash<DockWidgetArea, QWidget*> DropIndicatorWidgets;
- QGridLayout* GridLayout;
- QColor IconColors[5];
- bool UpdateRequired = false;
- double LastDevicePixelRatio = 0.1;
-
- /**
- * Private data constructor
- */
- DockOverlayCrossPrivate(CDockOverlayCross* _public) : _this(_public) {}
-
- /**
- *
- * @param area
- * @return
- */
- QPoint areaGridPosition(const DockWidgetArea area);
-
-
- /**
- * Palette based default icon colors
- */
- QColor defaultIconColor(CDockOverlayCross::eIconColor ColorIndex)
- {
- QPalette pal = _this->palette();
- switch (ColorIndex)
- {
- case CDockOverlayCross::FrameColor: return pal.color(QPalette::Active, QPalette::Highlight);
- case CDockOverlayCross::WindowBackgroundColor: return pal.color(QPalette::Active, QPalette::Base);
- case CDockOverlayCross::OverlayColor:
- {
- QColor Color = pal.color(QPalette::Active, QPalette::Highlight);
- Color.setAlpha(64);
- return Color;
- }
- break;
-
- case CDockOverlayCross::ArrowColor: return pal.color(QPalette::Active, QPalette::Base);
- case CDockOverlayCross::ShadowColor: return QColor(0, 0, 0, 64);
- default:
- return QColor();
- }
-
- return QColor();
- }
-
- /**
- * Stylehseet based icon colors
- */
- QColor iconColor(CDockOverlayCross::eIconColor ColorIndex)
- {
- QColor Color = IconColors[ColorIndex];
- if (!Color.isValid())
- {
- Color = defaultIconColor(ColorIndex);
- IconColors[ColorIndex] = Color;
- }
- return Color;
- }
-
- //============================================================================
- /**
- * Helper function that returns the drop indicator width depending on the
- * operating system
- */
- qreal dropIndicatiorWidth(QLabel* l) const
- {
- #if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
- Q_UNUSED(l)
- return 40;
- #else
- return static_cast<qreal>(l->fontMetrics().height()) * 3.f;
- #endif
- }
-
-
- //============================================================================
- QWidget* createDropIndicatorWidget(DockWidgetArea DockWidgetArea,
- CDockOverlay::eMode Mode)
- {
- QLabel* l = new QLabel();
- l->setObjectName("DockWidgetAreaLabel");
-
- 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);
- l->setAttribute(Qt::WA_TranslucentBackground);
- l->setProperty("dockWidgetArea", DockWidgetArea);
- return l;
- }
-
- //============================================================================
- void updateDropIndicatorIcon(QWidget* DropIndicatorWidget)
- {
- QLabel* l = qobject_cast<QLabel*>(DropIndicatorWidget);
- const qreal metric = dropIndicatiorWidth(l);
- const QSizeF size(metric, metric);
-
- int Area = l->property("dockWidgetArea").toInt();
- l->setPixmap(createHighDpiDropIndicatorPixmap(size, (DockWidgetArea)Area, Mode));
- }
-
- //============================================================================
- QPixmap createHighDpiDropIndicatorPixmap(const QSizeF& size, DockWidgetArea DockWidgetArea,
- CDockOverlay::eMode Mode)
- {
- 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();
-#else
- double DevicePixelRatio = _this->window()->devicePixelRatio();
-#endif
- QSizeF PixmapSize = size * DevicePixelRatio;
- QPixmap pm(PixmapSize.toSize());
- pm.fill(QColor(0, 0, 0, 0));
-
- QPainter p(&pm);
- QPen pen = p.pen();
- QRectF ShadowRect(pm.rect());
- QRectF baseRect;
- baseRect.setSize(ShadowRect.size() * 0.7);
- baseRect.moveCenter(ShadowRect.center());
-
- // Fill
- QColor ShadowColor = iconColor(CDockOverlayCross::ShadowColor);
- if (ShadowColor.alpha() == 255)
- {
- ShadowColor.setAlpha(64);
- }
- p.fillRect(ShadowRect, ShadowColor);
-
- // Drop area rect.
- p.save();
- QRectF areaRect;
- QLineF areaLine;
- QRectF nonAreaRect;
- switch (DockWidgetArea)
- {
- case TopDockWidgetArea:
- areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
- nonAreaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
- areaLine = QLineF(areaRect.bottomLeft(), areaRect.bottomRight());
- break;
- case RightDockWidgetArea:
- areaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
- nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
- areaLine = QLineF(areaRect.topLeft(), areaRect.bottomLeft());
- break;
- case BottomDockWidgetArea:
- areaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
- nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
- areaLine = QLineF(areaRect.topLeft(), areaRect.topRight());
- break;
- case LeftDockWidgetArea:
- areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
- nonAreaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
- areaLine = QLineF(areaRect.topRight(), areaRect.bottomRight());
- break;
- default:
- break;
- }
-
- QSizeF baseSize = baseRect.size();
- 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);
- p.setBrush(overlayColor);
- p.setPen(Qt::NoPen);
- p.drawRect(areaRect);
-
- pen = p.pen();
- pen.setWidth(1);
- pen.setColor(borderColor);
- pen.setStyle(Qt::DashLine);
- p.setPen(pen);
- p.drawLine(areaLine);
- }
- p.restore();
-
-
- p.save();
- // Draw outer border
- pen = p.pen();
- pen.setColor(borderColor);
- pen.setWidth(1);
- p.setBrush(Qt::NoBrush);
- p.setPen(pen);
- p.drawRect(baseRect);
-
- // draw window title bar
- p.setBrush(borderColor);
- QRectF FrameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10));
- p.drawRect(FrameRect);
- p.restore();
-
-
- // Draw arrow for outer container drop indicators
- if (IsOuterContainerArea)
- {
- QRectF ArrowRect;
- ArrowRect.setSize(baseSize);
- ArrowRect.setWidth(ArrowRect.width() / 4.6);
- ArrowRect.setHeight(ArrowRect.height() / 2);
- ArrowRect.moveCenter(QPointF(0, 0));
- QPolygonF Arrow;
- Arrow << ArrowRect.topLeft()
- << QPointF( ArrowRect.right(), ArrowRect.center().y())
- << ArrowRect.bottomLeft();
- p.setPen(Qt::NoPen);
- p.setBrush(iconColor(CDockOverlayCross::ArrowColor));
- p.setRenderHint(QPainter::Antialiasing, true);
- p.translate(nonAreaRect.center().x(), nonAreaRect.center().y());
-
- switch (DockWidgetArea)
- {
- case TopDockWidgetArea:
- p.rotate(-90);
- break;
- case RightDockWidgetArea:
- break;
- case BottomDockWidgetArea:
- p.rotate(90);
- break;
- case LeftDockWidgetArea:
- p.rotate(180);
- break;
- default:
- break;
- }
-
- p.drawPolygon(Arrow);
- }
-
- pm.setDevicePixelRatio(DevicePixelRatio);
- return pm;
- }
-
-};
-
-
-//============================================================================
-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),
- d(new DockOverlayPrivate(this))
-{
- d->Mode = Mode;
- d->Cross = new CDockOverlayCross(this);
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
- setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
-#else
- setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
-#endif
- setWindowOpacity(1);
- setWindowTitle("DockOverlay");
- setAttribute(Qt::WA_NoSystemBackground);
- setAttribute(Qt::WA_TranslucentBackground);
-
- d->Cross->setVisible(false);
- setVisible(false);
-}
-
-
-//============================================================================
-CDockOverlay::~CDockOverlay()
-{
- delete d;
-}
-
-
-//============================================================================
-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
-{
- return d->AllowedAreas;
-}
-
-
-//============================================================================
-DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
-{
- d->TabIndex = InvalidTabIndex;
- if (!d->TargetWidget)
- {
- return InvalidDockWidgetArea;
- }
-
- DockWidgetArea Result = d->Cross->cursorLocation();
- if (Result != InvalidDockWidgetArea)
- {
- return Result;
- }
-
- 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(CursorPos)))
- {
- auto TabBar = DockArea->titleBar()->tabBar();
- d->TabIndex = TabBar->tabInsertIndexAt(TabBar->mapFromGlobal(CursorPos));
- return CenterDockWidgetArea;
- }
-
- return Result;
-}
-
-
-//============================================================================
-int CDockOverlay::tabIndexUnderCursor() const
-{
- return d->TabIndex;
-}
-
-
-//============================================================================
-DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const
-{
- if (isHidden() || !d->DropPreviewEnabled)
- {
- return InvalidDockWidgetArea;
- }
- else
- {
- return dropAreaUnderCursor();
- }
-}
-
-
-//============================================================================
-DockWidgetArea CDockOverlay::showOverlay(QWidget* target)
-{
- if (d->TargetWidget == target)
- {
- // Hint: We could update geometry of overlay here.
- DockWidgetArea da = dropAreaUnderCursor();
- if (da != d->LastLocation)
- {
- repaint();
- d->LastLocation = da;
- }
- return da;
- }
-
- d->TargetWidget = target;
- d->LastLocation = InvalidDockWidgetArea;
-
- // Move it over the target.
- hide();
- resize(target->size());
- QPoint TopLeft = target->mapToGlobal(target->rect().topLeft());
- move(TopLeft);
- show();
- d->Cross->updatePosition();
- d->Cross->updateOverlayIcons();
- return dropAreaUnderCursor();
-}
-
-
-//============================================================================
-void CDockOverlay::hideOverlay()
-{
- hide();
- d->TargetWidget.clear();
- d->LastLocation = InvalidDockWidgetArea;
- d->DropAreaRect = QRect();
-}
-
-
-//============================================================================
-void CDockOverlay::enableDropPreview(bool Enable)
-{
- d->DropPreviewEnabled = Enable;
- update();
-}
-
-
-//============================================================================
-bool CDockOverlay::dropPreviewEnabled() const
-{
- return d->DropPreviewEnabled;
-}
-
-
-//============================================================================
-void CDockOverlay::paintEvent(QPaintEvent* event)
-{
- Q_UNUSED(event);
-
- // Draw rect based on location
- if (!d->DropPreviewEnabled)
- {
- d->DropAreaRect = QRect();
- return;
- }
-
- QRect r = rect();
- const DockWidgetArea da = dropAreaUnderCursor();
- double Factor = (CDockOverlay::ModeContainerOverlay == d->Mode) ?
- 3 : 2;
-
- switch (da)
- {
- case TopDockWidgetArea: r.setHeight(r.height() / Factor); break;
- case RightDockWidgetArea: r.setX(r.width() * (1 - 1 / Factor)); break;
- 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();
- Pen.setColor(Color.darker(120));
- Pen.setStyle(Qt::SolidLine);
- Pen.setWidth(1);
- Pen.setCosmetic(true);
- painter.setPen(Pen);
- Color = Color.lighter(130);
- Color.setAlpha(64);
- painter.setBrush(Color);
- painter.drawRect(r.adjusted(0, 0, -1, -1));
- d->DropAreaRect = r;
-}
-
-
-//============================================================================
-QRect CDockOverlay::dropOverlayRect() const
-{
- return d->DropAreaRect;
-}
-
-
-//============================================================================
-void CDockOverlay::showEvent(QShowEvent* e)
-{
- d->Cross->show();
- QFrame::showEvent(e);
-}
-
-
-//============================================================================
-void CDockOverlay::hideEvent(QHideEvent* e)
-{
- d->Cross->hide();
- QFrame::hideEvent(e);
-}
-
-
-//============================================================================
-bool CDockOverlay::event(QEvent *e)
-{
- bool Result = Super::event(e);
- if (e->type() == QEvent::Polish)
- {
- d->Cross->setupOverlayCross(d->Mode);
- }
- return Result;
-}
-
-
-//============================================================================
-static int areaAlignment(const DockWidgetArea area)
-{
- switch (area)
- {
- case TopDockWidgetArea: return (int) Qt::AlignHCenter | Qt::AlignBottom;
- case RightDockWidgetArea: return (int) Qt::AlignLeft | Qt::AlignVCenter;
- case BottomDockWidgetArea: return (int) Qt::AlignHCenter | Qt::AlignTop;
- case LeftDockWidgetArea: return (int) Qt::AlignRight | Qt::AlignVCenter;
- case CenterDockWidgetArea: return (int) Qt::AlignCenter;
- default: return Qt::AlignCenter;
- }
-}
-
-//============================================================================
-// DockOverlayCrossPrivate
-//============================================================================
-QPoint DockOverlayCrossPrivate::areaGridPosition(const DockWidgetArea area)
-{
- if (CDockOverlay::ModeDockAreaOverlay == Mode)
- {
- switch (area)
- {
- case TopDockWidgetArea: return QPoint(1, 2);
- case RightDockWidgetArea: return QPoint(2, 3);
- case BottomDockWidgetArea: return QPoint(3, 2);
- case LeftDockWidgetArea: return QPoint(2, 1);
- case CenterDockWidgetArea: return QPoint(2, 2);
- default: return QPoint();
- }
- }
- else
- {
- switch (area)
- {
- case TopDockWidgetArea: return QPoint(0, 2);
- case RightDockWidgetArea: return QPoint(2, 4);
- case BottomDockWidgetArea: return QPoint(4, 2);
- case LeftDockWidgetArea: return QPoint(2, 0);
- case CenterDockWidgetArea: return QPoint(2, 2);
- default: return QPoint();
- }
- }
-}
-
-
-//============================================================================
-CDockOverlayCross::CDockOverlayCross(CDockOverlay* overlay) :
- QWidget(overlay->parentWidget()),
- d(new DockOverlayCrossPrivate(this))
-{
- d->DockOverlay = overlay;
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
- setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
-#else
- setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
-#endif
- setWindowTitle("DockOverlayCross");
- setAttribute(Qt::WA_TranslucentBackground);
-
- d->GridLayout = new QGridLayout();
- d->GridLayout->setSpacing(0);
- setLayout(d->GridLayout);
-}
-
-
-//============================================================================
-CDockOverlayCross::~CDockOverlayCross()
-{
- delete d;
-}
-
-
-//============================================================================
-void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode)
-{
- d->Mode = Mode;
-
- QHash<DockWidgetArea, QWidget*> areaWidgets;
- areaWidgets.insert(TopDockWidgetArea, d->createDropIndicatorWidget(TopDockWidgetArea, Mode));
- areaWidgets.insert(RightDockWidgetArea, d->createDropIndicatorWidget(RightDockWidgetArea, 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
- d->LastDevicePixelRatio = devicePixelRatio();
-#endif
- setAreaWidgets(areaWidgets);
- d->UpdateRequired = false;
-}
-
-
-//============================================================================
-void CDockOverlayCross::updateOverlayIcons()
-{
- if (windowHandle()->devicePixelRatio() == d->LastDevicePixelRatio)
- {
- return;
- }
-
- for (auto Widget : d->DropIndicatorWidgets)
- {
- d->updateDropIndicatorIcon(Widget);
- }
-#if QT_VERSION >= 0x050600
- d->LastDevicePixelRatio = devicePixelRatioF();
-#else
- d->LastDevicePixelRatio = devicePixelRatio();
-#endif
-}
-
-
-//============================================================================
-void CDockOverlayCross::setIconColor(eIconColor ColorIndex, const QColor& Color)
-{
- d->IconColors[ColorIndex] = Color;
- d->UpdateRequired = true;
-}
-
-
-//============================================================================
-QColor CDockOverlayCross::iconColor(eIconColor ColorIndex) const
-{
- return d->IconColors[ColorIndex];
-}
-
-
-//============================================================================
-void CDockOverlayCross::setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets)
-{
- // Delete old widgets.
- QMutableHashIterator<DockWidgetArea, QWidget*> i(d->DropIndicatorWidgets);
- while (i.hasNext())
- {
- i.next();
- QWidget* widget = i.value();
- d->GridLayout->removeWidget(widget);
- delete widget;
- i.remove();
- }
-
- // Insert new widgets into grid.
- d->DropIndicatorWidgets = widgets;
- QHashIterator<DockWidgetArea, QWidget*> i2(d->DropIndicatorWidgets);
- while (i2.hasNext())
- {
- i2.next();
- const DockWidgetArea area = i2.key();
- QWidget* widget = i2.value();
- QPoint p = d->areaGridPosition(area);
- d->GridLayout->addWidget(widget, p.x(), p.y(), (Qt::Alignment) areaAlignment(area));
- }
-
- if (CDockOverlay::ModeDockAreaOverlay == d->Mode)
- {
- d->GridLayout->setContentsMargins(0, 0, 0, 0);
- d->GridLayout->setRowStretch(0, 1);
- d->GridLayout->setRowStretch(1, 0);
- d->GridLayout->setRowStretch(2, 0);
- d->GridLayout->setRowStretch(3, 0);
- d->GridLayout->setRowStretch(4, 1);
-
- d->GridLayout->setColumnStretch(0, 1);
- d->GridLayout->setColumnStretch(1, 0);
- d->GridLayout->setColumnStretch(2, 0);
- d->GridLayout->setColumnStretch(3, 0);
- d->GridLayout->setColumnStretch(4, 1);
- }
- else
- {
- d->GridLayout->setContentsMargins(4, 4, 4, 4);
- d->GridLayout->setRowStretch(0, 0);
- d->GridLayout->setRowStretch(1, 1);
- d->GridLayout->setRowStretch(2, 1);
- d->GridLayout->setRowStretch(3, 1);
- d->GridLayout->setRowStretch(4, 0);
-
- d->GridLayout->setColumnStretch(0, 0);
- d->GridLayout->setColumnStretch(1, 1);
- d->GridLayout->setColumnStretch(2, 1);
- d->GridLayout->setColumnStretch(3, 1);
- d->GridLayout->setColumnStretch(4, 0);
- }
- reset();
-}
-
-
-//============================================================================
-DockWidgetArea CDockOverlayCross::cursorLocation() const
-{
- const QPoint pos = mapFromGlobal(QCursor::pos());
- QHashIterator<DockWidgetArea, QWidget*> i(d->DropIndicatorWidgets);
- while (i.hasNext())
- {
- i.next();
- if (d->DockOverlay->allowedAreas().testFlag(i.key())
- && i.value()
- && i.value()->isVisible()
- && i.value()->geometry().contains(pos))
- {
- return i.key();
- }
- }
- return InvalidDockWidgetArea;
-}
-
-
-//============================================================================
-void CDockOverlayCross::showEvent(QShowEvent*)
-{
- if (d->UpdateRequired)
- {
- setupOverlayCross(d->Mode);
- }
- this->updatePosition();
-}
-
-
-//============================================================================
-void CDockOverlayCross::updatePosition()
-{
- resize(d->DockOverlay->size());
- QPoint TopLeft = d->DockOverlay->pos();
- QPoint Offest((this->width() - d->DockOverlay->width()) / 2,
- (this->height() - d->DockOverlay->height()) / 2);
- QPoint CrossTopLeft = TopLeft - Offest;
- move(CrossTopLeft);
-}
-
-
-//============================================================================
-void CDockOverlayCross::reset()
-{
- QList<DockWidgetArea> allAreas;
- allAreas << TopDockWidgetArea << RightDockWidgetArea
- << BottomDockWidgetArea << LeftDockWidgetArea << CenterDockWidgetArea;
- const DockWidgetAreas allowedAreas = d->DockOverlay->allowedAreas();
-
- // Update visibility of area widgets based on allowedAreas.
- for (int i = 0; i < allAreas.count(); ++i)
- {
- QPoint p = d->areaGridPosition(allAreas.at(i));
- QLayoutItem* item = d->GridLayout->itemAtPosition(p.x(), p.y());
- QWidget* w = nullptr;
- if (item && (w = item->widget()) != nullptr)
- {
- w->setVisible(allowedAreas.testFlag(allAreas.at(i)));
- }
- }
-}
-
-
-//============================================================================
-void CDockOverlayCross::setIconColors(const QString& Colors)
-{
- static const QMap<QString, int> ColorCompenentStringMap{
- {"Frame", CDockOverlayCross::FrameColor},
- {"Background", CDockOverlayCross::WindowBackgroundColor},
- {"Overlay", CDockOverlayCross::OverlayColor},
- {"Arrow", CDockOverlayCross::ArrowColor},
- {"Shadow", CDockOverlayCross::ShadowColor}};
-
-#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
- auto SkipEmptyParts = QString::SkipEmptyParts;
-#else
- auto SkipEmptyParts = Qt::SkipEmptyParts;
-#endif
- auto ColorList = Colors.split(' ', SkipEmptyParts);
- for (const auto& ColorListEntry : ColorList)
- {
- auto ComponentColor = ColorListEntry.split('=', SkipEmptyParts);
- int Component = ColorCompenentStringMap.value(ComponentColor[0], -1);
- if (Component < 0)
- {
- continue;
- }
- d->IconColors[Component] = QColor(ComponentColor[1]);
- }
-
- d->UpdateRequired = true;
-}
-
-//============================================================================
-QString CDockOverlayCross::iconColors() const
-{
- return QString();
-}
-
-
-
-} // namespace ads
-//----------------------------------------------------------------------------
-
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include "DockOverlay.h"
+
+#include <QPointer>
+#include <QPaintEvent>
+#include <QResizeEvent>
+#include <QMoveEvent>
+#include <QPainter>
+#include <QGridLayout>
+#include <QCursor>
+#include <QIcon>
+#include <QLabel>
+#include <QtGlobal>
+#include <QDebug>
+#include <QMap>
+#include <QWindow>
+
+#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
+ */
+struct DockOverlayPrivate
+{
+ CDockOverlay* _this;
+ DockWidgetAreas AllowedAreas = InvalidDockWidgetArea;
+ CDockOverlayCross* Cross;
+ QPointer<QWidget> TargetWidget;
+ DockWidgetArea LastLocation = InvalidDockWidgetArea;
+ bool DropPreviewEnabled = true;
+ CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay;
+ QRect DropAreaRect;
+ int TabIndex = InvalidTabIndex;
+ // Wayland: the global cursor position is not available, so the last drop
+ // position from the drag and drop events is cached here to drive the
+ // drop preview rectangle and the highlighted drop indicator
+ QPoint LastGlobalPos;
+ // Wayland: the overlay is temporarily reparented into whatever top level
+ // window it is shown over (see showOverlay), because a child widget cannot
+ // render over a foreign window. This is the stable home window (the dock
+ // manager's window) that the overlay is reparented back to when hidden, so
+ // it is never left as a child of a transient floating window that gets
+ // destroyed - which would delete this dock-manager-owned overlay with it.
+ QPointer<QWidget> HomeWindow;
+
+ /**
+ * 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);
+};
+
+/**
+ * Private data of CDockOverlayCross class
+ */
+struct DockOverlayCrossPrivate
+{
+ CDockOverlayCross* _this;
+ CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay;
+ CDockOverlay* DockOverlay;
+ QHash<DockWidgetArea, QWidget*> DropIndicatorWidgets;
+ QGridLayout* GridLayout;
+ QColor IconColors[5];
+ bool UpdateRequired = false;
+ double LastDevicePixelRatio = 0.1;
+
+ /**
+ * Private data constructor
+ */
+ DockOverlayCrossPrivate(CDockOverlayCross* _public) : _this(_public) {}
+
+ /**
+ *
+ * @param area
+ * @return
+ */
+ QPoint areaGridPosition(const DockWidgetArea area);
+
+
+ /**
+ * Palette based default icon colors
+ */
+ QColor defaultIconColor(CDockOverlayCross::eIconColor ColorIndex)
+ {
+ QPalette pal = _this->palette();
+ switch (ColorIndex)
+ {
+ case CDockOverlayCross::FrameColor: return pal.color(QPalette::Active, QPalette::Highlight);
+ case CDockOverlayCross::WindowBackgroundColor: return pal.color(QPalette::Active, QPalette::Base);
+ case CDockOverlayCross::OverlayColor:
+ {
+ QColor Color = pal.color(QPalette::Active, QPalette::Highlight);
+ Color.setAlpha(64);
+ return Color;
+ }
+ break;
+
+ case CDockOverlayCross::ArrowColor: return pal.color(QPalette::Active, QPalette::Base);
+ case CDockOverlayCross::ShadowColor:
+ {
+ QColor Color = pal.color(QPalette::Active, QPalette::Text);
+ Color.setAlpha(64);
+ return Color;
+ }
+ break;
+
+ default:
+ return QColor();
+ }
+
+ return QColor();
+ }
+
+ /**
+ * Stylehseet based icon colors
+ */
+ QColor iconColor(CDockOverlayCross::eIconColor ColorIndex)
+ {
+ QColor Color = IconColors[ColorIndex];
+ if (!Color.isValid())
+ {
+ Color = defaultIconColor(ColorIndex);
+ }
+ return Color;
+ }
+
+ //============================================================================
+ /**
+ * Helper function that returns the drop indicator width depending on the
+ * operating system
+ */
+ qreal dropIndicatiorWidth(QLabel* l) const
+ {
+ #if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ Q_UNUSED(l)
+ return 40;
+ #else
+ return static_cast<qreal>(l->fontMetrics().height()) * 3.f;
+ #endif
+ }
+
+
+ //============================================================================
+ QWidget* createDropIndicatorWidget(DockWidgetArea DockWidgetArea,
+ CDockOverlay::eMode Mode)
+ {
+ QLabel* l = new QLabel();
+ l->setObjectName("DockWidgetAreaLabel");
+
+ 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);
+ l->setAttribute(Qt::WA_TranslucentBackground);
+ l->setProperty("dockWidgetArea", DockWidgetArea);
+ return l;
+ }
+
+ //============================================================================
+ void updateDropIndicatorIcon(QWidget* DropIndicatorWidget)
+ {
+ QLabel* l = qobject_cast<QLabel*>(DropIndicatorWidget);
+ const qreal metric = dropIndicatiorWidth(l);
+ const QSizeF size(metric, metric);
+
+ int Area = l->property("dockWidgetArea").toInt();
+ l->setPixmap(createHighDpiDropIndicatorPixmap(size, (DockWidgetArea)Area, Mode));
+ }
+
+ //============================================================================
+ QPixmap createHighDpiDropIndicatorPixmap(const QSizeF& size, DockWidgetArea DockWidgetArea,
+ CDockOverlay::eMode Mode)
+ {
+ 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();
+#else
+ double DevicePixelRatio = _this->window()->devicePixelRatio();
+#endif
+ QSizeF PixmapSize = size * DevicePixelRatio;
+ QPixmap pm(PixmapSize.toSize());
+ pm.fill(QColor(0, 0, 0, 0));
+
+ QPainter p(&pm);
+ QPen pen = p.pen();
+ QRectF ShadowRect(pm.rect());
+ QRectF baseRect;
+ baseRect.setSize(ShadowRect.size() * 0.7);
+ baseRect.moveCenter(ShadowRect.center());
+
+ // Fill
+ QColor ShadowColor = iconColor(CDockOverlayCross::ShadowColor);
+ if (ShadowColor.alpha() == 255)
+ {
+ ShadowColor.setAlpha(64);
+ }
+ p.fillRect(ShadowRect, ShadowColor);
+
+ // Drop area rect.
+ p.save();
+ QRectF areaRect;
+ QLineF areaLine;
+ QRectF nonAreaRect;
+ switch (DockWidgetArea)
+ {
+ case TopDockWidgetArea:
+ areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
+ nonAreaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
+ areaLine = QLineF(areaRect.bottomLeft(), areaRect.bottomRight());
+ break;
+ case RightDockWidgetArea:
+ areaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
+ nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
+ areaLine = QLineF(areaRect.topLeft(), areaRect.bottomLeft());
+ break;
+ case BottomDockWidgetArea:
+ areaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
+ nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
+ areaLine = QLineF(areaRect.topLeft(), areaRect.topRight());
+ break;
+ case LeftDockWidgetArea:
+ areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
+ nonAreaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
+ areaLine = QLineF(areaRect.topRight(), areaRect.bottomRight());
+ break;
+ default:
+ break;
+ }
+
+ QSizeF baseSize = baseRect.size();
+ 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);
+ p.setBrush(overlayColor);
+ p.setPen(Qt::NoPen);
+ p.drawRect(areaRect);
+
+ pen = p.pen();
+ pen.setWidth(1);
+ pen.setColor(borderColor);
+ pen.setStyle(Qt::DashLine);
+ p.setPen(pen);
+ p.drawLine(areaLine);
+ }
+ p.restore();
+
+
+ p.save();
+ // Draw outer border
+ pen = p.pen();
+ pen.setColor(borderColor);
+ pen.setWidth(1);
+ p.setBrush(Qt::NoBrush);
+ p.setPen(pen);
+ p.drawRect(baseRect);
+
+ // draw window title bar
+ p.setBrush(borderColor);
+ QRectF FrameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10));
+ p.drawRect(FrameRect);
+ p.restore();
+
+
+ // Draw arrow for outer container drop indicators
+ if (IsOuterContainerArea)
+ {
+ QRectF ArrowRect;
+ ArrowRect.setSize(baseSize);
+ ArrowRect.setWidth(ArrowRect.width() / 4.6);
+ ArrowRect.setHeight(ArrowRect.height() / 2);
+ ArrowRect.moveCenter(QPointF(0, 0));
+ QPolygonF Arrow;
+ Arrow << ArrowRect.topLeft()
+ << QPointF( ArrowRect.right(), ArrowRect.center().y())
+ << ArrowRect.bottomLeft();
+ p.setPen(Qt::NoPen);
+ p.setBrush(iconColor(CDockOverlayCross::ArrowColor));
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.translate(nonAreaRect.center().x(), nonAreaRect.center().y());
+
+ switch (DockWidgetArea)
+ {
+ case TopDockWidgetArea:
+ p.rotate(-90);
+ break;
+ case RightDockWidgetArea:
+ break;
+ case BottomDockWidgetArea:
+ p.rotate(90);
+ break;
+ case LeftDockWidgetArea:
+ p.rotate(180);
+ break;
+ default:
+ break;
+ }
+
+ p.drawPolygon(Arrow);
+ }
+
+ pm.setDevicePixelRatio(DevicePixelRatio);
+ return pm;
+ }
+
+};
+
+
+//============================================================================
+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) :
+ // Wayland: the overlay must be a child widget of the target window. Top
+ // level windows cannot be positioned in screen coordinates on Wayland,
+ // so a Qt::Tool overlay would not align over the target dock area
+ QFrame(internal::isWayland() && parent ? parent->window() : parent),
+ d(new DockOverlayPrivate(this))
+{
+ d->Mode = Mode;
+ d->Cross = new CDockOverlayCross(this);
+ if (internal::isWayland())
+ {
+ // Remember the stable home window so hideOverlay() can reparent the
+ // overlay back to it (see HomeWindow), keeping it off transient
+ // floating windows that may be destroyed.
+ d->HomeWindow = parentWidget();
+ // A translucent child widget would become a native window
+ // (wl_subsurface) that takes part in the compositors drag and drop
+ // target picking and steals the drop focus from the dock container.
+ // A child widget composites with its parent without the attribute.
+ // WA_TransparentForMouseEvents lets a release on a drop indicator
+ // fall through to it
+ setAttribute(Qt::WA_TransparentForMouseEvents);
+ }
+ else
+ {
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
+#else
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
+#endif
+ setWindowOpacity(1);
+ setAttribute(Qt::WA_TranslucentBackground);
+ }
+ setWindowTitle("DockOverlay");
+ setAttribute(Qt::WA_NoSystemBackground);
+
+ d->Cross->setVisible(false);
+ setVisible(false);
+}
+
+
+//============================================================================
+CDockOverlay::~CDockOverlay()
+{
+ delete d;
+}
+
+
+//============================================================================
+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
+{
+ return d->AllowedAreas;
+}
+
+
+//============================================================================
+DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
+{
+ return dropAreaUnderCursor(QCursor::pos());
+}
+
+
+//============================================================================
+DockWidgetArea CDockOverlay::dropAreaUnderCursor(const QPoint& GlobalPos) const
+{
+ d->TabIndex = InvalidTabIndex;
+ if (!d->TargetWidget)
+ {
+ return InvalidDockWidgetArea;
+ }
+
+ DockWidgetArea Result = d->Cross->cursorLocation(GlobalPos);
+ if (Result != InvalidDockWidgetArea)
+ {
+ return Result;
+ }
+
+ auto CursorPos = GlobalPos;
+ auto DockArea = qobject_cast<CDockAreaWidget*>(d->TargetWidget.data());
+ if (!DockArea && CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled))
+ {
+ auto Rect = rect();
+ const QPoint pos = mapFromGlobal(GlobalPos);
+ 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(CursorPos)))
+ {
+ auto TabBar = DockArea->titleBar()->tabBar();
+ d->TabIndex = TabBar->tabInsertIndexAt(TabBar->mapFromGlobal(CursorPos));
+ return CenterDockWidgetArea;
+ }
+
+ return Result;
+}
+
+
+//============================================================================
+int CDockOverlay::tabIndexUnderCursor() const
+{
+ return d->TabIndex;
+}
+
+
+//============================================================================
+DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const
+{
+ return visibleDropAreaUnderCursor(QCursor::pos());
+}
+
+
+//============================================================================
+DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor(const QPoint& GlobalPos) const
+{
+ if (isHidden() || !d->DropPreviewEnabled)
+ {
+ return InvalidDockWidgetArea;
+ }
+ else
+ {
+ return dropAreaUnderCursor(GlobalPos);
+ }
+}
+
+
+//============================================================================
+DockWidgetArea CDockOverlay::showOverlay(QWidget* target)
+{
+ return showOverlay(target, QCursor::pos());
+}
+
+
+//============================================================================
+DockWidgetArea CDockOverlay::showOverlay(QWidget* target, const QPoint& GlobalPos)
+{
+ // Cache the drag position that drives this overlay's drop preview. On
+ // Wayland paintEvent() reads it back because the global cursor position is
+ // not available during a platform drag; it must be current before the
+ // show()/repaint() below triggers a paint
+ d->LastGlobalPos = GlobalPos;
+
+ // Wayland: a cross window drop (e.g. into a floating widget) requires the
+ // overlay to be a child of the target window because a widget cannot be
+ // positioned over a foreign window
+ if (internal::isWayland() && parentWidget() != target->window())
+ {
+ setParent(target->window());
+ d->Cross->setParent(target->window());
+ d->TargetWidget = nullptr;
+ }
+
+ if (d->TargetWidget == target)
+ {
+ // Hint: We could update geometry of overlay here.
+ DockWidgetArea da = dropAreaUnderCursor(GlobalPos);
+ if (da != d->LastLocation)
+ {
+ repaint();
+ d->LastLocation = da;
+ }
+ return da;
+ }
+
+ d->TargetWidget = target;
+ d->LastLocation = InvalidDockWidgetArea;
+
+ // Move it over the target.
+ hide();
+ resize(target->size());
+ QPoint TopLeft = target->mapToGlobal(target->rect().topLeft());
+ // Wayland: the overlay is a child of the target window, so the target top
+ // left has to be mapped into the parent coordinate system
+ if (internal::isWayland() && parentWidget())
+ {
+ move(parentWidget()->mapFromGlobal(TopLeft));
+ }
+ else
+ {
+ move(TopLeft);
+ }
+ show();
+ if (internal::isWayland())
+ {
+ // paint the child overlay above its sibling dock widgets
+ raise();
+ }
+ d->Cross->updatePosition();
+ d->Cross->updateOverlayIcons();
+ return dropAreaUnderCursor(GlobalPos);
+}
+
+
+//============================================================================
+void CDockOverlay::hideOverlay()
+{
+ hide();
+ // Wayland: showOverlay() reparents this overlay (and its cross) into the
+ // top level window it is shown over. Reparent them back to the stable home
+ // window now that the overlay is hidden, so the dock-manager-owned overlay
+ // is never left as a child of a transient floating window - destroying that
+ // window would otherwise delete the overlay and leave the dock manager with
+ // a dangling pointer.
+ if (internal::isWayland() && d->HomeWindow && parentWidget() != d->HomeWindow)
+ {
+ setParent(d->HomeWindow);
+ d->Cross->setParent(d->HomeWindow);
+ }
+ d->TargetWidget.clear();
+ d->LastLocation = InvalidDockWidgetArea;
+ d->DropAreaRect = QRect();
+}
+
+
+//============================================================================
+void CDockOverlay::enableDropPreview(bool Enable)
+{
+ d->DropPreviewEnabled = Enable;
+ update();
+}
+
+
+//============================================================================
+bool CDockOverlay::dropPreviewEnabled() const
+{
+ return d->DropPreviewEnabled;
+}
+
+
+//============================================================================
+void CDockOverlay::paintEvent(QPaintEvent* event)
+{
+ Q_UNUSED(event);
+
+ // Draw rect based on location
+ if (!d->DropPreviewEnabled)
+ {
+ d->DropAreaRect = QRect();
+ return;
+ }
+
+ QRect r = rect();
+ // Wayland: use the cached drag position because the global cursor
+ // position is not available during a platform drag
+ const DockWidgetArea da = internal::isWayland()
+ ? dropAreaUnderCursor(d->LastGlobalPos) : dropAreaUnderCursor();
+ double Factor = (CDockOverlay::ModeContainerOverlay == d->Mode) ?
+ 3 : 2;
+
+ switch (da)
+ {
+ case TopDockWidgetArea: r.setHeight(r.height() / Factor); break;
+ case RightDockWidgetArea: r.setX(r.width() * (1 - 1 / Factor)); break;
+ 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();
+ Pen.setColor(Color.darker(120));
+ Pen.setStyle(Qt::SolidLine);
+ Pen.setWidth(1);
+ Pen.setCosmetic(true);
+ painter.setPen(Pen);
+ Color = Color.lighter(130);
+ Color.setAlpha(64);
+ painter.setBrush(Color);
+ painter.drawRect(r.adjusted(0, 0, -1, -1));
+ d->DropAreaRect = r;
+}
+
+
+//============================================================================
+QRect CDockOverlay::dropOverlayRect() const
+{
+ return d->DropAreaRect;
+}
+
+
+//============================================================================
+void CDockOverlay::showEvent(QShowEvent* e)
+{
+ d->Cross->show();
+ QFrame::showEvent(e);
+}
+
+
+//============================================================================
+void CDockOverlay::hideEvent(QHideEvent* e)
+{
+ d->Cross->hide();
+ QFrame::hideEvent(e);
+}
+
+
+//============================================================================
+bool CDockOverlay::event(QEvent *e)
+{
+ bool Result = Super::event(e);
+ if (e->type() == QEvent::Polish)
+ {
+ d->Cross->setupOverlayCross(d->Mode);
+ }
+ return Result;
+}
+
+
+//============================================================================
+static int areaAlignment(const DockWidgetArea area)
+{
+ switch (area)
+ {
+ case TopDockWidgetArea: return (int) Qt::AlignHCenter | Qt::AlignBottom;
+ case RightDockWidgetArea: return (int) Qt::AlignLeft | Qt::AlignVCenter;
+ case BottomDockWidgetArea: return (int) Qt::AlignHCenter | Qt::AlignTop;
+ case LeftDockWidgetArea: return (int) Qt::AlignRight | Qt::AlignVCenter;
+ case CenterDockWidgetArea: return (int) Qt::AlignCenter;
+ default: return Qt::AlignCenter;
+ }
+}
+
+//============================================================================
+// DockOverlayCrossPrivate
+//============================================================================
+QPoint DockOverlayCrossPrivate::areaGridPosition(const DockWidgetArea area)
+{
+ if (CDockOverlay::ModeDockAreaOverlay == Mode)
+ {
+ switch (area)
+ {
+ case TopDockWidgetArea: return QPoint(1, 2);
+ case RightDockWidgetArea: return QPoint(2, 3);
+ case BottomDockWidgetArea: return QPoint(3, 2);
+ case LeftDockWidgetArea: return QPoint(2, 1);
+ case CenterDockWidgetArea: return QPoint(2, 2);
+ default: return QPoint();
+ }
+ }
+ else
+ {
+ switch (area)
+ {
+ case TopDockWidgetArea: return QPoint(0, 2);
+ case RightDockWidgetArea: return QPoint(2, 4);
+ case BottomDockWidgetArea: return QPoint(4, 2);
+ case LeftDockWidgetArea: return QPoint(2, 0);
+ case CenterDockWidgetArea: return QPoint(2, 2);
+ default: return QPoint();
+ }
+ }
+}
+
+
+//============================================================================
+CDockOverlayCross::CDockOverlayCross(CDockOverlay* overlay) :
+ // Wayland: see CDockOverlay - the cross must be a child of the target
+ // window for the same reason as the overlay
+ QWidget(internal::isWayland() && overlay->parentWidget()
+ ? overlay->parentWidget()->window() : overlay->parentWidget()),
+ d(new DockOverlayCrossPrivate(this))
+{
+ d->DockOverlay = overlay;
+ if (internal::isWayland())
+ {
+ setAttribute(Qt::WA_TransparentForMouseEvents);
+ }
+ else
+ {
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
+#else
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
+#endif
+ setAttribute(Qt::WA_TranslucentBackground);
+ }
+ setWindowTitle("DockOverlayCross");
+
+ d->GridLayout = new QGridLayout();
+ d->GridLayout->setSpacing(0);
+ setLayout(d->GridLayout);
+}
+
+
+//============================================================================
+CDockOverlayCross::~CDockOverlayCross()
+{
+ delete d;
+}
+
+
+//============================================================================
+void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode)
+{
+ d->Mode = Mode;
+
+ QHash<DockWidgetArea, QWidget*> areaWidgets;
+ areaWidgets.insert(TopDockWidgetArea, d->createDropIndicatorWidget(TopDockWidgetArea, Mode));
+ areaWidgets.insert(RightDockWidgetArea, d->createDropIndicatorWidget(RightDockWidgetArea, 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
+ d->LastDevicePixelRatio = devicePixelRatio();
+#endif
+ setAreaWidgets(areaWidgets);
+ d->UpdateRequired = false;
+}
+
+
+//============================================================================
+void CDockOverlayCross::updateOverlayIcons()
+{
+ // Wayland: the cross is a child widget and has no window handle, so the
+ // device pixel ratio is taken from the widget instead of the window
+ const qreal DevicePixelRatio = internal::isWayland()
+ ? devicePixelRatioF() : windowHandle()->devicePixelRatio();
+ if (DevicePixelRatio == d->LastDevicePixelRatio)
+ {
+ return;
+ }
+
+ for (auto Widget : d->DropIndicatorWidgets)
+ {
+ d->updateDropIndicatorIcon(Widget);
+ }
+#if QT_VERSION >= 0x050600
+ d->LastDevicePixelRatio = devicePixelRatioF();
+#else
+ d->LastDevicePixelRatio = devicePixelRatio();
+#endif
+}
+
+
+//============================================================================
+void CDockOverlayCross::setIconColor(eIconColor ColorIndex, const QColor& Color)
+{
+ d->IconColors[ColorIndex] = Color;
+ d->UpdateRequired = true;
+}
+
+
+//============================================================================
+QColor CDockOverlayCross::iconColor(eIconColor ColorIndex) const
+{
+ return d->IconColors[ColorIndex];
+}
+
+
+//============================================================================
+void CDockOverlayCross::setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets)
+{
+ // Delete old widgets.
+ QMutableHashIterator<DockWidgetArea, QWidget*> i(d->DropIndicatorWidgets);
+ while (i.hasNext())
+ {
+ i.next();
+ QWidget* widget = i.value();
+ d->GridLayout->removeWidget(widget);
+ delete widget;
+ i.remove();
+ }
+
+ // Insert new widgets into grid.
+ d->DropIndicatorWidgets = widgets;
+ QHashIterator<DockWidgetArea, QWidget*> i2(d->DropIndicatorWidgets);
+ while (i2.hasNext())
+ {
+ i2.next();
+ const DockWidgetArea area = i2.key();
+ QWidget* widget = i2.value();
+ QPoint p = d->areaGridPosition(area);
+ d->GridLayout->addWidget(widget, p.x(), p.y(), (Qt::Alignment) areaAlignment(area));
+ }
+
+ if (CDockOverlay::ModeDockAreaOverlay == d->Mode)
+ {
+ d->GridLayout->setContentsMargins(0, 0, 0, 0);
+ d->GridLayout->setRowStretch(0, 1);
+ d->GridLayout->setRowStretch(1, 0);
+ d->GridLayout->setRowStretch(2, 0);
+ d->GridLayout->setRowStretch(3, 0);
+ d->GridLayout->setRowStretch(4, 1);
+
+ d->GridLayout->setColumnStretch(0, 1);
+ d->GridLayout->setColumnStretch(1, 0);
+ d->GridLayout->setColumnStretch(2, 0);
+ d->GridLayout->setColumnStretch(3, 0);
+ d->GridLayout->setColumnStretch(4, 1);
+ }
+ else
+ {
+ d->GridLayout->setContentsMargins(4, 4, 4, 4);
+ d->GridLayout->setRowStretch(0, 0);
+ d->GridLayout->setRowStretch(1, 1);
+ d->GridLayout->setRowStretch(2, 1);
+ d->GridLayout->setRowStretch(3, 1);
+ d->GridLayout->setRowStretch(4, 0);
+
+ d->GridLayout->setColumnStretch(0, 0);
+ d->GridLayout->setColumnStretch(1, 1);
+ d->GridLayout->setColumnStretch(2, 1);
+ d->GridLayout->setColumnStretch(3, 1);
+ d->GridLayout->setColumnStretch(4, 0);
+ }
+ reset();
+}
+
+
+//============================================================================
+DockWidgetArea CDockOverlayCross::cursorLocation() const
+{
+ return cursorLocation(QCursor::pos());
+}
+
+
+//============================================================================
+DockWidgetArea CDockOverlayCross::cursorLocation(const QPoint& GlobalPos) const
+{
+ const QPoint pos = mapFromGlobal(GlobalPos);
+ QHashIterator<DockWidgetArea, QWidget*> i(d->DropIndicatorWidgets);
+ while (i.hasNext())
+ {
+ i.next();
+ if (d->DockOverlay->allowedAreas().testFlag(i.key())
+ && i.value()
+ && i.value()->isVisible()
+ && i.value()->geometry().contains(pos))
+ {
+ return i.key();
+ }
+ }
+ return InvalidDockWidgetArea;
+}
+
+
+//============================================================================
+void CDockOverlayCross::showEvent(QShowEvent*)
+{
+ if (d->UpdateRequired)
+ {
+ setupOverlayCross(d->Mode);
+ }
+ this->updatePosition();
+}
+
+
+//============================================================================
+bool CDockOverlayCross::event(QEvent *e)
+{
+ bool Result = QWidget::event(e);
+
+ if (e->type() == QEvent::ApplicationPaletteChange)
+ {
+ d->UpdateRequired = true;
+ }
+
+ return Result;
+}
+
+
+//============================================================================
+void CDockOverlayCross::updatePosition()
+{
+ resize(d->DockOverlay->size());
+ QPoint TopLeft = d->DockOverlay->pos();
+ QPoint Offest((this->width() - d->DockOverlay->width()) / 2,
+ (this->height() - d->DockOverlay->height()) / 2);
+ QPoint CrossTopLeft = TopLeft - Offest;
+ move(CrossTopLeft);
+ if (internal::isWayland())
+ {
+ // paint the child cross above its sibling dock widgets
+ raise();
+ }
+}
+
+
+//============================================================================
+void CDockOverlayCross::reset()
+{
+ QList<DockWidgetArea> allAreas;
+ allAreas << TopDockWidgetArea << RightDockWidgetArea
+ << BottomDockWidgetArea << LeftDockWidgetArea << CenterDockWidgetArea;
+ const DockWidgetAreas allowedAreas = d->DockOverlay->allowedAreas();
+
+ // Update visibility of area widgets based on allowedAreas.
+ for (int i = 0; i < allAreas.count(); ++i)
+ {
+ QPoint p = d->areaGridPosition(allAreas.at(i));
+ QLayoutItem* item = d->GridLayout->itemAtPosition(p.x(), p.y());
+ QWidget* w = nullptr;
+ if (item && (w = item->widget()) != nullptr)
+ {
+ w->setVisible(allowedAreas.testFlag(allAreas.at(i)));
+ }
+ }
+}
+
+
+//============================================================================
+void CDockOverlayCross::setIconColors(const QString& Colors)
+{
+ static const QMap<QString, int> ColorCompenentStringMap{
+ {"Frame", CDockOverlayCross::FrameColor},
+ {"Background", CDockOverlayCross::WindowBackgroundColor},
+ {"Overlay", CDockOverlayCross::OverlayColor},
+ {"Arrow", CDockOverlayCross::ArrowColor},
+ {"Shadow", CDockOverlayCross::ShadowColor}};
+
+#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
+ auto SkipEmptyParts = QString::SkipEmptyParts;
+#else
+ auto SkipEmptyParts = Qt::SkipEmptyParts;
+#endif
+ auto ColorList = Colors.split(' ', SkipEmptyParts);
+ for (const auto& ColorListEntry : ColorList)
+ {
+ auto ComponentColor = ColorListEntry.split('=', SkipEmptyParts);
+ int Component = ColorCompenentStringMap.value(ComponentColor[0], -1);
+ if (Component < 0)
+ {
+ continue;
+ }
+ d->IconColors[Component] = QColor(ComponentColor[1]);
+ }
+
+ d->UpdateRequired = true;
+}
+
+//============================================================================
+QString CDockOverlayCross::iconColors() const
+{
+ return QString();
+}
+
+
+
+} // namespace ads
+//----------------------------------------------------------------------------
+
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockOverlay.h b/scribus/third_party/Qt-Advanced-Docking-System/src/DockOverlay.h
index 00d1461bb..db58eeec6 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockOverlay.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockOverlay.h
@@ -1,280 +1,308 @@
-#ifndef DockOverlayH
-#define DockOverlayH
-/*******************************************************************************
-** Qt Advanced Docking System
-** Copyright (C) 2017 Uwe Kindler
-**
-** This library is free software; you can redistribute it and/or
-** modify it under the terms of the GNU Lesser General Public
-** License as published by the Free Software Foundation; either
-** version 2.1 of the License, or (at your option) any later version.
-**
-** This library is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-** Lesser General Public License for more details.
-**
-** You should have received a copy of the GNU Lesser General Public
-** License along with this library; If not, see <http://www.gnu.org/licenses/>.
-******************************************************************************/
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include <QPointer>
-#include <QHash>
-#include <QRect>
-#include <QFrame>
-
-#include "ads_globals.h"
-
-QT_FORWARD_DECLARE_CLASS(QGridLayout)
-
-namespace ads
-{
-struct DockOverlayPrivate;
-class CDockOverlayCross;
-
-/*!
- * DockOverlay paints a translucent rectangle over another widget. The geometry
- * of the rectangle is based on the mouse location.
- */
-class ADS_EXPORT CDockOverlay : public QFrame
-{
- Q_OBJECT
-private:
- DockOverlayPrivate* d; //< private data class
- friend struct DockOverlayPrivate;
- friend class DockOverlayCross;
-
-public:
- using Super = QFrame;
-
- enum eMode
- {
- ModeDockAreaOverlay,
- ModeContainerOverlay
- };
-
- /**
- * Creates a dock overlay
- */
- CDockOverlay(QWidget* parent, eMode Mode = ModeDockAreaOverlay);
-
- /**
- * Virtual destructor
- */
- virtual ~CDockOverlay();
-
- /**
- * Configures the areas that are allowed for docking
- */
- void setAllowedAreas(DockWidgetAreas areas);
-
- /**
- * Enable / disable a certain area
- */
- void setAllowedArea(DockWidgetArea area, bool Enable);
-
- /**
- * Returns flags with all allowed drop areas
- */
- DockWidgetAreas allowedAreas() const;
-
- /**
- * Returns the drop area under the current cursor location
- */
- 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
- * InvalidDockWidgetArea if it is hidden or drop preview is disabled.
- */
- DockWidgetArea visibleDropAreaUnderCursor() const;
-
- /**
- * Show the drop overly for the given target widget
- */
- DockWidgetArea showOverlay(QWidget* target);
-
- /**
- * Hides the overlay
- */
- void hideOverlay();
-
- /**
- * Enables / disables the semi transparent overlay rectangle that represents
- * the future area of the dropped widget
- */
- void enableDropPreview(bool Enable);
-
- /**
- * Returns true if drop preview is enabled
- */
- bool dropPreviewEnabled() const;
-
- /**
- * The drop overlay rectangle for the target area
- */
- QRect dropOverlayRect() const;
-
- /**
- * Handle polish events
- */
- virtual bool event(QEvent *e) override;
-
-protected:
- virtual void paintEvent(QPaintEvent *e) override;
- virtual void showEvent(QShowEvent* e) override;
- virtual void hideEvent(QHideEvent* e) override;
-};
-
-
-struct DockOverlayCrossPrivate;
-/*!
- * DockOverlayCross shows a cross with 5 different drop area possibilities.
- * I could have handled everything inside DockOverlay, but because of some
- * styling issues it's better to have a separate class for the cross.
- * You can style the cross icon using the property system.
- * \code
- * ads--CDockOverlayCross
- {
- qproperty-iconFrameColor: palette(highlight);
- qproperty-iconBackgroundColor: palette(base);
- qproperty-iconOverlayColor: palette(highlight);
- qproperty-iconArrowColor: rgb(227, 227, 227);
- qproperty-iconShadowColor: rgb(0, 0, 0);
- }
- * \endcode
- * Or you can use the iconColors property to pass in AARRGGBB values as
- * hex string like shown in the example below.
- * \code
- * ads--CDockOverlayCross
- * {
- * qproperty-iconColors: "Frame=#ff3d3d3d Background=#ff929292 Overlay=#1f3d3d3d Arrow=#ffb4b4b4 Shadow=#40474747";
- * }
- * \endcode
- */
-class CDockOverlayCross : public QWidget
-{
- Q_OBJECT
- Q_PROPERTY(QString iconColors READ iconColors WRITE setIconColors)
- Q_PROPERTY(QColor iconFrameColor READ iconColor WRITE setIconFrameColor)
- Q_PROPERTY(QColor iconBackgroundColor READ iconColor WRITE setIconBackgroundColor)
- Q_PROPERTY(QColor iconOverlayColor READ iconColor WRITE setIconOverlayColor)
- Q_PROPERTY(QColor iconArrowColor READ iconColor WRITE setIconArrowColor)
- Q_PROPERTY(QColor iconShadowColor READ iconColor WRITE setIconShadowColor)
-
-public:
- enum eIconColor
- {
- FrameColor,///< the color of the frame of the small window icon
- WindowBackgroundColor,///< the background color of the small window in the icon
- OverlayColor,///< the color that shows the overlay (the dock side) in the icon
- ArrowColor,///< the arrow that points into the direction
- ShadowColor///< the color of the shadow rectangle that is painted below the icons
- };
-
-private:
- DockOverlayCrossPrivate* d;
- friend struct DockOverlayCrossPrivate;
- friend class CDockOverlay;
-
-protected:
- /**
- * This function returns an empty string and is only here to silence
- * moc
- */
- QString iconColors() const;
-
- /**
- * This is a dummy function for the property system
- */
- QColor iconColor() const {return QColor();}
- void setIconFrameColor(const QColor& Color) {setIconColor(FrameColor, Color);}
- void setIconBackgroundColor(const QColor& Color) {setIconColor(WindowBackgroundColor, Color);}
- void setIconOverlayColor(const QColor& Color) {setIconColor(OverlayColor, Color);}
- void setIconArrowColor(const QColor& Color) {setIconColor(ArrowColor, Color);}
- void setIconShadowColor(const QColor& Color) {setIconColor(ShadowColor, Color);}
-
-public:
- /**
- * Creates an overlay cross for the given overlay
- */
- CDockOverlayCross(CDockOverlay* overlay);
-
- /**
- * Virtual destructor
- */
- virtual ~CDockOverlayCross();
-
- /**
- * Sets a certain icon color
- */
- void setIconColor(eIconColor ColorIndex, const QColor& Color);
-
- /**
- * Returns the icon color given by ColorIndex
- */
- QColor iconColor(eIconColor ColorIndex) const;
-
- /**
- * Returns the dock widget area depending on the current cursor location.
- * The function checks, if the mouse cursor is inside of any drop indicator
- * widget and returns the corresponding DockWidgetArea.
- */
- DockWidgetArea cursorLocation() const;
-
- /**
- * Sets up the overlay cross for the given overlay mode
- */
- void setupOverlayCross(CDockOverlay::eMode Mode);
-
- /**
- * Recreates the overlay icons.
- */
- void updateOverlayIcons();
-
- /**
- * Resets and updates the
- */
- void reset();
-
- /**
- * Updates the current position
- */
- void updatePosition();
-
- /**
- * A string with all icon colors to set.
- * You can use this property to style the overly icon via CSS stylesheet
- * file. The colors are set via a color identifier and a hex AARRGGBB value like
- * in the example below.
- * \code
- * ads--CDockOverlayCross
- * {
- * qproperty-iconColors: "Frame=#ff3d3d3d Background=#ff929292 Overlay=#1f3d3d3d Arrow=#ffb4b4b4 Shadow=#40474747";
- * }
- */
- void setIconColors(const QString& Colors);
-
-protected:
- virtual void showEvent(QShowEvent* e) override;
- void setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets);
-}; // CDockOverlayCross
-
-} // namespace ads
-#endif // DockOverlayH
+#ifndef DockOverlayH
+#define DockOverlayH
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include <QPointer>
+#include <QHash>
+#include <QRect>
+#include <QFrame>
+
+#include "ads_globals.h"
+
+QT_FORWARD_DECLARE_CLASS(QGridLayout)
+
+namespace ads
+{
+struct DockOverlayPrivate;
+class CDockOverlayCross;
+
+/*!
+ * DockOverlay paints a translucent rectangle over another widget. The geometry
+ * of the rectangle is based on the mouse location.
+ */
+class ADS_EXPORT CDockOverlay : public QFrame
+{
+ Q_OBJECT
+private:
+ DockOverlayPrivate* d; //< private data class
+ friend struct DockOverlayPrivate;
+ friend class DockOverlayCross;
+
+public:
+ using Super = QFrame;
+
+ enum eMode
+ {
+ ModeDockAreaOverlay,
+ ModeContainerOverlay
+ };
+
+ /**
+ * Creates a dock overlay
+ */
+ CDockOverlay(QWidget* parent, eMode Mode = ModeDockAreaOverlay);
+
+ /**
+ * Virtual destructor
+ */
+ virtual ~CDockOverlay();
+
+ /**
+ * Configures the areas that are allowed for docking
+ */
+ void setAllowedAreas(DockWidgetAreas areas);
+
+ /**
+ * Enable / disable a certain area
+ */
+ void setAllowedArea(DockWidgetArea area, bool Enable);
+
+ /**
+ * Returns flags with all allowed drop areas
+ */
+ DockWidgetAreas allowedAreas() const;
+
+ /**
+ * Returns the drop area under the current cursor location
+ */
+ DockWidgetArea dropAreaUnderCursor() const;
+
+ /**
+ * Returns the drop area under the given global position.
+ * Use this overload if the position does not come from the mouse cursor
+ * (e.g. from drag and drop events on Wayland, where the global cursor
+ * position is not available)
+ */
+ DockWidgetArea dropAreaUnderCursor(const QPoint& GlobalPos) 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
+ * InvalidDockWidgetArea if it is hidden or drop preview is disabled.
+ */
+ DockWidgetArea visibleDropAreaUnderCursor() const;
+
+ /**
+ * This function returns the same like dropAreaUnderCursor(GlobalPos) if
+ * this overlay is not hidden and if drop preview is enabled and returns
+ * InvalidDockWidgetArea if it is hidden or drop preview is disabled.
+ */
+ DockWidgetArea visibleDropAreaUnderCursor(const QPoint& GlobalPos) const;
+
+ /**
+ * Show the drop overly for the given target widget
+ */
+ DockWidgetArea showOverlay(QWidget* target);
+
+ /**
+ * Show the drop overlay for the given target widget and evaluate the
+ * drop area for the given global position instead of the cursor position
+ */
+ DockWidgetArea showOverlay(QWidget* target, const QPoint& GlobalPos);
+
+ /**
+ * Hides the overlay
+ */
+ void hideOverlay();
+
+ /**
+ * Enables / disables the semi transparent overlay rectangle that represents
+ * the future area of the dropped widget
+ */
+ void enableDropPreview(bool Enable);
+
+ /**
+ * Returns true if drop preview is enabled
+ */
+ bool dropPreviewEnabled() const;
+
+ /**
+ * The drop overlay rectangle for the target area
+ */
+ QRect dropOverlayRect() const;
+
+ /**
+ * Handle polish events
+ */
+ virtual bool event(QEvent *e) override;
+
+protected:
+ virtual void paintEvent(QPaintEvent *e) override;
+ virtual void showEvent(QShowEvent* e) override;
+ virtual void hideEvent(QHideEvent* e) override;
+};
+
+
+struct DockOverlayCrossPrivate;
+/*!
+ * DockOverlayCross shows a cross with 5 different drop area possibilities.
+ * I could have handled everything inside DockOverlay, but because of some
+ * styling issues it's better to have a separate class for the cross.
+ * You can style the cross icon using the property system.
+ * \code
+ * ads--CDockOverlayCross
+ {
+ qproperty-iconFrameColor: palette(highlight);
+ qproperty-iconBackgroundColor: palette(base);
+ qproperty-iconOverlayColor: palette(highlight);
+ qproperty-iconArrowColor: rgb(227, 227, 227);
+ qproperty-iconShadowColor: rgb(0, 0, 0);
+ }
+ * \endcode
+ * Or you can use the iconColors property to pass in AARRGGBB values as
+ * hex string like shown in the example below.
+ * \code
+ * ads--CDockOverlayCross
+ * {
+ * qproperty-iconColors: "Frame=#ff3d3d3d Background=#ff929292 Overlay=#1f3d3d3d Arrow=#ffb4b4b4 Shadow=#40474747";
+ * }
+ * \endcode
+ */
+class CDockOverlayCross : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QString iconColors READ iconColors WRITE setIconColors)
+ Q_PROPERTY(QColor iconFrameColor READ iconColor WRITE setIconFrameColor)
+ Q_PROPERTY(QColor iconBackgroundColor READ iconColor WRITE setIconBackgroundColor)
+ Q_PROPERTY(QColor iconOverlayColor READ iconColor WRITE setIconOverlayColor)
+ Q_PROPERTY(QColor iconArrowColor READ iconColor WRITE setIconArrowColor)
+ Q_PROPERTY(QColor iconShadowColor READ iconColor WRITE setIconShadowColor)
+
+public:
+ enum eIconColor
+ {
+ FrameColor,///< the color of the frame of the small window icon
+ WindowBackgroundColor,///< the background color of the small window in the icon
+ OverlayColor,///< the color that shows the overlay (the dock side) in the icon
+ ArrowColor,///< the arrow that points into the direction
+ ShadowColor///< the color of the shadow rectangle that is painted below the icons
+ };
+
+private:
+ DockOverlayCrossPrivate* d;
+ friend struct DockOverlayCrossPrivate;
+ friend class CDockOverlay;
+
+protected:
+ /**
+ * This function returns an empty string and is only here to silence
+ * moc
+ */
+ QString iconColors() const;
+
+ /**
+ * This is a dummy function for the property system
+ */
+ QColor iconColor() const {return QColor();}
+ void setIconFrameColor(const QColor& Color) {setIconColor(FrameColor, Color);}
+ void setIconBackgroundColor(const QColor& Color) {setIconColor(WindowBackgroundColor, Color);}
+ void setIconOverlayColor(const QColor& Color) {setIconColor(OverlayColor, Color);}
+ void setIconArrowColor(const QColor& Color) {setIconColor(ArrowColor, Color);}
+ void setIconShadowColor(const QColor& Color) {setIconColor(ShadowColor, Color);}
+
+public:
+ /**
+ * Creates an overlay cross for the given overlay
+ */
+ CDockOverlayCross(CDockOverlay* overlay);
+
+ /**
+ * Virtual destructor
+ */
+ virtual ~CDockOverlayCross();
+
+ /**
+ * Sets a certain icon color
+ */
+ void setIconColor(eIconColor ColorIndex, const QColor& Color);
+
+ /**
+ * Returns the icon color given by ColorIndex
+ */
+ QColor iconColor(eIconColor ColorIndex) const;
+
+ /**
+ * Returns the dock widget area depending on the current cursor location.
+ * The function checks, if the mouse cursor is inside of any drop indicator
+ * widget and returns the corresponding DockWidgetArea.
+ */
+ DockWidgetArea cursorLocation() const;
+
+ /**
+ * The function checks, if the given global position is inside of any
+ * drop indicator widget and returns the corresponding DockWidgetArea.
+ */
+ DockWidgetArea cursorLocation(const QPoint& GlobalPos) const;
+
+ /**
+ * Sets up the overlay cross for the given overlay mode
+ */
+ void setupOverlayCross(CDockOverlay::eMode Mode);
+
+ /**
+ * Recreates the overlay icons.
+ */
+ void updateOverlayIcons();
+
+ /**
+ * Resets and updates the
+ */
+ void reset();
+
+ /**
+ * Updates the current position
+ */
+ void updatePosition();
+
+ /**
+ * A string with all icon colors to set.
+ * You can use this property to style the overly icon via CSS stylesheet
+ * file. The colors are set via a color identifier and a hex AARRGGBB value like
+ * in the example below.
+ * \code
+ * ads--CDockOverlayCross
+ * {
+ * qproperty-iconColors: "Frame=#ff3d3d3d Background=#ff929292 Overlay=#1f3d3d3d Arrow=#ffb4b4b4 Shadow=#40474747";
+ * }
+ */
+ void setIconColors(const QString& Colors);
+
+protected:
+ virtual void showEvent(QShowEvent* e) override;
+ virtual bool event(QEvent* e) override;
+ void setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets);
+}; // CDockOverlayCross
+
+} // namespace ads
+#endif // DockOverlayH
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockSplitter.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/DockSplitter.cpp
index 2aba642b6..33f617236 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockSplitter.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockSplitter.cpp
@@ -1,122 +1,122 @@
-/*******************************************************************************
-** Qt Advanced Docking System
-** Copyright (C) 2017 Uwe Kindler
-**
-** This library is free software; you can redistribute it and/or
-** modify it under the terms of the GNU Lesser General Public
-** License as published by the Free Software Foundation; either
-** version 2.1 of the License, or (at your option) any later version.
-**
-** This library is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-** Lesser General Public License for more details.
-**
-** You should have received a copy of the GNU Lesser General Public
-** License along with this library; If not, see <http://www.gnu.org/licenses/>.
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockSplitter.cpp
-/// \author Uwe Kindler
-/// \date 24.03.2017
-/// \brief Implementation of CDockSplitter
-//============================================================================
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include "DockSplitter.h"
-
-#include <QDebug>
-#include <QChildEvent>
-#include <QVariant>
-#include "DockAreaWidget.h"
-
-namespace ads
-{
-/**
- * Private dock splitter data
- */
-struct DockSplitterPrivate
-{
- CDockSplitter* _this;
- int VisibleContentCount = 0;
-
- DockSplitterPrivate(CDockSplitter* _public) : _this(_public) {}
-};
-
-//============================================================================
-CDockSplitter::CDockSplitter(QWidget *parent)
- : QSplitter(parent),
- d(new DockSplitterPrivate(this))
-{
- setProperty("ads-splitter", QVariant(true));
- setChildrenCollapsible(false);
-}
-
-
-//============================================================================
-CDockSplitter::CDockSplitter(Qt::Orientation orientation, QWidget *parent)
- : QSplitter(orientation, parent),
- d(new DockSplitterPrivate(this))
-{
-
-}
-
-//============================================================================
-CDockSplitter::~CDockSplitter()
-{
- ADS_PRINT("~CDockSplitter");
- delete d;
-}
-
-
-//============================================================================
-bool CDockSplitter::hasVisibleContent() const
-{
- // TODO Cache or precalculate this to speed up
- for (int i = 0; i < count(); ++i)
- {
- if (!widget(i)->isHidden())
- {
- return true;
- }
- }
-
- return false;
-}
-
-
-//============================================================================
-QWidget* CDockSplitter::firstWidget() const
-{
- return (count() > 0) ? widget(0) : nullptr;
-}
-
-
-//============================================================================
-QWidget* CDockSplitter::lastWidget() const
-{
- return (count() > 0) ? widget(count() - 1) : nullptr;
-}
-
-//============================================================================
-bool CDockSplitter::isResizingWithContainer() const
-{
- for (auto area : findChildren<CDockAreaWidget*>())
- {
- if(area->isCentralWidgetArea())
- {
- return true;
- }
- }
-
- return false;
-}
-
-} // namespace ads
-
-//---------------------------------------------------------------------------
-// EOF DockSplitter.cpp
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockSplitter.cpp
+/// \author Uwe Kindler
+/// \date 24.03.2017
+/// \brief Implementation of CDockSplitter
+//============================================================================
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include "DockSplitter.h"
+
+#include <QDebug>
+#include <QChildEvent>
+#include <QVariant>
+#include "DockAreaWidget.h"
+
+namespace ads
+{
+/**
+ * Private dock splitter data
+ */
+struct DockSplitterPrivate
+{
+ CDockSplitter* _this;
+ int VisibleContentCount = 0;
+
+ DockSplitterPrivate(CDockSplitter* _public) : _this(_public) {}
+};
+
+//============================================================================
+CDockSplitter::CDockSplitter(QWidget *parent)
+ : QSplitter(parent),
+ d(new DockSplitterPrivate(this))
+{
+ setProperty("ads-splitter", QVariant(true));
+ setChildrenCollapsible(false);
+}
+
+
+//============================================================================
+CDockSplitter::CDockSplitter(Qt::Orientation orientation, QWidget *parent)
+ : QSplitter(orientation, parent),
+ d(new DockSplitterPrivate(this))
+{
+
+}
+
+//============================================================================
+CDockSplitter::~CDockSplitter()
+{
+ ADS_PRINT("~CDockSplitter");
+ delete d;
+}
+
+
+//============================================================================
+bool CDockSplitter::hasVisibleContent() const
+{
+ // TODO Cache or precalculate this to speed up
+ for (int i = 0; i < count(); ++i)
+ {
+ if (!widget(i)->isHidden())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+//============================================================================
+QWidget* CDockSplitter::firstWidget() const
+{
+ return (count() > 0) ? widget(0) : nullptr;
+}
+
+
+//============================================================================
+QWidget* CDockSplitter::lastWidget() const
+{
+ return (count() > 0) ? widget(count() - 1) : nullptr;
+}
+
+//============================================================================
+bool CDockSplitter::isResizingWithContainer() const
+{
+ for (auto area : findChildren<CDockAreaWidget*>())
+ {
+ if(area->isCentralWidgetArea())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // namespace ads
+
+//---------------------------------------------------------------------------
+// EOF DockSplitter.cpp
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockSplitter.h b/scribus/third_party/Qt-Advanced-Docking-System/src/DockSplitter.h
index 863640cce..498a507ad 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockSplitter.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockSplitter.h
@@ -1,84 +1,84 @@
-#ifndef DockSplitterH
-#define DockSplitterH
-/*******************************************************************************
-** Qt Advanced Docking System
-** Copyright (C) 2017 Uwe Kindler
-**
-** This library is free software; you can redistribute it and/or
-** modify it under the terms of the GNU Lesser General Public
-** License as published by the Free Software Foundation; either
-** version 2.1 of the License, or (at your option) any later version.
-**
-** This library is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-** Lesser General Public License for more details.
-**
-** You should have received a copy of the GNU Lesser General Public
-** License along with this library; If not, see <http://www.gnu.org/licenses/>.
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockSplitter.h
-/// \author Uwe Kindler
-/// \date 24.03.2017
-/// \brief Declaration of CDockSplitter
-//============================================================================
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include <QSplitter>
-
-#include "ads_globals.h"
-
-namespace ads
-{
-struct DockSplitterPrivate;
-
-/**
- * Splitter used internally instead of QSplitter with some additional
- * functionality.
- */
-class ADS_EXPORT CDockSplitter : public QSplitter
-{
- Q_OBJECT
-private:
- DockSplitterPrivate* d;
- friend struct DockSplitterPrivate;
-
-public:
- CDockSplitter(QWidget *parent = Q_NULLPTR);
- CDockSplitter(Qt::Orientation orientation, QWidget *parent = Q_NULLPTR);
-
- /**
- * Prints debug info
- */
- virtual ~CDockSplitter();
-
- /**
- * Returns true, if any of the internal widgets is visible
- */
- bool hasVisibleContent() const;
-
- /**
- * Returns first widget or nullptr if splitter is empty
- */
- QWidget* firstWidget() const;
-
- /**
- * Returns last widget of nullptr is splitter is empty
- */
- QWidget* lastWidget() const;
-
- /**
- * Returns true if the splitter contains central widget of dock manager.
- */
- bool isResizingWithContainer() const;
-}; // class CDockSplitter
-
-} // namespace ads
-
-//---------------------------------------------------------------------------
-#endif // DockSplitterH
+#ifndef DockSplitterH
+#define DockSplitterH
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockSplitter.h
+/// \author Uwe Kindler
+/// \date 24.03.2017
+/// \brief Declaration of CDockSplitter
+//============================================================================
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include <QSplitter>
+
+#include "ads_globals.h"
+
+namespace ads
+{
+struct DockSplitterPrivate;
+
+/**
+ * Splitter used internally instead of QSplitter with some additional
+ * functionality.
+ */
+class ADS_EXPORT CDockSplitter : public QSplitter
+{
+ Q_OBJECT
+private:
+ DockSplitterPrivate* d;
+ friend struct DockSplitterPrivate;
+
+public:
+ CDockSplitter(QWidget *parent = Q_NULLPTR);
+ CDockSplitter(Qt::Orientation orientation, QWidget *parent = Q_NULLPTR);
+
+ /**
+ * Prints debug info
+ */
+ virtual ~CDockSplitter();
+
+ /**
+ * Returns true, if any of the internal widgets is visible
+ */
+ bool hasVisibleContent() const;
+
+ /**
+ * Returns first widget or nullptr if splitter is empty
+ */
+ QWidget* firstWidget() const;
+
+ /**
+ * Returns last widget of nullptr is splitter is empty
+ */
+ QWidget* lastWidget() const;
+
+ /**
+ * Returns true if the splitter contains central widget of dock manager.
+ */
+ bool isResizingWithContainer() const;
+}; // class CDockSplitter
+
+} // namespace ads
+
+//---------------------------------------------------------------------------
+#endif // DockSplitterH
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidget.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidget.cpp
index 063413acd..97011247b 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidget.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidget.cpp
@@ -1,1357 +1,1402 @@
-/*******************************************************************************
-** Qt Advanced Docking System
-** Copyright (C) 2017 Uwe Kindler
-**
-** This library is free software; you can redistribute it and/or
-** modify it under the terms of the GNU Lesser General Public
-** License as published by the Free Software Foundation; either
-** version 2.1 of the License, or (at your option) any later version.
-**
-** This library is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-** Lesser General Public License for more details.
-**
-** You should have received a copy of the GNU Lesser General Public
-** License along with this library; If not, see <http://www.gnu.org/licenses/>.
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockWidget.cpp
-/// \author Uwe Kindler
-/// \date 26.02.2017
-/// \brief Implementation of CDockWidget class
-//============================================================================
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include <AutoHideDockContainer.h>
-#include <AutoHideSideBar.h>
-#include <AutoHideTab.h>
-#include "DockWidgetTab.h"
-#include "DockWidget.h"
-
-#include <iostream>
-
-#include <QBoxLayout>
-#include <QAction>
-#include <QSplitter>
-#include <QStack>
-#include <QScrollArea>
-#include <QTextStream>
-#include <QPointer>
-#include <QEvent>
-#include <QDebug>
-#include <QToolBar>
-#include <QXmlStreamWriter>
-#include <QWindow>
-
-#include <QGuiApplication>
-#include <QScreen>
-#include <QWindow>
-
-#include "DockContainerWidget.h"
-#include "DockAreaWidget.h"
-#include "DockManager.h"
-#include "FloatingDockContainer.h"
-#include "DockSplitter.h"
-#include "DockComponentsFactory.h"
-#include "ads_globals.h"
-
-
-namespace ads
-{
-/**
- * Private data class of CDockWidget class (pimpl)
- */
-struct DockWidgetPrivate
-{
- struct WidgetFactory
- {
- CDockWidget::FactoryFunc createWidget;
- CDockWidget::eInsertMode insertMode;
- };
-
- CDockWidget* _this = nullptr;
- QBoxLayout* Layout = nullptr;
- QWidget* Widget = nullptr;
- CDockWidgetTab* TabWidget = nullptr;
- CDockWidget::DockWidgetFeatures Features = CDockWidget::DefaultDockWidgetFeatures;
- QPointer<CDockManager> DockManager;
- QPointer<CDockAreaWidget> DockArea;
- QAction* ToggleViewAction = nullptr;
- bool Closed = false;
- QScrollArea* ScrollArea = nullptr;
- QToolBar* ToolBar = nullptr;
- Qt::ToolButtonStyle ToolBarStyleDocked = Qt::ToolButtonIconOnly;
- Qt::ToolButtonStyle ToolBarStyleFloating = Qt::ToolButtonTextUnderIcon;
- QSize ToolBarIconSizeDocked = QSize(16, 16);
- QSize ToolBarIconSizeFloating = QSize(24, 24);
- bool IsFloatingTopLevel = false;
- QList<QAction*> TitleBarActions;
- CDockWidget::eMinimumSizeHintMode MinimumSizeHintMode = CDockWidget::MinimumSizeHintFromDockWidget;
- WidgetFactory* Factory = nullptr;
- QPointer<CAutoHideTab> SideTabWidget;
- CDockWidget::eToolBarStyleSource ToolBarStyleSource = CDockWidget::ToolBarStyleFromDockManager;
-
- /**
- * Private data constructor
- */
- DockWidgetPrivate(CDockWidget* _public);
-
- /**
- * Show dock widget
- */
- void showDockWidget();
-
- /**
- * Hide dock widget.
- */
- void hideDockWidget();
-
- /**
- * Hides a dock area if all dock widgets in the area are closed.
- * This function updates the current selected tab and hides the parent
- * dock area if it is empty
- */
- void updateParentDockArea();
-
- /**
- * Closes all auto hide dock widgets if there are no more opened dock areas
- * This prevents the auto hide dock widgets from being pinned to an empty dock area
- */
- void closeAutoHideDockWidgetsIfNeeded();
-
- /**
- * Setup the top tool bar
- */
- void setupToolBar();
-
- /**
- * Setup the main scroll area
- */
- void setupScrollArea();
-
- /**
- * Creates the content widget with the registered widget factory and
- * returns true on success.
- */
- bool createWidgetFromFactory();
-
- /**
- * Use the dock manager toolbar style and icon size for the different states
- */
- void setToolBarStyleFromDockManager();
-};
-// struct DockWidgetPrivate
-
-//============================================================================
-DockWidgetPrivate::DockWidgetPrivate(CDockWidget* _public) :
- _this(_public)
-{
-
-}
-
-
-//============================================================================
-void DockWidgetPrivate::showDockWidget()
-{
- if (!Widget)
- {
- if (!createWidgetFromFactory())
- {
- Q_ASSERT(!Features.testFlag(CDockWidget::DeleteContentOnClose)
- && "DeleteContentOnClose flag was set, but the widget "
- "factory is missing or it doesn't return a valid QWidget.");
- return;
- }
- }
-
- if (!DockArea)
- {
- CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this);
- // We use the size hint of the content widget to provide a good
- // initial size
- FloatingWidget->resize(Widget ? Widget->sizeHint() : _this->sizeHint());
- TabWidget->show();
- FloatingWidget->show();
- }
- else
- {
- DockArea->setCurrentDockWidget(_this);
- DockArea->toggleView(true);
- TabWidget->show();
- auto Splitter = DockArea->parentSplitter();
- while (Splitter && !Splitter->isVisible() && !DockArea->isAutoHide())
- {
- Splitter->show();
- Splitter = internal::findParent<CDockSplitter*>(Splitter);
- }
-
- CDockContainerWidget* Container = DockArea->dockContainer();
- if (Container->isFloating())
- {
- CFloatingDockContainer* FloatingWidget = internal::findParent<
- CFloatingDockContainer*>(Container);
- FloatingWidget->show();
- }
-
- // If this widget is pinned and there are no opened dock widgets, unpin the auto hide widget by moving it's contents to parent container
- // While restoring state, opened dock widgets are not valid
- if (Container->openedDockWidgets().count() == 0 && DockArea->isAutoHide() && !DockManager->isRestoringState())
- {
- DockArea->autoHideDockContainer()->moveContentsToParent();
- }
- }
-}
-
-
-//============================================================================
-void DockWidgetPrivate::hideDockWidget()
-{
- TabWidget->hide();
- updateParentDockArea();
-
- closeAutoHideDockWidgetsIfNeeded();
-
- if (Features.testFlag(CDockWidget::DeleteContentOnClose))
- {
- if (ScrollArea)
- {
- ScrollArea->takeWidget();
- delete ScrollArea;
- ScrollArea = nullptr;
- }
- Widget->deleteLater();
- Widget = nullptr;
- }
-}
-
-
-//============================================================================
-void DockWidgetPrivate::updateParentDockArea()
-{
- if (!DockArea)
- {
- return;
- }
-
- // we don't need to change the current tab if the
- // current dock widget is not the one being closed
- if (DockArea->currentDockWidget() != _this){
- return;
- }
-
- auto NextDockWidget = DockArea->nextOpenDockWidget(_this);
- if (NextDockWidget)
- {
- DockArea->setCurrentDockWidget(NextDockWidget);
- }
- else
- {
- DockArea->hideAreaWithNoVisibleContent();
- }
-}
-
-
-//============================================================================
-void DockWidgetPrivate::closeAutoHideDockWidgetsIfNeeded()
-{
- auto DockContainer = _this->dockContainer();
- if (!DockContainer)
- {
- return;
- }
-
- if (_this->dockManager()->isRestoringState())
- {
- return;
- }
-
- // If the dock container is the dock manager, or if it is not empty, then we
- // don't need to do anything
- if ((DockContainer == _this->dockManager())
- || !DockContainer->openedDockWidgets().isEmpty())
- {
- return;
- }
-
- for (auto autoHideWidget : DockContainer->autoHideWidgets())
- {
- auto DockWidget = autoHideWidget->dockWidget();
- if (DockWidget == _this)
- {
- continue;
- }
-
- DockWidget->toggleView(false);
- }
-}
-
-
-//============================================================================
-void DockWidgetPrivate::setupToolBar()
-{
- ToolBar = new QToolBar(_this);
- ToolBar->setObjectName("dockWidgetToolBar");
- Layout->insertWidget(0, ToolBar);
- ToolBar->setIconSize(QSize(16, 16));
- ToolBar->toggleViewAction()->setEnabled(false);
- ToolBar->toggleViewAction()->setVisible(false);
- _this->connect(_this, SIGNAL(topLevelChanged(bool)), SLOT(setToolbarFloatingStyle(bool)));
-}
-
-
-
-//============================================================================
-void DockWidgetPrivate::setupScrollArea()
-{
- ScrollArea = new QScrollArea(_this);
- ScrollArea->setObjectName("dockWidgetScrollArea");
- ScrollArea->setWidgetResizable(true);
- Layout->addWidget(ScrollArea);
-}
-
-
-//============================================================================
-bool DockWidgetPrivate::createWidgetFromFactory()
-{
- if (!Features.testFlag(CDockWidget::DeleteContentOnClose))
- {
- return false;
- }
-
- if (!Factory)
- {
- return false;
- }
-
- QWidget* w = Factory->createWidget(_this);
- if (!w)
- {
- return false;
- }
-
- _this->setWidget(w, Factory->insertMode);
- return true;
-}
-
-
-//============================================================================
-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),
- d(new DockWidgetPrivate(this))
-{
- d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
- d->Layout->setContentsMargins(0, 0, 0, 0);
- d->Layout->setSpacing(0);
- setLayout(d->Layout);
- setWindowTitle(title);
- setObjectName(title);
-
- d->TabWidget = componentsFactory()->createDockWidgetTab(this);
-
- d->ToggleViewAction = new QAction(title, this);
- d->ToggleViewAction->setCheckable(true);
- connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this,
- SLOT(toggleView(bool)));
- setToolbarFloatingStyle(false);
-
- if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
- {
- setFocusPolicy(Qt::ClickFocus);
- }
-}
-
-//============================================================================
-CDockWidget::~CDockWidget()
-{
- ADS_PRINT("~CDockWidget(): " << this->windowTitle());
- 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)
-{
- QAction* Action = d->ToggleViewAction;
- Action->blockSignals(true);
- Action->setChecked(Checked);
- Action->blockSignals(false);
-}
-
-
-//============================================================================
-void CDockWidget::setWidget(QWidget* widget, eInsertMode InsertMode)
-{
- if (d->Widget)
- {
- takeWidget();
- }
-
- auto ScrollAreaWidget = qobject_cast<QAbstractScrollArea*>(widget);
- if (ScrollAreaWidget || ForceNoScrollArea == InsertMode)
- {
- d->Layout->addWidget(widget);
- if (ScrollAreaWidget && ScrollAreaWidget->viewport())
- {
- ScrollAreaWidget->viewport()->setProperty("dockWidgetContent", true);
- }
- }
- else
- {
- d->setupScrollArea();
- d->ScrollArea->setWidget(widget);
- }
-
- d->Widget = widget;
- d->Widget->setProperty("dockWidgetContent", true);
-}
-
-//============================================================================
-void CDockWidget::setWidgetFactory(FactoryFunc createWidget, eInsertMode insertMode)
-{
- if (d->Factory)
- {
- delete d->Factory;
- }
-
- d->Factory = new DockWidgetPrivate::WidgetFactory { createWidget, insertMode };
-}
-
-
-//============================================================================
-QWidget* CDockWidget::takeWidget()
-{
- QWidget* w = nullptr;
- if (d->ScrollArea)
- {
- d->Layout->removeWidget(d->ScrollArea);
- w = d->ScrollArea->takeWidget();
- delete d->ScrollArea;
- d->ScrollArea = nullptr;
- d->Widget = nullptr;
- }
- else if (d->Widget)
- {
- d->Layout->removeWidget(d->Widget);
- w = d->Widget;
- d->Widget = nullptr;
- }
-
- if (w)
- {
- w->setParent(nullptr);
- }
- return w;
-}
-
-
-//============================================================================
-QWidget* CDockWidget::widget() const
-{
- return d->Widget;
-}
-
-
-//============================================================================
-CDockWidgetTab* CDockWidget::tabWidget() const
-{
- return d->TabWidget;
-}
-
-
-//============================================================================
-CAutoHideDockContainer* CDockWidget::autoHideDockContainer() const
-{
- if (!d->DockArea)
- {
- return nullptr;
- }
-
- return d->DockArea->autoHideDockContainer();
-}
-
-
-//============================================================================
-void CDockWidget::setFeatures(DockWidgetFeatures features)
-{
- if (d->Features == features)
- {
- return;
- }
- d->Features = features;
- notifyFeaturesChanged();
-}
-
-
-//============================================================================
-void CDockWidget::notifyFeaturesChanged()
-{
- Q_EMIT featuresChanged(d->Features);
- d->TabWidget->onDockWidgetFeaturesChanged();
- if(CDockAreaWidget* DockArea = dockAreaWidget())
- {
- DockArea->onDockWidgetFeaturesChanged();
- }
-}
-
-
-//============================================================================
-void CDockWidget::setFeature(DockWidgetFeature flag, bool on)
-{
- auto Features = features();
- internal::setFlag(Features, flag, on);
- setFeatures(Features);
-}
-
-
-//============================================================================
-CDockWidget::DockWidgetFeatures CDockWidget::features() const
-{
- if (d->DockManager)
- {
- return d->Features &~ d->DockManager->globallyLockedDockWidgetFeatures();
- }
- else
- {
- return d->Features;
- }
-}
-
-
-//============================================================================
-CDockManager* CDockWidget::dockManager() const
-{
- return d->DockManager;
-}
-
-
-//============================================================================
-void CDockWidget::setDockManager(CDockManager* DockManager)
-{
- d->DockManager = DockManager;
- if (!DockManager)
- {
- return;
- }
-
- if (ToolBarStyleFromDockManager == d->ToolBarStyleSource)
- {
- d->setToolBarStyleFromDockManager();
- }
-}
-
-
-//============================================================================
-CDockContainerWidget* CDockWidget::dockContainer() const
-{
- if (d->DockArea)
- {
- return d->DockArea->dockContainer();
- }
- else
- {
- return nullptr;
- }
-}
-
-
-//============================================================================
-CFloatingDockContainer* CDockWidget::floatingDockContainer() const
-{
- auto DockContainer = dockContainer();
- return DockContainer ? DockContainer->floatingWidget() : nullptr;
-}
-
-
-//============================================================================
-CDockAreaWidget* CDockWidget::dockAreaWidget() const
-{
- return d->DockArea;
-}
-
-//============================================================================
-CAutoHideTab* CDockWidget::sideTabWidget() const
-{
- return d->SideTabWidget;
-}
-
-
-//============================================================================
-void CDockWidget::setSideTabWidget(CAutoHideTab* SideTab) const
-{
- d->SideTabWidget = SideTab;
-}
-
-
-//============================================================================
-bool CDockWidget::isAutoHide() const
-{
- return !d->SideTabWidget.isNull();
-}
-
-
-//============================================================================
-SideBarLocation CDockWidget::autoHideLocation() const
-{
- return isAutoHide() ? autoHideDockContainer()->sideBarLocation() : SideBarNone;
-}
-
-
-//============================================================================
-bool CDockWidget::isFloating() const
-{
- if (!isInFloatingContainer())
- {
- return false;
- }
-
- return dockContainer()->topLevelDockWidget() == this;
-}
-
-
-//============================================================================
-bool CDockWidget::isInFloatingContainer() const
-{
- auto Container = dockContainer();
- if (!Container)
- {
- return false;
- }
-
- if (!Container->isFloating())
- {
- return false;
- }
-
- return true;
-}
-
-
-//============================================================================
-bool CDockWidget::isClosed() const
-{
- return d->Closed;
-}
-
-
-//============================================================================
-QAction* CDockWidget::toggleViewAction() const
-{
- return d->ToggleViewAction;
-}
-
-
-//============================================================================
-void CDockWidget::setToggleViewActionMode(eToggleViewActionMode Mode)
-{
- if (ActionModeToggle == Mode)
- {
- d->ToggleViewAction->setCheckable(true);
- d->ToggleViewAction->setIcon(QIcon());
- }
- else
- {
- d->ToggleViewAction->setCheckable(false);
- d->ToggleViewAction->setIcon(d->TabWidget->icon());
- }
-}
-
-
-//============================================================================
-void CDockWidget::setMinimumSizeHintMode(eMinimumSizeHintMode Mode)
-{
- d->MinimumSizeHintMode = Mode;
-}
-
-
-//============================================================================
-CDockWidget::eMinimumSizeHintMode CDockWidget::minimumSizeHintMode() const
-{
- return d->MinimumSizeHintMode;
-}
-
-
-//============================================================================
-bool CDockWidget::isCentralWidget() const
-{
- return dockManager()->centralWidget() == this;
-}
-
-
-//============================================================================
-void CDockWidget::toggleView(bool Open)
-{
- // If the toggle view action mode is ActionModeShow, then Open is always
- // true if the sender is the toggle view action
- QAction* Sender = qobject_cast<QAction*>(sender());
- if (Sender == d->ToggleViewAction && !d->ToggleViewAction->isCheckable())
- {
- Open = true;
- }
-
- // 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 && !AutoHideContainer)
- {
- raise();
- }
-
- if (Open && AutoHideContainer)
- {
- AutoHideContainer->collapseView(false);
- }
-}
-
-
-//============================================================================
-void CDockWidget::toggleViewInternal(bool Open)
-{
- CDockContainerWidget* DockContainer = dockContainer();
- CDockWidget* TopLevelDockWidgetBefore = DockContainer
- ? DockContainer->topLevelDockWidget() : nullptr;
-
- d->Closed = !Open;
-
- if (Open)
- {
- d->showDockWidget();
- }
- else
- {
- d->hideDockWidget();
- }
-
- d->ToggleViewAction->blockSignals(true);
- d->ToggleViewAction->setChecked(Open);
- d->ToggleViewAction->blockSignals(false);
- if (d->DockArea)
- {
- d->DockArea->toggleDockWidgetView(this, Open);
- if (d->DockArea->isAutoHide())
- {
- d->DockArea->autoHideDockContainer()->toggleView(Open);
- }
- }
-
- if (Open && TopLevelDockWidgetBefore)
- {
- CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidgetBefore, false);
- }
-
- // Here we need to call the dockContainer() function again, because if
- // this dock widget was unassigned before the call to showDockWidget() then
- // it has a dock container now
- DockContainer = dockContainer();
- CDockWidget* TopLevelDockWidgetAfter = DockContainer
- ? DockContainer->topLevelDockWidget() : nullptr;
- CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidgetAfter, true);
- CFloatingDockContainer* FloatingContainer = DockContainer
- ? DockContainer->floatingWidget() : nullptr;
- if (FloatingContainer)
- {
- FloatingContainer->updateWindowTitle();
- }
-
- if (!Open)
- {
- Q_EMIT closed();
- }
- Q_EMIT viewToggled(Open);
-}
-
-
-//============================================================================
-void CDockWidget::setDockArea(CDockAreaWidget* DockArea)
-{
- d->DockArea = DockArea;
- d->ToggleViewAction->setChecked(DockArea != nullptr && !this->isClosed());
- setParent(DockArea);
-}
-
-
-//============================================================================
-void CDockWidget::saveState(QXmlStreamWriter& s) const
-{
- s.writeStartElement("Widget");
- s.writeAttribute("Name", objectName());
- s.writeAttribute("Closed", QString::number(d->Closed ? 1 : 0));
- s.writeEndElement();
-}
-
-
-//============================================================================
-void CDockWidget::flagAsUnassigned()
-{
- d->Closed = true;
- setParent(d->DockManager);
- setVisible(false);
- setDockArea(nullptr);
- tabWidget()->setParent(this);
-}
-
-
-//============================================================================
-bool CDockWidget::event(QEvent *e)
-{
- switch (e->type())
- {
- case QEvent::Hide:
- Q_EMIT visibilityChanged(false);
- break;
-
- case QEvent::Show:
- Q_EMIT visibilityChanged(geometry().right() >= 0 && geometry().bottom() >= 0);
- break;
-
- case QEvent::WindowTitleChange :
- {
- const auto title = windowTitle();
- if (d->TabWidget)
- {
- d->TabWidget->setText(title);
- }
- if (d->SideTabWidget)
- {
- d->SideTabWidget->setText(title);
- }
- if (d->ToggleViewAction)
- {
- d->ToggleViewAction->setText(title);
- }
- if (d->DockArea)
- {
- d->DockArea->markTitleBarMenuOutdated();//update tabs menu
- }
-
- auto FloatingWidget = floatingDockContainer();
- if (FloatingWidget)
- {
- FloatingWidget->updateWindowTitle();
- }
- Q_EMIT titleChanged(title);
- }
- break;
-
- default:
- break;
- }
-
- return Super::event(e);
-}
-
-
-#ifndef QT_NO_TOOLTIP
-//============================================================================
-void CDockWidget::setTabToolTip(const QString &text)
-{
- if (d->TabWidget)
- {
- d->TabWidget->setToolTip(text);
- }
- if (d->ToggleViewAction)
- {
- d->ToggleViewAction->setToolTip(text);
- }
- if (d->DockArea)
- {
- d->DockArea->markTitleBarMenuOutdated();//update tabs menu
- }
-}
-#endif
-
-
-//============================================================================
-void CDockWidget::setIcon(const QIcon& Icon)
-{
- d->TabWidget->setIcon(Icon);
-
- if (d->SideTabWidget)
- {
- d->SideTabWidget->setIcon(Icon);
- }
-
- if (!d->ToggleViewAction->isCheckable())
- {
- d->ToggleViewAction->setIcon(Icon);
- }
-}
-
-
-//============================================================================
-QIcon CDockWidget::icon() const
-{
- return d->TabWidget->icon();
-}
-
-
-//============================================================================
-QToolBar* CDockWidget::toolBar() const
-{
- return d->ToolBar;
-}
-
-
-//============================================================================
-QToolBar* CDockWidget::createDefaultToolBar()
-{
- if (!d->ToolBar)
- {
- d->setupToolBar();
- }
-
- return d->ToolBar;
-}
-
-
-//============================================================================
-void CDockWidget::setToolBar(QToolBar* ToolBar)
-{
- if (d->ToolBar)
- {
- delete d->ToolBar;
- }
-
- d->ToolBar = ToolBar;
- d->Layout->insertWidget(0, d->ToolBar);
- this->connect(this, SIGNAL(topLevelChanged(bool)), SLOT(setToolbarFloatingStyle(bool)));
- setToolbarFloatingStyle(isFloating());
-}
-
-
-//============================================================================
-void CDockWidget::setToolBarStyle(Qt::ToolButtonStyle Style, eState State)
-{
- if (StateFloating == State)
- {
- d->ToolBarStyleFloating = Style;
- }
- else
- {
- d->ToolBarStyleDocked = Style;
- }
-
- setToolbarFloatingStyle(isFloating());
-}
-
-
-//============================================================================
-Qt::ToolButtonStyle CDockWidget::toolBarStyle(eState State) const
-{
- if (StateFloating == State)
- {
- return d->ToolBarStyleFloating;
- }
- else
- {
- return d->ToolBarStyleDocked;
- }
-}
-
-
-//============================================================================
-void CDockWidget::setToolBarIconSize(const QSize& IconSize, eState State)
-{
- if (StateFloating == State)
- {
- d->ToolBarIconSizeFloating = IconSize;
- }
- else
- {
- d->ToolBarIconSizeDocked = IconSize;
- }
-
- setToolbarFloatingStyle(isFloating());
-}
-
-
-//============================================================================
-QSize CDockWidget::toolBarIconSize(eState State) const
-{
- if (StateFloating == State)
- {
- return d->ToolBarIconSizeFloating;
- }
- else
- {
- return d->ToolBarIconSizeDocked;
- }
-}
-
-
-//============================================================================
-void CDockWidget::setToolbarFloatingStyle(bool Floating)
-{
- if (!d->ToolBar)
- {
- return;
- }
-
- auto IconSize = Floating ? d->ToolBarIconSizeFloating : d->ToolBarIconSizeDocked;
- if (IconSize != d->ToolBar->iconSize())
- {
- d->ToolBar->setIconSize(IconSize);
- }
-
- auto ButtonStyle = Floating ? d->ToolBarStyleFloating : d->ToolBarStyleDocked;
- if (ButtonStyle != d->ToolBar->toolButtonStyle())
- {
- d->ToolBar->setToolButtonStyle(ButtonStyle);
- }
-}
-
-
-//============================================================================
-void CDockWidget::emitTopLevelEventForWidget(CDockWidget* TopLevelDockWidget, bool Floating)
-{
- if (TopLevelDockWidget)
- {
- TopLevelDockWidget->dockAreaWidget()->updateTitleBarVisibility();
- TopLevelDockWidget->emitTopLevelChanged(Floating);
- }
-}
-
-
-//============================================================================
-void CDockWidget::emitTopLevelChanged(bool Floating)
-{
- if (Floating != d->IsFloatingTopLevel)
- {
- d->IsFloatingTopLevel = Floating;
- Q_EMIT topLevelChanged(d->IsFloatingTopLevel);
- }
-}
-
-
-//============================================================================
-void CDockWidget::setClosedState(bool Closed)
-{
- d->Closed = Closed;
-}
-
-
-//============================================================================
-QSize CDockWidget::minimumSizeHint() const
-{
- if (!d->Widget)
- {
- return QSize(60, 40);
- }
-
- switch (d->MinimumSizeHintMode)
- {
- 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();
-}
-
-
-//============================================================================
-void CDockWidget::setFloating()
-{
- if (isClosed())
- {
- return;
- }
-
- if (this->isAutoHide())
- {
- dockAreaWidget()->setFloating();
- }
- else
- {
- d->TabWidget->detachDockWidget();
- }
-}
-
-
-//============================================================================
-void CDockWidget::deleteDockWidget()
-{
- auto manager=dockManager();
- if(manager){
- manager->removeDockWidget(this);
- }
- deleteLater();
- d->Closed = true;
-}
-
-
-//============================================================================
-void CDockWidget::closeDockWidget()
-{
- closeDockWidgetInternal(true);
-}
-
-
-
-//============================================================================
-void CDockWidget::requestCloseDockWidget()
-{
- if (features().testFlag(CDockWidget::DockWidgetDeleteOnClose)
- || features().testFlag(CDockWidget::CustomCloseHandling))
- {
- closeDockWidgetInternal(false);
- }
- else
- {
- toggleView(false);
- }
-}
-
-
-//============================================================================
-bool CDockWidget::closeDockWidgetInternal(bool ForceClose)
-{
- if (!ForceClose)
- {
- Q_EMIT closeRequested();
- }
-
- if (!ForceClose && features().testFlag(CDockWidget::CustomCloseHandling))
- {
- return false;
- }
-
- if (features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
- {
- // If the dock widget is floating, then we check if we also need to
- // delete the floating widget
- if (isFloating())
- {
- CFloatingDockContainer* FloatingWidget = internal::findParent<
- CFloatingDockContainer*>(this);
- if (FloatingWidget->dockWidgets().count() == 1)
- {
- FloatingWidget->deleteLater();
- }
- else
- {
- FloatingWidget->hide();
- }
- }
- if (d->DockArea && d->DockArea->isAutoHide())
- {
- d->DockArea->autoHideDockContainer()->cleanupAndDelete();
- }
- deleteDockWidget();
- Q_EMIT closed();
- }
- else
- {
- toggleView(false);
- }
-
- return true;
-}
-
-
-//============================================================================
-void CDockWidget::setTitleBarActions(QList<QAction*> actions)
-{
- d->TitleBarActions = actions;
-}
-
-
-//============================================================================
-QList<QAction*> CDockWidget::titleBarActions() const
-{
- return d->TitleBarActions;
-}
-
-
-//============================================================================
-void CDockWidget::showFullScreen()
-{
- if (isFloating())
- {
- dockContainer()->floatingWidget()->showFullScreen();
- }
- else
- {
- Super::showFullScreen();
- }
-}
-
-
-//============================================================================
-void CDockWidget::showNormal()
-{
- if (isFloating())
- {
- dockContainer()->floatingWidget()->showNormal();
- }
- else
- {
- Super::showNormal();
- }
-}
-
-
-//============================================================================
-bool CDockWidget::isFullScreen() const
-{
- if (isFloating())
- {
- return dockContainer()->floatingWidget()->isFullScreen();
- }
- else
- {
- return Super::isFullScreen();
- }
-}
-
-
-//============================================================================
-void CDockWidget::setAsCurrentTab()
-{
- if (d->DockArea && !isClosed())
- {
- d->DockArea->setCurrentDockWidget(this);
- }
-}
-
-
-//============================================================================
-bool CDockWidget::isTabbed() const
-{
- return d->DockArea && (d->DockArea->openDockWidgetsCount() > 1);
-}
-
-
-
-//============================================================================
-bool CDockWidget::isCurrentTab() const
-{
- return d->DockArea && (d->DockArea->currentDockWidget() == this);
-}
-
-
-//============================================================================
-void CDockWidget::raise()
-{
- if (isClosed())
- {
- return;
- }
-
- setAsCurrentTab();
- if (isInFloatingContainer())
- {
- auto FloatingWindow = window();
- FloatingWindow->raise();
- FloatingWindow->activateWindow();
- }
-}
-
-
-//============================================================================
-void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location, int TabIndex)
-{
- if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
- {
- return;
- }
-
- // Do nothing if nothing changes
- 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, TabIndex);
- }
-}
-
-
-//============================================================================
-void CDockWidget::toggleAutoHide(SideBarLocation Location)
-{
- if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
- {
- return;
- }
-
- setAutoHide(!isAutoHide(), 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
-
-//---------------------------------------------------------------------------
-// EOF DockWidget.cpp
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockWidget.cpp
+/// \author Uwe Kindler
+/// \date 26.02.2017
+/// \brief Implementation of CDockWidget class
+//============================================================================
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include <AutoHideDockContainer.h>
+#include <AutoHideSideBar.h>
+#include <AutoHideTab.h>
+#include "DockWidgetTab.h"
+#include "DockWidget.h"
+
+#include <iostream>
+
+#include <QBoxLayout>
+#include <QAction>
+#include <QSplitter>
+#include <QStack>
+#include <QScrollArea>
+#include <QTextStream>
+#include <QPointer>
+#include <QEvent>
+#include <QDebug>
+#include <QToolBar>
+#include <QXmlStreamWriter>
+#include <QWindow>
+
+#include <QGuiApplication>
+#include <QScreen>
+#include <QWindow>
+
+#include "DockContainerWidget.h"
+#include "DockAreaWidget.h"
+#include "DockManager.h"
+#include "FloatingDockContainer.h"
+#include "DockSplitter.h"
+#include "DockComponentsFactory.h"
+#include "ads_globals.h"
+
+
+namespace ads
+{
+/**
+ * Private data class of CDockWidget class (pimpl)
+ */
+struct DockWidgetPrivate
+{
+ struct WidgetFactory
+ {
+ CDockWidget::FactoryFunc createWidget;
+ CDockWidget::eInsertMode insertMode;
+ };
+
+ CDockWidget* _this = nullptr;
+ QBoxLayout* Layout = nullptr;
+ QWidget* Widget = nullptr;
+ CDockWidgetTab* TabWidget = nullptr;
+ CDockWidget::DockWidgetFeatures Features = CDockWidget::DefaultDockWidgetFeatures;
+ QPointer<CDockManager> DockManager;
+ QPointer<CDockAreaWidget> DockArea;
+ QAction* ToggleViewAction = nullptr;
+ bool Closed = false;
+ QScrollArea* ScrollArea = nullptr;
+ QToolBar* ToolBar = nullptr;
+ Qt::ToolButtonStyle ToolBarStyleDocked = Qt::ToolButtonIconOnly;
+ Qt::ToolButtonStyle ToolBarStyleFloating = Qt::ToolButtonTextUnderIcon;
+ QSize ToolBarIconSizeDocked = QSize(16, 16);
+ QSize ToolBarIconSizeFloating = QSize(24, 24);
+ bool IsFloatingTopLevel = false;
+ QList<QAction*> TitleBarActions;
+ CDockWidget::eMinimumSizeHintMode MinimumSizeHintMode = CDockWidget::MinimumSizeHintFromDockWidget;
+ WidgetFactory* Factory = nullptr;
+ QPointer<CAutoHideTab> SideTabWidget;
+ CDockWidget::eToolBarStyleSource ToolBarStyleSource = CDockWidget::ToolBarStyleFromDockManager;
+ SideBarLocation PreferredAutoHideSideBarLocation = SideBarNone;
+
+ /**
+ * Private data constructor
+ */
+ DockWidgetPrivate(CDockWidget* _public);
+
+ /**
+ * Convenience function to ease components factory access
+ */
+ QSharedPointer<ads::CDockComponentsFactory> componentsFactory() const
+ {
+ return DockManager ? DockManager->componentsFactory() : CDockComponentsFactory::factory();
+ }
+
+ /**
+ * Show dock widget
+ */
+ void showDockWidget();
+
+ /**
+ * Hide dock widget.
+ */
+ void hideDockWidget();
+
+ /**
+ * Hides a dock area if all dock widgets in the area are closed.
+ * This function updates the current selected tab and hides the parent
+ * dock area if it is empty
+ */
+ void updateParentDockArea();
+
+ /**
+ * Closes all auto hide dock widgets if there are no more opened dock areas
+ * This prevents the auto hide dock widgets from being pinned to an empty dock area
+ */
+ void closeAutoHideDockWidgetsIfNeeded();
+
+ /**
+ * Setup the top tool bar
+ */
+ void setupToolBar();
+
+ /**
+ * Setup the main scroll area
+ */
+ void setupScrollArea();
+
+ /**
+ * Creates the content widget with the registered widget factory and
+ * returns true on success.
+ */
+ bool createWidgetFromFactory();
+
+ /**
+ * Use the dock manager toolbar style and icon size for the different states
+ */
+ void setToolBarStyleFromDockManager();
+};
+// struct DockWidgetPrivate
+
+//============================================================================
+DockWidgetPrivate::DockWidgetPrivate(CDockWidget* _public) :
+ _this(_public)
+{
+
+}
+
+
+//============================================================================
+void DockWidgetPrivate::showDockWidget()
+{
+ if (!Widget)
+ {
+ if (!createWidgetFromFactory())
+ {
+ Q_ASSERT(!Features.testFlag(CDockWidget::DeleteContentOnClose)
+ && "DeleteContentOnClose flag was set, but the widget "
+ "factory is missing or it doesn't return a valid QWidget.");
+ return;
+ }
+ }
+
+ if (!DockArea)
+ {
+ CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this);
+ // We use the size hint of the content widget to provide a good
+ // initial size
+ FloatingWidget->resize(Widget ? Widget->sizeHint() : _this->sizeHint());
+ TabWidget->show();
+ FloatingWidget->show();
+ }
+ else
+ {
+ DockArea->setCurrentDockWidget(_this);
+ DockArea->toggleView(true);
+ TabWidget->show();
+ auto Splitter = DockArea->parentSplitter();
+ while (Splitter && !Splitter->isVisible() && !DockArea->isAutoHide())
+ {
+ Splitter->show();
+ Splitter = internal::findParent<CDockSplitter*>(Splitter);
+ }
+
+ CDockContainerWidget* Container = DockArea->dockContainer();
+ if (Container->isFloating())
+ {
+ CFloatingDockContainer* FloatingWidget = internal::findParent<
+ CFloatingDockContainer*>(Container);
+ FloatingWidget->show();
+ }
+
+ // If this widget is pinned and there are no opened dock widgets, unpin the auto hide widget by moving it's contents to parent container
+ // While restoring state, opened dock widgets are not valid
+ if (Container->openedDockWidgets().count() == 0 && DockArea->isAutoHide() && !DockManager->isRestoringState())
+ {
+ DockArea->autoHideDockContainer()->moveContentsToParent();
+ }
+ }
+}
+
+
+//============================================================================
+void DockWidgetPrivate::hideDockWidget()
+{
+ TabWidget->hide();
+ updateParentDockArea();
+
+ closeAutoHideDockWidgetsIfNeeded();
+
+ if (Features.testFlag(CDockWidget::DeleteContentOnClose))
+ {
+ if (ScrollArea)
+ {
+ ScrollArea->takeWidget();
+ delete ScrollArea;
+ ScrollArea = nullptr;
+ }
+ Widget->deleteLater();
+ Widget = nullptr;
+ }
+}
+
+
+//============================================================================
+void DockWidgetPrivate::updateParentDockArea()
+{
+ if (!DockArea)
+ {
+ return;
+ }
+
+ // we don't need to change the current tab if the
+ // current dock widget is not the one being closed
+ if (DockArea->currentDockWidget() != _this){
+ return;
+ }
+
+ auto NextDockWidget = DockArea->nextOpenDockWidget(_this);
+ if (NextDockWidget)
+ {
+ DockArea->setCurrentDockWidget(NextDockWidget);
+ }
+ else
+ {
+ DockArea->hideAreaWithNoVisibleContent();
+ }
+}
+
+
+//============================================================================
+void DockWidgetPrivate::closeAutoHideDockWidgetsIfNeeded()
+{
+ auto DockContainer = _this->dockContainer();
+ if (!DockContainer)
+ {
+ return;
+ }
+
+ if (_this->dockManager()->isRestoringState())
+ {
+ return;
+ }
+
+ // If the dock container is the dock manager, or if it is not empty, then we
+ // don't need to do anything
+ if ((DockContainer == _this->dockManager())
+ || !DockContainer->openedDockWidgets().isEmpty())
+ {
+ return;
+ }
+
+ for (auto autoHideWidget : DockContainer->autoHideWidgets())
+ {
+ auto DockWidget = autoHideWidget->dockWidget();
+ if (DockWidget == _this)
+ {
+ continue;
+ }
+
+ DockWidget->toggleView(false);
+ }
+}
+
+
+//============================================================================
+void DockWidgetPrivate::setupToolBar()
+{
+ ToolBar = new QToolBar(_this);
+ ToolBar->setObjectName("dockWidgetToolBar");
+ Layout->insertWidget(0, ToolBar);
+ ToolBar->setIconSize(QSize(16, 16));
+ ToolBar->toggleViewAction()->setEnabled(false);
+ ToolBar->toggleViewAction()->setVisible(false);
+ _this->connect(_this, SIGNAL(topLevelChanged(bool)), SLOT(setToolbarFloatingStyle(bool)));
+}
+
+
+
+//============================================================================
+void DockWidgetPrivate::setupScrollArea()
+{
+ ScrollArea = new QScrollArea(_this);
+ ScrollArea->setObjectName("dockWidgetScrollArea");
+ ScrollArea->setWidgetResizable(true);
+ Layout->addWidget(ScrollArea);
+}
+
+
+//============================================================================
+bool DockWidgetPrivate::createWidgetFromFactory()
+{
+ if (!Features.testFlag(CDockWidget::DeleteContentOnClose))
+ {
+ return false;
+ }
+
+ if (!Factory)
+ {
+ return false;
+ }
+
+ QWidget* w = Factory->createWidget(_this);
+ if (!w)
+ {
+ return false;
+ }
+
+ _this->setWidget(w, Factory->insertMode);
+ return true;
+}
+
+
+//============================================================================
+void DockWidgetPrivate::setToolBarStyleFromDockManager()
+{
+ if (!DockManager)
+ {
+ return;
+ }
+ auto State = CDockWidget::StateDocked;
+ _this->setToolBarIconSize(DockManager->dockWidgetToolBarIconSize(State), State);
+ _this->setToolBarStyle(DockManager->dockWidgetToolBarStyle(State), State);
+ State = CDockWidget::StateFloating;
+ _this->setToolBarIconSize(DockManager->dockWidgetToolBarIconSize(State), State);
+ _this->setToolBarStyle(DockManager->dockWidgetToolBarStyle(State), State);
+}
+
+
+//============================================================================
+CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
+ CDockWidget(nullptr, title, parent)
+{
+}
+
+
+//============================================================================
+CDockWidget::CDockWidget(CDockManager *manager, const QString &title, QWidget* parent)
+ : QFrame(parent),
+ d(new DockWidgetPrivate(this))
+{
+ d->DockManager = manager;
+ d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
+ d->Layout->setContentsMargins(0, 0, 0, 0);
+ d->Layout->setSpacing(0);
+ setLayout(d->Layout);
+ setWindowTitle(title);
+ setObjectName(title);
+
+ d->TabWidget = d->componentsFactory()->createDockWidgetTab(this);
+
+ d->ToggleViewAction = new QAction(title, this);
+ d->ToggleViewAction->setCheckable(true);
+ connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this,
+ SLOT(toggleView(bool)));
+ setToolbarFloatingStyle(false);
+
+ if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
+ {
+ setFocusPolicy(Qt::ClickFocus);
+ }
+
+ if (CDockManager::testConfigFlag(CDockManager::UseNativeWindows))
+ {
+ winId();
+ }
+}
+
+
+//============================================================================
+CDockWidget::~CDockWidget()
+{
+ ADS_PRINT("~CDockWidget(): " << this->windowTitle());
+ 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)
+{
+ QAction* Action = d->ToggleViewAction;
+ Action->blockSignals(true);
+ Action->setChecked(Checked);
+ Action->blockSignals(false);
+}
+
+
+//============================================================================
+void CDockWidget::setWidget(QWidget* widget, eInsertMode InsertMode)
+{
+ if (d->Widget)
+ {
+ takeWidget();
+ }
+
+ auto ScrollAreaWidget = qobject_cast<QAbstractScrollArea*>(widget);
+ if (ScrollAreaWidget || ForceNoScrollArea == InsertMode)
+ {
+ d->Layout->addWidget(widget);
+ if (ScrollAreaWidget && ScrollAreaWidget->viewport())
+ {
+ ScrollAreaWidget->viewport()->setProperty("dockWidgetContent", true);
+ }
+ }
+ else
+ {
+ d->setupScrollArea();
+ d->ScrollArea->setWidget(widget);
+ }
+
+ d->Widget = widget;
+ d->Widget->setProperty("dockWidgetContent", true);
+}
+
+//============================================================================
+void CDockWidget::setWidgetFactory(FactoryFunc createWidget, eInsertMode insertMode)
+{
+ if (d->Factory)
+ {
+ delete d->Factory;
+ }
+
+ d->Factory = new DockWidgetPrivate::WidgetFactory { createWidget, insertMode };
+}
+
+
+//============================================================================
+QWidget* CDockWidget::takeWidget()
+{
+ QWidget* w = nullptr;
+ if (d->ScrollArea)
+ {
+ d->Layout->removeWidget(d->ScrollArea);
+ w = d->ScrollArea->takeWidget();
+ delete d->ScrollArea;
+ d->ScrollArea = nullptr;
+ d->Widget = nullptr;
+ }
+ else if (d->Widget)
+ {
+ d->Layout->removeWidget(d->Widget);
+ w = d->Widget;
+ d->Widget = nullptr;
+ }
+
+ if (w)
+ {
+ w->setParent(nullptr);
+ }
+ return w;
+}
+
+
+//============================================================================
+QWidget* CDockWidget::widget() const
+{
+ return d->Widget;
+}
+
+
+//============================================================================
+CDockWidgetTab* CDockWidget::tabWidget() const
+{
+ return d->TabWidget;
+}
+
+
+//============================================================================
+CAutoHideDockContainer* CDockWidget::autoHideDockContainer() const
+{
+ if (!d->DockArea)
+ {
+ return nullptr;
+ }
+
+ return d->DockArea->autoHideDockContainer();
+}
+
+
+//============================================================================
+void CDockWidget::setFeatures(DockWidgetFeatures features)
+{
+ if (d->Features == features)
+ {
+ return;
+ }
+ d->Features = features;
+ notifyFeaturesChanged();
+}
+
+
+//============================================================================
+void CDockWidget::notifyFeaturesChanged()
+{
+ Q_EMIT featuresChanged(d->Features);
+ d->TabWidget->onDockWidgetFeaturesChanged();
+ if(CDockAreaWidget* DockArea = dockAreaWidget())
+ {
+ DockArea->onDockWidgetFeaturesChanged();
+ }
+}
+
+
+//============================================================================
+void CDockWidget::setFeature(DockWidgetFeature flag, bool on)
+{
+ auto Features = features();
+ internal::setFlag(Features, flag, on);
+ setFeatures(Features);
+}
+
+
+//============================================================================
+CDockWidget::DockWidgetFeatures CDockWidget::features() const
+{
+ if (d->DockManager)
+ {
+ return d->Features &~ d->DockManager->globallyLockedDockWidgetFeatures();
+ }
+ else
+ {
+ return d->Features;
+ }
+}
+
+
+//============================================================================
+CDockManager* CDockWidget::dockManager() const
+{
+ return d->DockManager;
+}
+
+
+//============================================================================
+void CDockWidget::setDockManager(CDockManager* DockManager)
+{
+ d->DockManager = DockManager;
+ if (!DockManager)
+ {
+ return;
+ }
+
+ if (ToolBarStyleFromDockManager == d->ToolBarStyleSource)
+ {
+ d->setToolBarStyleFromDockManager();
+ }
+}
+
+
+//============================================================================
+CDockContainerWidget* CDockWidget::dockContainer() const
+{
+ if (d->DockArea)
+ {
+ return d->DockArea->dockContainer();
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+
+//============================================================================
+CFloatingDockContainer* CDockWidget::floatingDockContainer() const
+{
+ auto DockContainer = dockContainer();
+ return DockContainer ? DockContainer->floatingWidget() : nullptr;
+}
+
+
+//============================================================================
+CDockAreaWidget* CDockWidget::dockAreaWidget() const
+{
+ return d->DockArea;
+}
+
+//============================================================================
+CAutoHideTab* CDockWidget::sideTabWidget() const
+{
+ return d->SideTabWidget;
+}
+
+
+//============================================================================
+void CDockWidget::setSideTabWidget(CAutoHideTab* SideTab) const
+{
+ d->SideTabWidget = SideTab;
+}
+
+
+//============================================================================
+bool CDockWidget::isAutoHide() const
+{
+ return !d->SideTabWidget.isNull();
+}
+
+
+//============================================================================
+SideBarLocation CDockWidget::autoHideLocation() const
+{
+ return isAutoHide() ? autoHideDockContainer()->sideBarLocation() : SideBarNone;
+}
+
+
+//============================================================================
+void CDockWidget::setPreferredAutoHideSideBarLocation(SideBarLocation Location)
+{
+ d->PreferredAutoHideSideBarLocation = Location;
+}
+
+
+//============================================================================
+SideBarLocation CDockWidget::preferredAutoHideSideBarLocation() const
+{
+ return d->PreferredAutoHideSideBarLocation;
+}
+
+
+//============================================================================
+bool CDockWidget::isFloating() const
+{
+ if (!isInFloatingContainer())
+ {
+ return false;
+ }
+
+ return dockContainer()->topLevelDockWidget() == this;
+}
+
+
+//============================================================================
+bool CDockWidget::isInFloatingContainer() const
+{
+ auto Container = dockContainer();
+ if (!Container)
+ {
+ return false;
+ }
+
+ if (!Container->isFloating())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+//============================================================================
+bool CDockWidget::isClosed() const
+{
+ return d->Closed;
+}
+
+
+//============================================================================
+QAction* CDockWidget::toggleViewAction() const
+{
+ return d->ToggleViewAction;
+}
+
+
+//============================================================================
+void CDockWidget::setToggleViewActionMode(eToggleViewActionMode Mode)
+{
+ if (ActionModeToggle == Mode)
+ {
+ d->ToggleViewAction->setCheckable(true);
+ d->ToggleViewAction->setIcon(QIcon());
+ }
+ else
+ {
+ d->ToggleViewAction->setCheckable(false);
+ d->ToggleViewAction->setIcon(d->TabWidget->icon());
+ }
+}
+
+
+//============================================================================
+void CDockWidget::setMinimumSizeHintMode(eMinimumSizeHintMode Mode)
+{
+ d->MinimumSizeHintMode = Mode;
+}
+
+
+//============================================================================
+CDockWidget::eMinimumSizeHintMode CDockWidget::minimumSizeHintMode() const
+{
+ return d->MinimumSizeHintMode;
+}
+
+
+//============================================================================
+bool CDockWidget::isCentralWidget() const
+{
+ return dockManager()->centralWidget() == this;
+}
+
+
+//============================================================================
+void CDockWidget::toggleView(bool Open)
+{
+ // If the toggle view action mode is ActionModeShow, then Open is always
+ // true if the sender is the toggle view action
+ QAction* Sender = qobject_cast<QAction*>(sender());
+ if (Sender == d->ToggleViewAction && !d->ToggleViewAction->isCheckable())
+ {
+ Open = true;
+ }
+
+ // 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 && !AutoHideContainer)
+ {
+ raise();
+ }
+
+ if (Open && AutoHideContainer)
+ {
+ AutoHideContainer->collapseView(false);
+ }
+}
+
+
+//============================================================================
+void CDockWidget::toggleViewInternal(bool Open)
+{
+ CDockContainerWidget* DockContainer = dockContainer();
+ CDockWidget* TopLevelDockWidgetBefore = DockContainer
+ ? DockContainer->topLevelDockWidget() : nullptr;
+
+ d->Closed = !Open;
+
+ if (Open)
+ {
+ d->showDockWidget();
+ }
+ else
+ {
+ d->hideDockWidget();
+ }
+
+ d->ToggleViewAction->blockSignals(true);
+ d->ToggleViewAction->setChecked(Open);
+ d->ToggleViewAction->blockSignals(false);
+ if (d->DockArea)
+ {
+ d->DockArea->toggleDockWidgetView(this, Open);
+ if (d->DockArea->isAutoHide())
+ {
+ d->DockArea->autoHideDockContainer()->toggleView(Open);
+ }
+ }
+
+ if (Open && TopLevelDockWidgetBefore)
+ {
+ CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidgetBefore, false);
+ }
+
+ // Here we need to call the dockContainer() function again, because if
+ // this dock widget was unassigned before the call to showDockWidget() then
+ // it has a dock container now
+ DockContainer = dockContainer();
+ CDockWidget* TopLevelDockWidgetAfter = DockContainer
+ ? DockContainer->topLevelDockWidget() : nullptr;
+ CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidgetAfter, true);
+ CFloatingDockContainer* FloatingContainer = DockContainer
+ ? DockContainer->floatingWidget() : nullptr;
+ if (FloatingContainer)
+ {
+ FloatingContainer->updateWindowTitle();
+ }
+
+ if (!Open)
+ {
+ Q_EMIT closed();
+ }
+ Q_EMIT viewToggled(Open);
+}
+
+
+//============================================================================
+void CDockWidget::setDockArea(CDockAreaWidget* DockArea)
+{
+ d->DockArea = DockArea;
+ d->ToggleViewAction->setChecked(DockArea != nullptr && !this->isClosed());
+ setParent(DockArea);
+}
+
+
+//============================================================================
+void CDockWidget::saveState(QXmlStreamWriter& s) const
+{
+ s.writeStartElement("Widget");
+ s.writeAttribute("Name", objectName());
+ s.writeAttribute("Closed", QString::number(d->Closed ? 1 : 0));
+ s.writeEndElement();
+}
+
+
+//============================================================================
+void CDockWidget::flagAsUnassigned()
+{
+ d->Closed = true;
+ setVisible(false);
+ setDockArea(nullptr);
+ setParent(d->DockManager);
+ tabWidget()->setParent(this);
+}
+
+
+//============================================================================
+bool CDockWidget::event(QEvent *e)
+{
+ switch (e->type())
+ {
+ case QEvent::Hide:
+ Q_EMIT visibilityChanged(false);
+ break;
+
+ case QEvent::Show:
+ Q_EMIT visibilityChanged(geometry().right() >= 0 && geometry().bottom() >= 0);
+ break;
+
+ case QEvent::WindowTitleChange :
+ {
+ const auto title = windowTitle();
+ if (d->TabWidget)
+ {
+ d->TabWidget->setText(title);
+ }
+ if (d->SideTabWidget)
+ {
+ d->SideTabWidget->setText(title);
+ }
+ if (d->ToggleViewAction)
+ {
+ d->ToggleViewAction->setText(title);
+ }
+ if (d->DockArea)
+ {
+ d->DockArea->updateWindowTitle();
+ }
+
+ auto FloatingWidget = floatingDockContainer();
+ if (FloatingWidget)
+ {
+ FloatingWidget->updateWindowTitle();
+ }
+ Q_EMIT titleChanged(title);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return Super::event(e);
+}
+
+
+#ifndef QT_NO_TOOLTIP
+//============================================================================
+void CDockWidget::setTabToolTip(const QString &text)
+{
+ if (d->TabWidget)
+ {
+ d->TabWidget->setToolTip(text);
+ }
+ if (d->ToggleViewAction)
+ {
+ d->ToggleViewAction->setToolTip(text);
+ }
+ if (d->DockArea)
+ {
+ d->DockArea->markTitleBarMenuOutdated();//update tabs menu
+ }
+}
+#endif
+
+
+//============================================================================
+void CDockWidget::setIcon(const QIcon& Icon)
+{
+ d->TabWidget->setIcon(Icon);
+
+ if (d->SideTabWidget)
+ {
+ d->SideTabWidget->setIcon(Icon);
+ }
+
+ if (!d->ToggleViewAction->isCheckable())
+ {
+ d->ToggleViewAction->setIcon(Icon);
+ }
+}
+
+
+//============================================================================
+QIcon CDockWidget::icon() const
+{
+ return d->TabWidget->icon();
+}
+
+
+//============================================================================
+QToolBar* CDockWidget::toolBar() const
+{
+ return d->ToolBar;
+}
+
+
+//============================================================================
+QToolBar* CDockWidget::createDefaultToolBar()
+{
+ if (!d->ToolBar)
+ {
+ d->setupToolBar();
+ }
+
+ return d->ToolBar;
+}
+
+
+//============================================================================
+void CDockWidget::setToolBar(QToolBar* ToolBar)
+{
+ if (d->ToolBar)
+ {
+ delete d->ToolBar;
+ }
+
+ d->ToolBar = ToolBar;
+ d->Layout->insertWidget(0, d->ToolBar);
+ this->connect(this, SIGNAL(topLevelChanged(bool)), SLOT(setToolbarFloatingStyle(bool)));
+ setToolbarFloatingStyle(isFloating());
+}
+
+
+//============================================================================
+void CDockWidget::setToolBarStyle(Qt::ToolButtonStyle Style, eState State)
+{
+ if (StateFloating == State)
+ {
+ d->ToolBarStyleFloating = Style;
+ }
+ else
+ {
+ d->ToolBarStyleDocked = Style;
+ }
+
+ setToolbarFloatingStyle(isFloating());
+}
+
+
+//============================================================================
+Qt::ToolButtonStyle CDockWidget::toolBarStyle(eState State) const
+{
+ if (StateFloating == State)
+ {
+ return d->ToolBarStyleFloating;
+ }
+ else
+ {
+ return d->ToolBarStyleDocked;
+ }
+}
+
+
+//============================================================================
+void CDockWidget::setToolBarIconSize(const QSize& IconSize, eState State)
+{
+ if (StateFloating == State)
+ {
+ d->ToolBarIconSizeFloating = IconSize;
+ }
+ else
+ {
+ d->ToolBarIconSizeDocked = IconSize;
+ }
+
+ setToolbarFloatingStyle(isFloating());
+}
+
+
+//============================================================================
+QSize CDockWidget::toolBarIconSize(eState State) const
+{
+ if (StateFloating == State)
+ {
+ return d->ToolBarIconSizeFloating;
+ }
+ else
+ {
+ return d->ToolBarIconSizeDocked;
+ }
+}
+
+
+//============================================================================
+void CDockWidget::setToolbarFloatingStyle(bool Floating)
+{
+ if (!d->ToolBar)
+ {
+ return;
+ }
+
+ auto IconSize = Floating ? d->ToolBarIconSizeFloating : d->ToolBarIconSizeDocked;
+ if (IconSize != d->ToolBar->iconSize())
+ {
+ d->ToolBar->setIconSize(IconSize);
+ }
+
+ auto ButtonStyle = Floating ? d->ToolBarStyleFloating : d->ToolBarStyleDocked;
+ if (ButtonStyle != d->ToolBar->toolButtonStyle())
+ {
+ d->ToolBar->setToolButtonStyle(ButtonStyle);
+ }
+}
+
+
+//============================================================================
+void CDockWidget::emitTopLevelEventForWidget(CDockWidget* TopLevelDockWidget, bool Floating)
+{
+ if (TopLevelDockWidget)
+ {
+ TopLevelDockWidget->dockAreaWidget()->updateTitleBarVisibility();
+ TopLevelDockWidget->emitTopLevelChanged(Floating);
+ }
+}
+
+
+//============================================================================
+void CDockWidget::emitTopLevelChanged(bool Floating)
+{
+ if (Floating != d->IsFloatingTopLevel)
+ {
+ d->IsFloatingTopLevel = Floating;
+ Q_EMIT topLevelChanged(d->IsFloatingTopLevel);
+ }
+}
+
+
+//============================================================================
+void CDockWidget::setClosedState(bool Closed)
+{
+ d->Closed = Closed;
+}
+
+
+//============================================================================
+QSize CDockWidget::minimumSizeHint() const
+{
+ if (!d->Widget)
+ {
+ return QSize(60, 40);
+ }
+
+ switch (d->MinimumSizeHintMode)
+ {
+ 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();
+}
+
+
+//============================================================================
+void CDockWidget::setFloating()
+{
+ if (isClosed())
+ {
+ return;
+ }
+
+ if (this->isAutoHide())
+ {
+ dockAreaWidget()->setFloating();
+ }
+ else
+ {
+ d->TabWidget->detachDockWidget();
+ }
+}
+
+
+//============================================================================
+void CDockWidget::deleteDockWidget()
+{
+ auto manager=dockManager();
+ if(manager){
+ manager->removeDockWidget(this);
+ }
+ deleteLater();
+ d->Closed = true;
+}
+
+
+//============================================================================
+void CDockWidget::closeDockWidget()
+{
+ closeDockWidgetInternal(true);
+}
+
+
+
+//============================================================================
+void CDockWidget::requestCloseDockWidget()
+{
+ if (features().testFlag(CDockWidget::DockWidgetDeleteOnClose)
+ || features().testFlag(CDockWidget::CustomCloseHandling))
+ {
+ closeDockWidgetInternal(false);
+ }
+ else
+ {
+ toggleView(false);
+ }
+}
+
+
+//============================================================================
+bool CDockWidget::closeDockWidgetInternal(bool ForceClose)
+{
+ if (!ForceClose)
+ {
+ Q_EMIT closeRequested();
+ }
+
+ if (!ForceClose && features().testFlag(CDockWidget::CustomCloseHandling))
+ {
+ return false;
+ }
+
+ if (features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
+ {
+ // If the dock widget is floating, then we check if we also need to
+ // delete the floating widget
+ if (isFloating())
+ {
+ CFloatingDockContainer* FloatingWidget = internal::findParent<
+ CFloatingDockContainer*>(this);
+ if (FloatingWidget->dockWidgets().count() == 1)
+ {
+ FloatingWidget->deleteLater();
+ }
+ else
+ {
+ FloatingWidget->hide();
+ }
+ }
+ if (d->DockArea && d->DockArea->isAutoHide())
+ {
+ d->DockArea->autoHideDockContainer()->cleanupAndDelete();
+ }
+ deleteDockWidget();
+ Q_EMIT closed();
+ }
+ else
+ {
+ toggleView(false);
+ }
+
+ return true;
+}
+
+
+//============================================================================
+void CDockWidget::setTitleBarActions(QList<QAction*> actions)
+{
+ d->TitleBarActions = actions;
+}
+
+
+//============================================================================
+QList<QAction*> CDockWidget::titleBarActions() const
+{
+ return d->TitleBarActions;
+}
+
+
+//============================================================================
+void CDockWidget::showFullScreen()
+{
+ if (isFloating())
+ {
+ dockContainer()->floatingWidget()->showFullScreen();
+ }
+ else
+ {
+ Super::showFullScreen();
+ }
+}
+
+
+//============================================================================
+void CDockWidget::showNormal()
+{
+ if (isFloating())
+ {
+ dockContainer()->floatingWidget()->showNormal();
+ }
+ else
+ {
+ Super::showNormal();
+ }
+}
+
+
+//============================================================================
+bool CDockWidget::isFullScreen() const
+{
+ if (isFloating())
+ {
+ return dockContainer()->floatingWidget()->isFullScreen();
+ }
+ else
+ {
+ return Super::isFullScreen();
+ }
+}
+
+
+//============================================================================
+void CDockWidget::setAsCurrentTab()
+{
+ if (d->DockArea && !isClosed())
+ {
+ d->DockArea->setCurrentDockWidget(this);
+ }
+}
+
+
+//============================================================================
+bool CDockWidget::isTabbed() const
+{
+ return d->DockArea && (d->DockArea->openDockWidgetsCount() > 1);
+}
+
+
+
+//============================================================================
+bool CDockWidget::isCurrentTab() const
+{
+ return d->DockArea && (d->DockArea->currentDockWidget() == this);
+}
+
+
+//============================================================================
+void CDockWidget::raise()
+{
+ if (isClosed())
+ {
+ return;
+ }
+
+ setAsCurrentTab();
+ if (isInFloatingContainer())
+ {
+ auto FloatingWindow = window();
+ FloatingWindow->raise();
+ FloatingWindow->activateWindow();
+ }
+}
+
+
+//============================================================================
+void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location, int TabIndex)
+{
+ if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
+ {
+ return;
+ }
+
+ // Do nothing if nothing changes
+ if (Enable == isAutoHide() && Location == autoHideLocation())
+ {
+ return;
+ }
+
+ auto DockArea = dockAreaWidget();
+
+ if (!Enable)
+ {
+ DockArea->setAutoHide(false);
+ }
+ else if (isAutoHide())
+ {
+ autoHideDockContainer()->moveToNewSideBarLocation(Location);
+ }
+ else
+ {
+ auto area = Location;
+ if (SideBarNone == area && d->PreferredAutoHideSideBarLocation != SideBarNone)
+ {
+ area = d->PreferredAutoHideSideBarLocation;
+ }
+ else if (SideBarNone == area)
+ {
+ area = DockArea->calculateSideTabBarArea();
+ }
+ dockContainer()->createAndSetupAutoHideContainer(area, this, TabIndex);
+ }
+}
+
+
+//============================================================================
+void CDockWidget::toggleAutoHide(SideBarLocation Location)
+{
+ if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
+ {
+ return;
+ }
+
+ setAutoHide(!isAutoHide(), 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
+
+//---------------------------------------------------------------------------
+// EOF DockWidget.cpp
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidget.h b/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidget.h
index 2457385eb..04bec3477 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidget.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidget.h
@@ -1,708 +1,751 @@
-#ifndef DockWidgetH
-#define DockWidgetH
-/*******************************************************************************
-** Qt Advanced Docking System
-** Copyright (C) 2017 Uwe Kindler
-**
-** This library is free software; you can redistribute it and/or
-** modify it under the terms of the GNU Lesser General Public
-** License as published by the Free Software Foundation; either
-** version 2.1 of the License, or (at your option) any later version.
-**
-** This library is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-** Lesser General Public License for more details.
-**
-** You should have received a copy of the GNU Lesser General Public
-** License along with this library; If not, see <http://www.gnu.org/licenses/>.
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockWidget.h
-/// \author Uwe Kindler
-/// \date 26.02.2017
-/// \brief Declaration of CDockWidget class
-//============================================================================
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include <QFrame>
-
-#include "ads_globals.h"
-
-QT_FORWARD_DECLARE_CLASS(QToolBar)
-QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
-
-namespace ads
-{
-struct DockWidgetPrivate;
-class CDockWidgetTab;
-class CDockManager;
-class CDockContainerWidget;
-class CDockAreaWidget;
-class DockContainerWidgetPrivate;
-class CFloatingDockContainer;
-class CAutoHideTab;
-class CAutoHideDockContainer;
-class CAutoHideSideBar;
-
-/**
- * The QDockWidget class provides a widget that can be docked inside a
- * CDockManager or floated as a top-level window on the desktop.
- */
-class ADS_EXPORT CDockWidget : public QFrame
-{
- Q_OBJECT
-private:
- DockWidgetPrivate* d; ///< private data (pimpl)
- friend struct DockWidgetPrivate;
-
-private Q_SLOTS:
- /**
- * Adjusts the toolbar icon sizes according to the floating state
- */
- void setToolbarFloatingStyle(bool topLevel);
-
-protected:
- friend class CDockContainerWidget;
- friend class CDockAreaWidget;
- friend class CFloatingDockContainer;
- friend class CDockManager;
- friend struct DockManagerPrivate;
- friend class DockContainerWidgetPrivate;
- friend class CDockAreaTabBar;
- friend class CDockWidgetTab;
- friend struct DockWidgetTabPrivate;
- friend struct DockAreaTitleBarPrivate;
- friend class CAutoHideDockContainer;
- friend CAutoHideSideBar;
-
- /**
- * Assigns the dock manager that manages this dock widget
- */
- void setDockManager(CDockManager* DockManager);
-
- /**
- * If this dock widget is inserted into a dock area, the dock area will
- * be registered on this widget via this function. If a dock widget is
- * removed from a dock area, this function will be called with nullptr
- * value.
- */
- void setDockArea(CDockAreaWidget* DockArea);
-
- /**
- * This function changes the toggle view action without emitting any
- * signal
- */
- void setToggleViewActionChecked(bool Checked);
-
- /**
- * Saves the state into the given stream
- */
- void saveState(QXmlStreamWriter& Stream) const;
-
- /**
- * This is a helper function for the dock manager to flag this widget
- * as unassigned.
- * When calling the restore function, it may happen, that the saved state
- * contains less dock widgets then currently available. All widgets whose
- * data is not contained in the saved state, are flagged as unassigned
- * after the restore process. If the user shows an unassigned dock widget,
- * a floating widget will be created to take up the dock widget.
- */
- void flagAsUnassigned();
-
- /**
- * Call this function to emit a topLevelChanged() signal and to update
- * the dock area tool bar visibility
- */
- static void emitTopLevelEventForWidget(CDockWidget* TopLevelDockWidget, bool Floating);
-
- /**
- * Use this function to emit a top level changed event.
- * Do never use emit topLevelChanged(). Always use this function because
- * it only emits a signal if the floating state has really changed
- */
- void emitTopLevelChanged(bool Floating);
-
- /**
- * Internal function for modifying the closed state when restoring
- * a saved docking state
- */
- void setClosedState(bool Closed);
-
- /**
- * Internal toggle view function that does not check if the widget
- * already is in the given state
- */
- void toggleViewInternal(bool Open);
-
- /**
- * Internal close dock widget implementation.
- * The function returns true if the dock widget has been closed or hidden
- */
- bool closeDockWidgetInternal(bool ForceClose = false);
-
-public:
- using Super = QFrame;
-
- enum DockWidgetFeature
- {
- DockWidgetClosable = 0x001,///< dock widget has a close button
- DockWidgetMovable = 0x002,///< dock widget is movable and can be moved to a new position in the current dock container
- DockWidgetFloatable = 0x004,///< dock widget can be dragged into a floating window
- DockWidgetDeleteOnClose = 0x008, ///< deletes the dock widget when it is closed
- CustomCloseHandling = 0x010, ///< clicking the close button will not close the dock widget but emits the closeRequested() signal instead
- DockWidgetFocusable = 0x020, ///< if this is enabled, a dock widget can get focus highlighting
- DockWidgetForceCloseWithArea = 0x040, ///< dock widget will be closed when the dock area hosting it is closed
- NoTab = 0x080, ///< dock widget tab will never be shown if this flag is set
- DeleteContentOnClose = 0x100, ///< deletes only the contained widget on close, keeping the dock widget intact and in place. Attempts to rebuild the contents widget on show if there is a widget factory set.
- DockWidgetPinnable = 0x200, ///< dock widget can be pinned and added to an auto hide dock container
- DefaultDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable | DockWidgetFocusable | DockWidgetPinnable,
- AllDockWidgetFeatures = DefaultDockWidgetFeatures | DockWidgetDeleteOnClose | CustomCloseHandling,
- DockWidgetAlwaysCloseAndDelete = DockWidgetForceCloseWithArea | DockWidgetDeleteOnClose,
- GloballyLockableFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable | DockWidgetPinnable,
- NoDockWidgetFeatures = 0x000
- };
- Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature)
-
- enum eState
- {
- StateHidden,
- StateDocked,
- 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.
- * The content of a dock widget should be resizable do a very small size to
- * prevent the dock widget from blocking the resizing. To ensure, that a
- * dock widget can be resized very well, it is better to insert the content+
- * widget into a scroll area or to provide a widget that is already a scroll
- * area or that contains a scroll area.
- * If the InsertMode is AutoScrollArea, the DockWidget tries to automatically
- * detect how to insert the given widget. If the widget is derived from
- * QScrollArea (i.e. an QAbstractItemView), then the widget is inserted
- * directly. If the given widget is not a scroll area, the widget will be
- * inserted into a scroll area.
- * To force insertion into a scroll area, you can also provide the InsertMode
- * ForceScrollArea. To prevent insertion into a scroll area, you can
- * provide the InsertMode ForceNoScrollArea
- */
- enum eInsertMode
- {
- AutoScrollArea,
- ForceScrollArea,
- ForceNoScrollArea
- };
-
-
- /**
- * The mode of the minimumSizeHint() that is returned by the DockWidget
- * minimumSizeHint() function.
- * To ensure, that a dock widget does not block resizing, the dock widget
- * 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. 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,
- MinimumSizeHintFromDockWidgetMinimumSize,
- MinimumSizeHintFromContentMinimumSize,
- };
-
-
- /**
- * This mode configures the behavior of the toggle view action.
- * If the mode if ActionModeToggle, then the toggle view action is
- * a checkable action to show / hide the dock widget. If the mode
- * is ActionModeShow, then the action is not checkable an it will
- * always show the dock widget if clicked. If the mode is ActionModeShow,
- * the user can only close the DockWidget with the close button.
- */
- enum eToggleViewActionMode
- {
- ActionModeToggle,//!< ActionModeToggle
- ActionModeShow //!< ActionModeShow
- };
-
-
- /**
- * This constructor creates a dock widget with the given title.
- * The title is the text that is shown in the window title when the dock
- * widget is floating and it is the title that is shown in the titlebar
- * or the tab of this dock widget if it is tabified.
- * The object name of the dock widget is also set to the title. The
- * 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 explicitly
- * by calling setObjectName() after construction.
- * Use the layoutFlags to configure the layout of the dock widget.
- */
- CDockWidget(const QString &title, QWidget* parent = nullptr);
-
- /**
- * Virtual Destructor
- */
- virtual ~CDockWidget();
-
- /**
- * We return a fixed minimum size hint or the size hint of the content
- * widget if minimum size hint mode is MinimumSizeHintFromContent
- */
- virtual QSize minimumSizeHint() const override;
-
- /**
- * Sets the widget for the dock widget to widget.
- * The InsertMode defines how the widget is inserted into the dock widget.
- * The content of a dock widget should be resizable to a very small size to
- * prevent the dock widget from blocking the resizing. To ensure, that a
- * dock widget can be resized very well, it is better to insert the content+
- * widget into a scroll area or to provide a widget that is already a scroll
- * area or that contains a scroll area.
- * If the InsertMode is AutoScrollArea, the DockWidget tries to automatically
- * detect how to insert the given widget. If the widget is derived from
- * QScrollArea (i.e. an QAbstractItemView), then the widget is inserted
- * directly. If the given widget is not a scroll area, the widget will be
- * inserted into a scroll area.
- * To force insertion into a scroll area, you can also provide the InsertMode
- * ForceScrollArea. To prevent insertion into a scroll area, you can
- * provide the InsertMode ForceNoScrollArea
- */
- void setWidget(QWidget* widget, eInsertMode InsertMode = AutoScrollArea);
-
- /**
- * Only used when the feature flag DeleteContentOnClose is set.
- * Using the flag and setting a widget factory allows to free the resources
- * of the widget of your application while retaining the position the next
- * time you want to show your widget, unlike the flag DockWidgetDeleteOnClose
- * which deletes the dock widget itself. Since we keep the dock widget, all
- * regular features of ADS should work as normal, including saving and
- * restoring the state of the docking system and using perspectives.
- */
- using FactoryFunc = std::function<QWidget*(QWidget*)>;
- void setWidgetFactory(FactoryFunc createWidget, eInsertMode InsertMode = AutoScrollArea);
-
- /**
- * Remove the widget from the dock and give ownership back to the caller
- */
- QWidget* takeWidget();
-
- /**
- * Returns the widget for the dock widget. This function returns zero if
- * the widget has not been set.
- */
- QWidget* widget() const;
-
- /**
- * Returns the tab widget of this dock widget that is shown in the dock
- * area title bar
- */
- CDockWidgetTab* tabWidget() const;
-
- /**
- * Sets, whether the dock widget is movable, closable, and floatable.
- */
- void setFeatures(DockWidgetFeatures features);
-
- /**
- * Sets the feature flag for this dock widget if on is true; otherwise
- * clears the flag.
- */
- void setFeature(DockWidgetFeature flag, bool on);
-
- /**
- * This property holds whether the dock widget is movable, closable, and
- * floatable.
- * By default, this property is set to a combination of DockWidgetClosable,
- * DockWidgetMovable and DockWidgetFloatable.
- */
- DockWidgetFeatures features() const;
-
- /**
- * Triggers notification of feature change signals and functions
- */
- void notifyFeaturesChanged();
-
- /**
- * Returns the dock manager that manages the dock widget or 0 if the widget
- * has not been assigned to any dock manager yet
- */
- CDockManager* dockManager() const;
-
- /**
- * Returns the dock container widget this dock area widget belongs to or 0
- * if this dock widget has not been docked yet
- */
- CDockContainerWidget* dockContainer() const;
-
- /**
- * This function return the floating DockContainer if is isFloating() is true
- * and a nullptr if this dock widget is not floating.
- */
- CFloatingDockContainer* floatingDockContainer() const;
-
- /**
- * Returns the dock area widget this dock widget belongs to or 0
- * if this dock widget has not been docked yet
- */
- CDockAreaWidget* dockAreaWidget() const;
-
- /**
- * Returns the side tab widget for this dock, if this dock widget is in
- * a auto hide container. If it is not in a auto hide container, then this
- * function returns a nullptr,
- */
- CAutoHideTab* sideTabWidget() const;
-
- /**
- * Assign a side tab widget if this dock widget is an auto hide container
- */
- void setSideTabWidget(CAutoHideTab* SideTab) const;
-
- /**
- * Returns true, if this dock widget is in an auto hide container
- */
- bool isAutoHide() const;
-
- /**
- * Returns the auto hide dock container of this dock widget
- * or 0 if there is none
- */
- 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
- * of a floating container. If there are more than one dock widget in a
- * floating container, the all dock widgets are docked and not floating.
- */
- bool isFloating() const;
-
- /**
- * This function returns true, if this dock widget is in a floating.
- * The function returns true, if the dock widget is floating and it also
- * returns true if it is docked inside of a floating container.
- */
- bool isInFloatingContainer() const;
-
- /**
- * Returns true, if this dock widget is closed.
- */
- bool isClosed() const;
-
- /**
- * Returns a checkable action that can be used to show or close this dock widget.
- * The action's text is set to the dock widget's window title.
- */
- 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
- */
- void setToggleViewActionMode(eToggleViewActionMode Mode);
-
- /**
- * Configures the minimum size hint that is returned by the
- * minimumSizeHint() function.
- * \see eMinimumSizeHintMode for a detailed description
- */
- 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
- */
- bool isCentralWidget() const;
-
- /**
- * Sets the dock widget icon that is shown in tabs and in toggle view
- * actions
- */
- void setIcon(const QIcon& Icon);
-
- /**
- * Returns the icon that has been assigned to the dock widget
- */
- QIcon icon() const;
-
- /**
- * This function returns the dock widget top tool bar.
- * 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().
- */
- QToolBar* toolBar() const;
-
- /**
- * If you would like to use the default top tool bar, then call this
- * function to create the default tool bar.
- * After this function the toolBar() function will return a valid toolBar()
- * object.
- */
- QToolBar* createDefaultToolBar();
-
- /**
- * Assign a new tool bar that is shown above the content widget.
- * The dock widget will become the owner of the tool bar and deletes it
- * on destruction
- */
- 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.
- * 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 setToolBarStyle(Qt::ToolButtonStyle Style, eState State);
-
- /**
- * Returns the tool button style for the given docking state.
- * \see setToolBarStyle()
- */
- Qt::ToolButtonStyle toolBarStyle(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 an increasing the
- * icon size is possible. For docked widgets, small icon sizes, eg. 16 x 16
- * might be better.
- */
- void setToolBarIconSize(const QSize& IconSize, eState State);
-
- /**
- * Returns the icon size for a given docking state.
- * \see setToolBarIconSize()
- */
- QSize toolBarIconSize(eState State) const;
-
- /**
- * Set the actions that will be shown in the dock area title bar
- * if this dock widget is the active tab.
- * You should not add to many actions to the title bar, because this
- * will remove the available space for the tabs. If you have a number
- * of actions, just add an action with a menu to show a popup menu
- * button in the title bar.
- */
- void setTitleBarActions(QList<QAction*> actions);
-
- /**
- * Returns a list of actions that will be inserted into the dock area title
- * bar if this dock widget becomes the current widget
- */
- virtual QList<QAction*> titleBarActions() const;
-
-
-#ifndef QT_NO_TOOLTIP
- /**
- * This is function sets text tooltip for title bar widget
- * and tooltip for toggle view action
- */
- void setTabToolTip(const QString &text);
-#endif
-
- /**
- * Returns true if the dock widget is floating and if the floating dock
- * container is full screen
- */
- bool isFullScreen() const;
-
- /**
- * Returns true if this dock widget is in a dock area, that contains at
- * least 2 opened dock widgets
- */
- bool isTabbed() const;
-
- /**
- * Returns true if this dock widget is the current one in the dock
- * area widget that contains it.
- * If the dock widget is the only opened dock widget in a dock area,
- * the true is returned
- */
- bool isCurrentTab() const;
-
-public: // reimplements QFrame -----------------------------------------------
- /**
- * Emits titleChanged signal if title change event occurs
- */
- virtual bool event(QEvent *e) override;
-
-public Q_SLOTS:
- /**
- * This property controls whether the dock widget is open or closed.
- * The toogleViewAction triggers this slot
- */
- void toggleView(bool Open = true);
-
- /**
- * Makes this dock widget the current tab in its dock area.
- * The function only has an effect, if the dock widget is open. A call
- * to this function will not toggle the view, so if it is closed,
- * nothing will happen
- */
- void setAsCurrentTab();
-
- /**
- * Brings the dock widget to the front
- * This means:
- * - If the dock widget is tabbed with other dock widgets but its tab is not current, it's made current.
- * - If the dock widget is floating, QWindow::raise() is called.
- * This only applies if the dock widget is already open. If closed, does nothing.
- */
- void raise();
-
- /**
- * This function will make a docked widget floating
- */
- void setFloating();
-
- /**
- * This function will delete the dock widget and its content from the
- * docking system
- */
- void deleteDockWidget();
-
- /**
- * 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
- * compatible to QDockWidget, this function also maximizes a floating
- * dock widget.
- *
- * \note Full-screen mode works fine under Windows, but has certain
- * problems (doe not work) under X (Linux). These problems are due to
- * limitations of the ICCCM protocol that specifies the communication
- * between X11 clients and the window manager. ICCCM simply does not
- * understand the concept of non-decorated full-screen windows.
- */
- void showFullScreen();
-
- /**
- * This function complements showFullScreen() to restore the widget
- * after it has been in full screen mode.
- */
- void showNormal();
-
- /**
- * 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, int TabIndex = -1);
-
- /**
- * Switches the dock widget to auto hide mode or vice versa depending on its
- * current state.
- */
- void toggleAutoHide(SideBarLocation Location = SideBarNone);
-
-
-Q_SIGNALS:
- /**
- * This signal is emitted if the dock widget is opened or closed
- */
- void viewToggled(bool Open);
-
- /**
- * This signal is emitted if the dock widget is closed
- */
- void closed();
-
- /**
- * This signal is emitted if the window title of this dock widget
- * changed
- */
- void titleChanged(const QString& Title);
-
- /**
- * This signal is emitted when the floating property changes.
- * The topLevel parameter is true if the dock widget is now floating;
- * otherwise it is false.
- */
- void topLevelChanged(bool topLevel);
-
- /**
- * This signal is emitted, if close is requested
- */
- void closeRequested();
-
- /**
- * This signal is emitted when the dock widget becomes visible (or invisible).
- * This happens when the widget is hidden or shown, as well as when it is
- * docked in a tabbed dock area and its tab becomes selected or unselected.
- */
- void visibilityChanged(bool visible);
-
- /**
- * This signal is emitted when the features property changes.
- * The features parameter gives the new value of the property.
- */
- void featuresChanged(ads::CDockWidget::DockWidgetFeatures features);
-}; // class DockWidget
-} // namespace ads
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(ads::CDockWidget::DockWidgetFeatures)
-//-----------------------------------------------------------------------------
-#endif // DockWidgetH
+#ifndef DockWidgetH
+#define DockWidgetH
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockWidget.h
+/// \author Uwe Kindler
+/// \date 26.02.2017
+/// \brief Declaration of CDockWidget class
+//============================================================================
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include <QFrame>
+
+#include "ads_globals.h"
+
+QT_FORWARD_DECLARE_CLASS(QToolBar)
+QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
+
+namespace ads
+{
+struct DockWidgetPrivate;
+class CDockWidgetTab;
+class CDockManager;
+class CDockContainerWidget;
+class CDockAreaWidget;
+class DockContainerWidgetPrivate;
+class CFloatingDockContainer;
+class CAutoHideTab;
+class CAutoHideDockContainer;
+class CAutoHideSideBar;
+
+/**
+ * The QDockWidget class provides a widget that can be docked inside a
+ * CDockManager or floated as a top-level window on the desktop.
+ */
+class ADS_EXPORT CDockWidget : public QFrame
+{
+ Q_OBJECT
+private:
+ DockWidgetPrivate* d; ///< private data (pimpl)
+ friend struct DockWidgetPrivate;
+
+private Q_SLOTS:
+ /**
+ * Adjusts the toolbar icon sizes according to the floating state
+ */
+ void setToolbarFloatingStyle(bool topLevel);
+
+protected:
+ friend class CDockContainerWidget;
+ friend class CDockAreaWidget;
+ friend class CFloatingDockContainer;
+ friend class CDockManager;
+ friend struct DockManagerPrivate;
+ friend class DockContainerWidgetPrivate;
+ friend class CDockAreaTabBar;
+ friend class CDockWidgetTab;
+ friend struct DockWidgetTabPrivate;
+ friend struct DockAreaTitleBarPrivate;
+ friend class CAutoHideDockContainer;
+ friend CAutoHideSideBar;
+
+ /**
+ * Assigns the dock manager that manages this dock widget
+ */
+ void setDockManager(CDockManager* DockManager);
+
+ /**
+ * If this dock widget is inserted into a dock area, the dock area will
+ * be registered on this widget via this function. If a dock widget is
+ * removed from a dock area, this function will be called with nullptr
+ * value.
+ */
+ void setDockArea(CDockAreaWidget* DockArea);
+
+ /**
+ * This function changes the toggle view action without emitting any
+ * signal
+ */
+ void setToggleViewActionChecked(bool Checked);
+
+ /**
+ * Saves the state into the given stream
+ */
+ void saveState(QXmlStreamWriter& Stream) const;
+
+ /**
+ * This is a helper function for the dock manager to flag this widget
+ * as unassigned.
+ * When calling the restore function, it may happen, that the saved state
+ * contains less dock widgets then currently available. All widgets whose
+ * data is not contained in the saved state, are flagged as unassigned
+ * after the restore process. If the user shows an unassigned dock widget,
+ * a floating widget will be created to take up the dock widget.
+ */
+ void flagAsUnassigned();
+
+ /**
+ * Call this function to emit a topLevelChanged() signal and to update
+ * the dock area tool bar visibility
+ */
+ static void emitTopLevelEventForWidget(CDockWidget* TopLevelDockWidget, bool Floating);
+
+ /**
+ * Use this function to emit a top level changed event.
+ * Do never use emit topLevelChanged(). Always use this function because
+ * it only emits a signal if the floating state has really changed
+ */
+ void emitTopLevelChanged(bool Floating);
+
+ /**
+ * Internal function for modifying the closed state when restoring
+ * a saved docking state
+ */
+ void setClosedState(bool Closed);
+
+ /**
+ * Internal toggle view function that does not check if the widget
+ * already is in the given state
+ */
+ void toggleViewInternal(bool Open);
+
+ /**
+ * Internal close dock widget implementation.
+ * The function returns true if the dock widget has been closed or hidden
+ */
+ bool closeDockWidgetInternal(bool ForceClose = false);
+
+public:
+ using Super = QFrame;
+
+ enum DockWidgetFeature
+ {
+ DockWidgetClosable = 0x001,///< dock widget has a close button
+ DockWidgetMovable = 0x002,///< dock widget is movable and can be moved to a new position in the current dock container
+ DockWidgetFloatable = 0x004,///< dock widget can be dragged into a floating window
+ DockWidgetDeleteOnClose = 0x008, ///< deletes the dock widget when it is closed
+ CustomCloseHandling = 0x010, ///< clicking the close button will not close the dock widget but emits the closeRequested() signal instead
+ DockWidgetFocusable = 0x020, ///< if this is enabled, a dock widget can get focus highlighting
+ DockWidgetForceCloseWithArea = 0x040, ///< dock widget will be closed when the dock area hosting it is closed
+ NoTab = 0x080, ///< dock widget tab will never be shown if this flag is set
+ DeleteContentOnClose = 0x100, ///< deletes only the contained widget on close, keeping the dock widget intact and in place. Attempts to rebuild the contents widget on show if there is a widget factory set.
+ DockWidgetPinnable = 0x200, ///< dock widget can be pinned and added to an auto hide dock container
+ DefaultDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable | DockWidgetFocusable | DockWidgetPinnable,
+ AllDockWidgetFeatures = DefaultDockWidgetFeatures | DockWidgetDeleteOnClose | CustomCloseHandling,
+ DockWidgetAlwaysCloseAndDelete = DockWidgetForceCloseWithArea | DockWidgetDeleteOnClose,
+ GloballyLockableFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable | DockWidgetPinnable,
+ NoDockWidgetFeatures = 0x000
+ };
+ Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature)
+
+ enum eState
+ {
+ StateHidden,
+ StateDocked,
+ 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.
+ * The content of a dock widget should be resizable do a very small size to
+ * prevent the dock widget from blocking the resizing. To ensure, that a
+ * dock widget can be resized very well, it is better to insert the content+
+ * widget into a scroll area or to provide a widget that is already a scroll
+ * area or that contains a scroll area.
+ * If the InsertMode is AutoScrollArea, the DockWidget tries to automatically
+ * detect how to insert the given widget. If the widget is derived from
+ * QScrollArea (i.e. an QAbstractItemView), then the widget is inserted
+ * directly. If the given widget is not a scroll area, the widget will be
+ * inserted into a scroll area.
+ * To force insertion into a scroll area, you can also provide the InsertMode
+ * ForceScrollArea. To prevent insertion into a scroll area, you can
+ * provide the InsertMode ForceNoScrollArea
+ */
+ enum eInsertMode
+ {
+ AutoScrollArea,
+ ForceScrollArea,
+ ForceNoScrollArea
+ };
+
+
+ /**
+ * The mode of the minimumSizeHint() that is returned by the DockWidget
+ * minimumSizeHint() function.
+ * To ensure, that a dock widget does not block resizing, the dock widget
+ * 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. 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,
+ MinimumSizeHintFromDockWidgetMinimumSize,
+ MinimumSizeHintFromContentMinimumSize,
+ };
+
+
+ /**
+ * This mode configures the behavior of the toggle view action.
+ * If the mode if ActionModeToggle, then the toggle view action is
+ * a checkable action to show / hide the dock widget. If the mode
+ * is ActionModeShow, then the action is not checkable an it will
+ * always show the dock widget if clicked. If the mode is ActionModeShow,
+ * the user can only close the DockWidget with the close button.
+ */
+ enum eToggleViewActionMode
+ {
+ ActionModeToggle,//!< ActionModeToggle
+ ActionModeShow //!< ActionModeShow
+ };
+
+
+ /**
+ * This constructor creates a dock widget with the given title.
+ * The title is the text that is shown in the window title when the dock
+ * widget is floating and it is the title that is shown in the titlebar
+ * or the tab of this dock widget if it is tabified.
+ * The object name of the dock widget is also set to the title. The
+ * 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 explicitly
+ * by calling setObjectName() after construction.
+ * Use the layoutFlags to configure the layout of the dock widget.
+ * \note If you would like to use custom TabWidget implementations, you need
+ * to use the constructor with the CDockManager argument.
+ */
+ Q_DECL_DEPRECATED explicit CDockWidget(const QString &title, QWidget* parent = nullptr);
+
+ /**
+ * This constructor creates a dock widget for the given dock manager with the
+ * provided title.
+ *
+ * @param manager Pointer to the dock manager that owns the dock widget.
+ * @param title The title is the text that is shown in the window title when
+ * the dock widget is floating and it is the title that is shown in the
+ * titlebar or the tab of this dock widget if it is tabified.
+ * @param parent Pointer to the parent widget, defaults to nullptr.
+ *
+ * @note The object name of the dock widget is also set to the title. The
+ * 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
+ * the title is not unique or if you would like to change the title 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.
+ *
+ * @note this constructor is preferred over the two argument version, especially
+ * when custom factories are in use. Indeed, it will use the Dock Manager factory,
+ * and not the default factory. For this reason, the original constructor should
+ * be deprecated in favour of this version.
+ */
+ CDockWidget(CDockManager *manager, const QString &title, QWidget* parent = nullptr);
+
+ /**
+ * Virtual Destructor
+ */
+ ~CDockWidget() override;
+
+ /**
+ * We return a fixed minimum size hint or the size hint of the content
+ * widget if minimum size hint mode is MinimumSizeHintFromContent
+ */
+ virtual QSize minimumSizeHint() const override;
+
+ /**
+ * Sets the widget for the dock widget to widget.
+ * The InsertMode defines how the widget is inserted into the dock widget.
+ * The content of a dock widget should be resizable to a very small size to
+ * prevent the dock widget from blocking the resizing. To ensure, that a
+ * dock widget can be resized very well, it is better to insert the content+
+ * widget into a scroll area or to provide a widget that is already a scroll
+ * area or that contains a scroll area.
+ * If the InsertMode is AutoScrollArea, the DockWidget tries to automatically
+ * detect how to insert the given widget. If the widget is derived from
+ * QScrollArea (i.e. an QAbstractItemView), then the widget is inserted
+ * directly. If the given widget is not a scroll area, the widget will be
+ * inserted into a scroll area.
+ * To force insertion into a scroll area, you can also provide the InsertMode
+ * ForceScrollArea. To prevent insertion into a scroll area, you can
+ * provide the InsertMode ForceNoScrollArea
+ */
+ void setWidget(QWidget* widget, eInsertMode InsertMode = AutoScrollArea);
+
+ /**
+ * Only used when the feature flag DeleteContentOnClose is set.
+ * Using the flag and setting a widget factory allows to free the resources
+ * of the widget of your application while retaining the position the next
+ * time you want to show your widget, unlike the flag DockWidgetDeleteOnClose
+ * which deletes the dock widget itself. Since we keep the dock widget, all
+ * regular features of ADS should work as normal, including saving and
+ * restoring the state of the docking system and using perspectives.
+ */
+ using FactoryFunc = std::function<QWidget*(QWidget*)>;
+ void setWidgetFactory(FactoryFunc createWidget, eInsertMode InsertMode = AutoScrollArea);
+
+ /**
+ * Remove the widget from the dock and give ownership back to the caller
+ */
+ QWidget* takeWidget();
+
+ /**
+ * Returns the widget for the dock widget. This function returns zero if
+ * the widget has not been set.
+ */
+ QWidget* widget() const;
+
+ /**
+ * Returns the tab widget of this dock widget that is shown in the dock
+ * area title bar
+ */
+ CDockWidgetTab* tabWidget() const;
+
+ /**
+ * Sets, whether the dock widget is movable, closable, and floatable.
+ */
+ void setFeatures(DockWidgetFeatures features);
+
+ /**
+ * Sets the feature flag for this dock widget if on is true; otherwise
+ * clears the flag.
+ */
+ void setFeature(DockWidgetFeature flag, bool on);
+
+ /**
+ * This property holds whether the dock widget is movable, closable, and
+ * floatable.
+ * By default, this property is set to a combination of DockWidgetClosable,
+ * DockWidgetMovable and DockWidgetFloatable.
+ */
+ DockWidgetFeatures features() const;
+
+ /**
+ * Triggers notification of feature change signals and functions
+ */
+ void notifyFeaturesChanged();
+
+ /**
+ * Returns the dock manager that manages the dock widget or 0 if the widget
+ * has not been assigned to any dock manager yet
+ */
+ CDockManager* dockManager() const;
+
+ /**
+ * Returns the dock container widget this dock area widget belongs to or 0
+ * if this dock widget has not been docked yet
+ */
+ CDockContainerWidget* dockContainer() const;
+
+ /**
+ * This function return the floating DockContainer if is isFloating() is true
+ * and a nullptr if this dock widget is not floating.
+ */
+ CFloatingDockContainer* floatingDockContainer() const;
+
+ /**
+ * Returns the dock area widget this dock widget belongs to or 0
+ * if this dock widget has not been docked yet
+ */
+ CDockAreaWidget* dockAreaWidget() const;
+
+ /**
+ * Returns the side tab widget for this dock, if this dock widget is in
+ * a auto hide container. If it is not in a auto hide container, then this
+ * function returns a nullptr,
+ */
+ CAutoHideTab* sideTabWidget() const;
+
+ /**
+ * Assign a side tab widget if this dock widget is an auto hide container
+ */
+ void setSideTabWidget(CAutoHideTab* SideTab) const;
+
+ /**
+ * Returns true, if this dock widget is in an auto hide container
+ */
+ bool isAutoHide() const;
+
+ /**
+ * Returns the auto hide dock container of this dock widget
+ * or 0 if there is none
+ */
+ CAutoHideDockContainer* autoHideDockContainer() const;
+
+ /**
+ * Returns the auto hide side bar location or SideBarNone if, this is not
+ * an autohide dock widget
+ */
+ SideBarLocation autoHideLocation() const;
+
+ /**
+ * Sets the preferred auto-hide sidebar location for this dock widget.
+ * When set to a value other than SideBarNone, the pin button will place
+ * this widget in the specified sidebar instead of using geometry-based
+ * detection. When unpinning, widgets with the same preferred location
+ * will be merged as tabs in the same dock area.
+ * Set to SideBarNone (default) to use the original geometry-based behavior.
+ */
+ void setPreferredAutoHideSideBarLocation(SideBarLocation Location);
+
+ /**
+ * Returns the preferred auto-hide sidebar location, or SideBarNone
+ * if no preference is set (geometry-based detection will be used).
+ */
+ SideBarLocation preferredAutoHideSideBarLocation() 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
+ * of a floating container. If there are more than one dock widget in a
+ * floating container, the all dock widgets are docked and not floating.
+ */
+ bool isFloating() const;
+
+ /**
+ * This function returns true, if this dock widget is in a floating.
+ * The function returns true, if the dock widget is floating and it also
+ * returns true if it is docked inside of a floating container.
+ */
+ bool isInFloatingContainer() const;
+
+ /**
+ * Returns true, if this dock widget is closed.
+ */
+ bool isClosed() const;
+
+ /**
+ * Returns a checkable action that can be used to show or close this dock widget.
+ * The action's text is set to the dock widget's window title.
+ */
+ 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
+ */
+ void setToggleViewActionMode(eToggleViewActionMode Mode);
+
+ /**
+ * Configures the minimum size hint that is returned by the
+ * minimumSizeHint() function.
+ * \see eMinimumSizeHintMode for a detailed description
+ */
+ 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
+ */
+ bool isCentralWidget() const;
+
+ /**
+ * Sets the dock widget icon that is shown in tabs and in toggle view
+ * actions
+ */
+ void setIcon(const QIcon& Icon);
+
+ /**
+ * Returns the icon that has been assigned to the dock widget
+ */
+ QIcon icon() const;
+
+ /**
+ * This function returns the dock widget top tool bar.
+ * 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().
+ */
+ QToolBar* toolBar() const;
+
+ /**
+ * If you would like to use the default top tool bar, then call this
+ * function to create the default tool bar.
+ * After this function the toolBar() function will return a valid toolBar()
+ * object.
+ */
+ QToolBar* createDefaultToolBar();
+
+ /**
+ * Assign a new tool bar that is shown above the content widget.
+ * The dock widget will become the owner of the tool bar and deletes it
+ * on destruction
+ */
+ 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.
+ * 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 setToolBarStyle(Qt::ToolButtonStyle Style, eState State);
+
+ /**
+ * Returns the tool button style for the given docking state.
+ * \see setToolBarStyle()
+ */
+ Qt::ToolButtonStyle toolBarStyle(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 an increasing the
+ * icon size is possible. For docked widgets, small icon sizes, eg. 16 x 16
+ * might be better.
+ */
+ void setToolBarIconSize(const QSize& IconSize, eState State);
+
+ /**
+ * Returns the icon size for a given docking state.
+ * \see setToolBarIconSize()
+ */
+ QSize toolBarIconSize(eState State) const;
+
+ /**
+ * Set the actions that will be shown in the dock area title bar
+ * if this dock widget is the active tab.
+ * You should not add to many actions to the title bar, because this
+ * will remove the available space for the tabs. If you have a number
+ * of actions, just add an action with a menu to show a popup menu
+ * button in the title bar.
+ */
+ void setTitleBarActions(QList<QAction*> actions);
+
+ /**
+ * Returns a list of actions that will be inserted into the dock area title
+ * bar if this dock widget becomes the current widget
+ */
+ virtual QList<QAction*> titleBarActions() const;
+
+
+#ifndef QT_NO_TOOLTIP
+ /**
+ * This is function sets text tooltip for title bar widget
+ * and tooltip for toggle view action
+ */
+ void setTabToolTip(const QString &text);
+#endif
+
+ /**
+ * Returns true if the dock widget is floating and if the floating dock
+ * container is full screen
+ */
+ bool isFullScreen() const;
+
+ /**
+ * Returns true if this dock widget is in a dock area, that contains at
+ * least 2 opened dock widgets
+ */
+ bool isTabbed() const;
+
+ /**
+ * Returns true if this dock widget is the current one in the dock
+ * area widget that contains it.
+ * If the dock widget is the only opened dock widget in a dock area,
+ * the true is returned
+ */
+ bool isCurrentTab() const;
+
+public: // reimplements QFrame -----------------------------------------------
+ /**
+ * Emits titleChanged signal if title change event occurs
+ */
+ virtual bool event(QEvent *e) override;
+
+public Q_SLOTS:
+ /**
+ * This property controls whether the dock widget is open or closed.
+ * The toogleViewAction triggers this slot
+ */
+ void toggleView(bool Open = true);
+
+ /**
+ * Makes this dock widget the current tab in its dock area.
+ * The function only has an effect, if the dock widget is open. A call
+ * to this function will not toggle the view, so if it is closed,
+ * nothing will happen
+ */
+ void setAsCurrentTab();
+
+ /**
+ * Brings the dock widget to the front
+ * This means:
+ * - If the dock widget is tabbed with other dock widgets but its tab is not current, it's made current.
+ * - If the dock widget is floating, QWindow::raise() is called.
+ * This only applies if the dock widget is already open. If closed, does nothing.
+ */
+ void raise();
+
+ /**
+ * This function will make a docked widget floating
+ */
+ void setFloating();
+
+ /**
+ * This function will delete the dock widget and its content from the
+ * docking system
+ */
+ void deleteDockWidget();
+
+ /**
+ * 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
+ * compatible to QDockWidget, this function also maximizes a floating
+ * dock widget.
+ *
+ * \note Full-screen mode works fine under Windows, but has certain
+ * problems (doe not work) under X (Linux). These problems are due to
+ * limitations of the ICCCM protocol that specifies the communication
+ * between X11 clients and the window manager. ICCCM simply does not
+ * understand the concept of non-decorated full-screen windows.
+ */
+ void showFullScreen();
+
+ /**
+ * This function complements showFullScreen() to restore the widget
+ * after it has been in full screen mode.
+ */
+ void showNormal();
+
+ /**
+ * 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, int TabIndex = -1);
+
+ /**
+ * Switches the dock widget to auto hide mode or vice versa depending on its
+ * current state.
+ */
+ void toggleAutoHide(SideBarLocation Location = SideBarNone);
+
+
+Q_SIGNALS:
+ /**
+ * This signal is emitted if the dock widget is opened or closed
+ */
+ void viewToggled(bool Open);
+
+ /**
+ * This signal is emitted if the dock widget is closed
+ */
+ void closed();
+
+ /**
+ * This signal is emitted if the window title of this dock widget
+ * changed
+ */
+ void titleChanged(const QString& Title);
+
+ /**
+ * This signal is emitted when the floating property changes.
+ * The topLevel parameter is true if the dock widget is now floating;
+ * otherwise it is false.
+ */
+ void topLevelChanged(bool topLevel);
+
+ /**
+ * This signal is emitted, if close is requested
+ */
+ void closeRequested();
+
+ /**
+ * This signal is emitted when the dock widget becomes visible (or invisible).
+ * This happens when the widget is hidden or shown, as well as when it is
+ * docked in a tabbed dock area and its tab becomes selected or unselected.
+ */
+ void visibilityChanged(bool visible);
+
+ /**
+ * This signal is emitted when the features property changes.
+ * The features parameter gives the new value of the property.
+ */
+ void featuresChanged(ads::CDockWidget::DockWidgetFeatures features);
+}; // class DockWidget
+} // namespace ads
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(ads::CDockWidget::DockWidgetFeatures)
+//-----------------------------------------------------------------------------
+#endif // DockWidgetH
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidgetTab.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidgetTab.cpp
index 962de1723..757973a62 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidgetTab.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidgetTab.cpp
@@ -50,7 +50,6 @@
#include "FloatingDockContainer.h"
#include "DockOverlay.h"
#include "DockManager.h"
-#include "IconProvider.h"
#include "DockFocusController.h"
@@ -110,6 +109,14 @@ struct DockWidgetTabPrivate
*/
bool startFloating(eDragState DraggingState = DraggingFloatingWidget);
+ /**
+ * Wayland hybrid drag: drive the in-window drag preview from reliable
+ * event coordinates and, when the cursor leaves the source top-level
+ * window, convert the in-window drag into a native compositor platform
+ * drag.
+ */
+ void waylandPreviewMove(QMouseEvent* ev);
+
/**
* Returns true if the given config flag is set
*/
@@ -170,7 +177,7 @@ struct DockWidgetTabPrivate
else
{
auto w = new CFloatingDragPreview(Widget);
- _this->connect(w, &CFloatingDragPreview::draggingCanceled, [=]()
+ _this->connect(w, &CFloatingDragPreview::draggingCanceled, [this]()
{
DragState = DraggingInactive;
});
@@ -312,12 +319,30 @@ bool DockWidgetTabPrivate::startFloating(eDragState DraggingState)
&& (dockContainer->visibleDockAreaCount() == 1)
&& (DockWidget->dockAreaWidget()->dockWidgetsCount() == 1))
{
+ // On Wayland, dragging the tab of the single dock widget of a
+ // floating widget drags the existing floating widget, so the user
+ // can dock it into another container
+ if (internal::isWayland() && (DraggingFloatingWidget == DraggingState))
+ {
+ auto FloatingContainer = dockContainer->floatingWidget();
+ if (FloatingContainer)
+ {
+ DragState = DraggingInactive;
+ CFloatingDockContainer::startPlatformDrag(FloatingContainer,
+ GlobalDragStartMousePosition, _this);
+ return true;
+ }
+ }
return false;
}
ADS_PRINT("startFloating");
DragState = DraggingState;
IFloatingWidget* FloatingWidget = nullptr;
+ // On Wayland the drag preview is an in-window child widget (driven by event
+ // coordinates, confined to the source container); it converts to a native
+ // compositor platform drag only when the cursor leaves the source window
+ // (see waylandPreviewMove()). So a drag uses a preview on every platform.
bool CreateContainer = (DraggingFloatingWidget != DraggingState);
// If section widget has multiple tabs, we take only one tab
@@ -342,6 +367,15 @@ bool DockWidgetTabPrivate::startFloating(eDragState DraggingState)
auto Overlay = DockManager->containerOverlay();
Overlay->setAllowedAreas(OuterDockAreas);
this->FloatingWidget = FloatingWidget;
+ if (internal::isWayland())
+ {
+ // Confine the in-window preview to the source container; its
+ // position and the drop overlays are driven by event coordinates
+ // delivered to the tab (see waylandPreviewMove()). FloatingWidget is
+ // a CFloatingDragPreview here because CreateContainer was false.
+ auto Preview = static_cast<CFloatingDragPreview*>(FloatingWidget);
+ Preview->setSourceContainer(dockContainer);
+ }
qApp->postEvent(DockWidget, new QEvent((QEvent::Type)internal::DockedWidgetDragStartEvent));
}
else
@@ -353,6 +387,43 @@ bool DockWidgetTabPrivate::startFloating(eDragState DraggingState)
}
+//============================================================================
+void DockWidgetTabPrivate::waylandPreviewMove(QMouseEvent* ev)
+{
+ const QPoint GlobalPos = internal::globalPositionOf(ev);
+
+ // FloatingWidget is a CFloatingDragPreview during the in-window phase
+ // (DraggingFloatingWidget state on Wayland; see startFloating()). While the
+ // cursor stays inside the source window the preview just follows it.
+ auto Preview = static_cast<CFloatingDragPreview*>(FloatingWidget);
+ if (CFloatingDockContainer::waylandMoveOrLeaveInWindowPreview(
+ Preview, _this->window(), GlobalPos))
+ {
+ return;
+ }
+
+ // Boundary cross: the preview was torn down, convert the gesture into a
+ // native compositor platform drag of a freshly created floating widget.
+ FloatingWidget = nullptr;
+ DragState = DraggingInactive;
+
+ QSize Size;
+ IFloatingWidget* RealFloating = nullptr;
+ if (DockArea->dockWidgetsCount() > 1)
+ {
+ RealFloating = createFloatingWidget(DockWidget, true);
+ Size = DockWidget->size();
+ }
+ else
+ {
+ RealFloating = createFloatingWidget(DockArea, true);
+ Size = DockArea->size();
+ }
+ CFloatingDockContainer::startPlatformDragForFloatingWidget(RealFloating,
+ DragStartMousePosition, Size, GlobalDragStartMousePosition, _this);
+}
+
+
//============================================================================
CDockWidgetTab::CDockWidgetTab(CDockWidget* DockWidget, QWidget *parent) :
QFrame(parent),
@@ -458,7 +529,16 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
// move floating window
if (d->isDraggingState(DraggingFloatingWidget))
{
- d->FloatingWidget->moveFloating();
+ if (internal::isWayland())
+ {
+ // Wayland hybrid drag: in-window preview until the cursor leaves
+ // the source window, then convert to a native platform drag.
+ d->waylandPreviewMove(ev);
+ }
+ else
+ {
+ d->FloatingWidget->moveFloating();
+ }
Super::mouseMoveEvent(ev);
return;
}
@@ -479,10 +559,14 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
{
// If this is the last dock area in a dock container with only
// one single dock widget it does not make sense to move it to a new
- // floating widget and leave this one empty
+ // floating widget and leave this one empty.
+ // On Wayland we fall through, because dragging the tab drags the
+ // existing floating widget so the user can dock it into another
+ // container
if (d->DockArea->dockContainer()->isFloating()
&& d->DockArea->openDockWidgetsCount() == 1
- && d->DockArea->dockContainer()->visibleDockAreaCount() == 1)
+ && d->DockArea->dockContainer()->visibleDockAreaCount() == 1
+ && !internal::isWayland())
{
return;
}
@@ -529,26 +613,35 @@ void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev)
return;
}
+ auto Menu = buildContextMenu(nullptr);
d->saveDragStartMousePosition(ev->globalPos());
+ Menu->exec(ev->globalPos());
+}
+QMenu* CDockWidgetTab::buildContextMenu(QMenu *Menu)
+{
+ if (Menu == nullptr) {
+ Menu = new QMenu(this);
+ }
+
+ ADS_PRINT("CDockWidgetTab::buildContextMenu");
const bool isFloatable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable);
- const bool isNotOnlyTabInContainer = !d->DockArea->dockContainer()->hasTopLevelDockWidget();
const bool isTopLevelArea = d->DockArea->isTopLevelArea();
- const bool isDetachable = isFloatable && isNotOnlyTabInContainer;
+ const bool isFloating = d->DockWidget->isFloating();
+ const bool isDetachable = isFloatable && !isFloating;
QAction* Action;
- QMenu Menu(this);
- if (!isTopLevelArea)
+ if (!(isTopLevelArea && isFloating))
{
- Action = Menu.addAction(tr("Detach"), this, SLOT(detachDockWidget()));
+ Action = Menu->addAction(tr("Detach"), this, SLOT(detachDockWidget()));
Action->setEnabled(isDetachable);
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
{
- Action = Menu.addAction(tr("Pin"), this, SLOT(autoHideDockWidget()));
+ Action = Menu->addAction(tr("Pin"), this, SLOT(autoHideDockWidget()));
auto IsPinnable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable);
Action->setEnabled(IsPinnable);
- auto menu = Menu.addMenu(tr("Pin To..."));
+ auto menu = Menu->addMenu(tr("Pin To..."));
menu->setEnabled(IsPinnable);
d->createAutoHideToAction(tr("Top"), SideBarTop, menu);
d->createAutoHideToAction(tr("Left"), SideBarLeft, menu);
@@ -557,17 +650,16 @@ void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev)
}
}
- Menu.addSeparator();
- Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested()));
+ Menu->addSeparator();
+ Action = Menu->addAction(tr("Close"), this, SIGNAL(closeRequested()));
Action->setEnabled(isClosable());
if (d->DockArea->openDockWidgetsCount() > 1)
{
- Action = Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested()));
+ Menu->addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested()));
}
- Menu.exec(ev->globalPos());
-}
-
+ return Menu;
+}
//============================================================================
bool CDockWidgetTab::isActiveTab() const
{
@@ -592,9 +684,9 @@ void CDockWidgetTab::setActiveTab(bool active)
if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting) && !d->DockWidget->dockManager()->isRestoringState())
{
bool UpdateFocusStyle = false;
- if (active && !hasFocus())
- {
- //setFocus(Qt::OtherFocusReason);
+ // Update the focus only, if this the dock area of this tab is the focused dock area
+ if (active && !hasFocus() && (d->focusController()->focusedDockArea() == this->dockAreaWidget()))
+ {
d->focusController()->setDockWidgetTabFocused(this);
UpdateFocusStyle = true;
}
@@ -692,7 +784,7 @@ QString CDockWidgetTab::text() const
//============================================================================
void CDockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event)
{
- if (event->button() == Qt::LeftButton)
+ if (event->button() == Qt::LeftButton && CDockManager::testConfigFlag(CDockManager::DoubleClickUndocksWidget))
{
// 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
@@ -789,6 +881,13 @@ bool CDockWidgetTab::event(QEvent *e)
}
+//============================================================================
+eDragState CDockWidgetTab::dragState() const
+{
+ return d->DragState;
+}
+
+
//============================================================================
void CDockWidgetTab::onDockWidgetFeaturesChanged()
{
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidgetTab.h b/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidgetTab.h
index 0b5ba718e..e90f1da55 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidgetTab.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/DockWidgetTab.h
@@ -35,6 +35,8 @@
#include "ads_globals.h"
+QT_FORWARD_DECLARE_CLASS(QMenu)
+
namespace ads
{
class CDockWidget;
@@ -89,7 +91,7 @@ public:
/**
* Virtual Destructor
*/
- virtual ~CDockWidgetTab();
+ ~CDockWidgetTab() override;
/**
* Returns true, if this is the active tab
@@ -178,6 +180,26 @@ public:
*/
void setIconSize(const QSize& Size);
+ /**
+ * Returns the current drag state of this tab.
+ * Use this function to determine if the tab is currently being dragged
+ */
+ eDragState dragState() const;
+
+ /**
+ * Fills the provided menu with standard entries. If a nullptr is passed, a
+ * new menu is created and filled with standard entries.
+ * This function is called from the actual version of contextMenuEvent, but
+ * can be called from any code. Caller is responsible of deleting the created
+ * object.
+ *
+ * @param menu The QMenu to fill with standard entries. If nullptr, a new
+ * QMenu will be created.
+ * @return The filled QMenu, either the provided one or a newly created one if
+ * nullptr was passed.
+ */
+ virtual QMenu *buildContextMenu(QMenu *);
+
public Q_SLOTS:
virtual void setVisible(bool visible) override;
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDockContainer.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDockContainer.cpp
index 885553862..de11bcf8f 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDockContainer.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDockContainer.cpp
@@ -1,1427 +1,1696 @@
-/*******************************************************************************
- ** Qt Advanced Docking System
- ** Copyright (C) 2017 Uwe Kindler
- **
- ** This library is free software; you can redistribute it and/or
- ** modify it under the terms of the GNU Lesser General Public
- ** License as published by the Free Software Foundation; either
- ** version 2.1 of the License, or (at your option) any later version.
- **
- ** This library is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- ** Lesser General Public License for more details.
- **
- ** You should have received a copy of the GNU Lesser General Public
- ** License along with this library; If not, see <http://www.gnu.org/licenses/>.
- ******************************************************************************/
-
-//============================================================================
-/// \file FloatingDockContainer.cpp
-/// \author Uwe Kindler
-/// \date 01.03.2017
-/// \brief Implementation of CFloatingDockContainer class
-//============================================================================
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include "FloatingDockContainer.h"
-
-#include <iostream>
-
-#include <QBoxLayout>
-#include <QApplication>
-#include <QMouseEvent>
-#include <QPointer>
-#include <QAction>
-#include <QDebug>
-#include <QAbstractButton>
-#include <QElapsedTimer>
-#include <QTime>
-
-#include "DockContainerWidget.h"
-#include "DockAreaWidget.h"
-#include "DockManager.h"
-#include "DockWidget.h"
-#include "DockOverlay.h"
-
-#ifdef Q_OS_WIN
-#include <windows.h>
-#ifdef _MSC_VER
-#pragma comment(lib, "User32.lib")
-#endif
-#endif
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
-#include "linux/FloatingWidgetTitleBar.h"
-#include <xcb/xcb.h>
-#endif
-
-namespace ads
-{
-#ifdef Q_OS_WIN
-#if 0 // set to 1 if you need this function for debugging
-/**
- * Just for debugging to convert windows message identifiers to strings
- */
-static const char* windowsMessageString(int MessageId)
-{
- switch (MessageId)
- {
- case 0: return "WM_NULL";
- case 1: return "WM_CREATE";
- case 2: return "WM_DESTROY";
- case 3: return "WM_MOVE";
- case 5: return "WM_SIZE";
- case 6: return "WM_ACTIVATE";
- case 7: return "WM_SETFOCUS";
- case 8: return "WM_KILLFOCUS";
- case 10: return "WM_ENABLE";
- case 11: return "WM_SETREDRAW";
- case 12: return "WM_SETTEXT";
- case 13: return "WM_GETTEXT";
- case 14: return "WM_GETTEXTLENGTH";
- case 15: return "WM_PAINT";
- case 16: return "WM_CLOSE";
- case 17: return "WM_QUERYENDSESSION";
- case 18: return "WM_QUIT";
- case 19: return "WM_QUERYOPEN";
- case 20: return "WM_ERASEBKGND";
- case 21: return "WM_SYSCOLORCHANGE";
- case 22: return "WM_ENDSESSION";
- case 24: return "WM_SHOWWINDOW";
- case 25: return "WM_CTLCOLOR";
- case 26: return "WM_WININICHANGE";
- case 27: return "WM_DEVMODECHANGE";
- case 28: return "WM_ACTIVATEAPP";
- case 29: return "WM_FONTCHANGE";
- case 30: return "WM_TIMECHANGE";
- case 31: return "WM_CANCELMODE";
- case 32: return "WM_SETCURSOR";
- case 33: return "WM_MOUSEACTIVATE";
- case 34: return "WM_CHILDACTIVATE";
- case 35: return "WM_QUEUESYNC";
- case 36: return "WM_GETMINMAXINFO";
- case 38: return "WM_PAINTICON";
- case 39: return "WM_ICONERASEBKGND";
- case 40: return "WM_NEXTDLGCTL";
- case 42: return "WM_SPOOLERSTATUS";
- case 43: return "WM_DRAWITEM";
- case 44: return "WM_MEASUREITEM";
- case 45: return "WM_DELETEITEM";
- case 46: return "WM_VKEYTOITEM";
- case 47: return "WM_CHARTOITEM";
- case 48: return "WM_SETFONT";
- case 49: return "WM_GETFONT";
- case 50: return "WM_SETHOTKEY";
- case 51: return "WM_GETHOTKEY";
- case 55: return "WM_QUERYDRAGICON";
- case 57: return "WM_COMPAREITEM";
- case 61: return "WM_GETOBJECT";
- case 65: return "WM_COMPACTING";
- case 68: return "WM_COMMNOTIFY";
- case 70: return "WM_WINDOWPOSCHANGING";
- case 71: return "WM_WINDOWPOSCHANGED";
- case 72: return "WM_POWER";
- case 73: return "WM_COPYGLOBALDATA";
- case 74: return "WM_COPYDATA";
- case 75: return "WM_CANCELJOURNAL";
- case 78: return "WM_NOTIFY";
- case 80: return "WM_INPUTLANGCHANGEREQUEST";
- case 81: return "WM_INPUTLANGCHANGE";
- case 82: return "WM_TCARD";
- case 83: return "WM_HELP";
- case 84: return "WM_USERCHANGED";
- case 85: return "WM_NOTIFYFORMAT";
- case 123: return "WM_CONTEXTMENU";
- case 124: return "WM_STYLECHANGING";
- case 125: return "WM_STYLECHANGED";
- case 126: return "WM_DISPLAYCHANGE";
- case 127: return "WM_GETICON";
- case 128: return "WM_SETICON";
- case 129: return "WM_NCCREATE";
- case 130: return "WM_NCDESTROY";
- case 131: return "WM_NCCALCSIZE";
- case 132: return "WM_NCHITTEST";
- case 133: return "WM_NCPAINT";
- case 134: return "WM_NCACTIVATE";
- case 135: return "WM_GETDLGCODE";
- case 136: return "WM_SYNCPAINT";
- case 160: return "WM_NCMOUSEMOVE";
- case 161: return "WM_NCLBUTTONDOWN";
- case 162: return "WM_NCLBUTTONUP";
- case 163: return "WM_NCLBUTTONDBLCLK";
- case 164: return "WM_NCRBUTTONDOWN";
- case 165: return "WM_NCRBUTTONUP";
- case 166: return "WM_NCRBUTTONDBLCLK";
- case 167: return "WM_NCMBUTTONDOWN";
- case 168: return "WM_NCMBUTTONUP";
- case 169: return "WM_NCMBUTTONDBLCLK";
- case 171: return "WM_NCXBUTTONDOWN";
- case 172: return "WM_NCXBUTTONUP";
- case 173: return "WM_NCXBUTTONDBLCLK";
- case 176: return "EM_GETSEL";
- case 177: return "EM_SETSEL";
- case 178: return "EM_GETRECT";
- case 179: return "EM_SETRECT";
- case 180: return "EM_SETRECTNP";
- case 181: return "EM_SCROLL";
- case 182: return "EM_LINESCROLL";
- case 183: return "EM_SCROLLCARET";
- case 185: return "EM_GETMODIFY";
- case 187: return "EM_SETMODIFY";
- case 188: return "EM_GETLINECOUNT";
- case 189: return "EM_LINEINDEX";
- case 190: return "EM_SETHANDLE";
- case 191: return "EM_GETHANDLE";
- case 192: return "EM_GETTHUMB";
- case 193: return "EM_LINELENGTH";
- case 194: return "EM_REPLACESEL";
- case 195: return "EM_SETFONT";
- case 196: return "EM_GETLINE";
- case 197: return "EM_LIMITTEXT / EM_SETLIMITTEXT";
- case 198: return "EM_CANUNDO";
- case 199: return "EM_UNDO";
- case 200: return "EM_FMTLINES";
- case 201: return "EM_LINEFROMCHAR";
- case 202: return "EM_SETWORDBREAK";
- case 203: return "EM_SETTABSTOPS";
- case 204: return "EM_SETPASSWORDCHAR";
- case 205: return "EM_EMPTYUNDOBUFFER";
- case 206: return "EM_GETFIRSTVISIBLELINE";
- case 207: return "EM_SETREADONLY";
- case 209: return "EM_SETWORDBREAKPROC / EM_GETWORDBREAKPROC";
- case 210: return "EM_GETPASSWORDCHAR";
- case 211: return "EM_SETMARGINS";
- case 212: return "EM_GETMARGINS";
- case 213: return "EM_GETLIMITTEXT";
- case 214: return "EM_POSFROMCHAR";
- case 215: return "EM_CHARFROMPOS";
- case 216: return "EM_SETIMESTATUS";
- case 217: return "EM_GETIMESTATUS";
- case 224: return "SBM_SETPOS";
- case 225: return "SBM_GETPOS";
- case 226: return "SBM_SETRANGE";
- case 227: return "SBM_GETRANGE";
- case 228: return "SBM_ENABLE_ARROWS";
- case 230: return "SBM_SETRANGEREDRAW";
- case 233: return "SBM_SETSCROLLINFO";
- case 234: return "SBM_GETSCROLLINFO";
- case 235: return "SBM_GETSCROLLBARINFO";
- case 240: return "BM_GETCHECK";
- case 241: return "BM_SETCHECK";
- case 242: return "BM_GETSTATE";
- case 243: return "BM_SETSTATE";
- case 244: return "BM_SETSTYLE";
- case 245: return "BM_CLICK";
- case 246: return "BM_GETIMAGE";
- case 247: return "BM_SETIMAGE";
- case 248: return "BM_SETDONTCLICK";
- case 255: return "WM_INPUT";
- case 256: return "WM_KEYDOWN";
- case 257: return "WM_KEYUP";
- case 258: return "WM_CHAR";
- case 259: return "WM_DEADCHAR";
- case 260: return "WM_SYSKEYDOWN";
- case 261: return "WM_SYSKEYUP";
- case 262: return "WM_SYSCHAR";
- case 263: return "WM_SYSDEADCHAR";
- case 265: return "WM_UNICHAR / WM_WNT_CONVERTREQUESTEX";
- case 266: return "WM_CONVERTREQUEST";
- case 267: return "WM_CONVERTRESULT";
- case 268: return "WM_INTERIM";
- case 269: return "WM_IME_STARTCOMPOSITION";
- case 270: return "WM_IME_ENDCOMPOSITION";
- case 272: return "WM_INITDIALOG";
- case 273: return "WM_COMMAND";
- case 274: return "WM_SYSCOMMAND";
- case 275: return "WM_TIMER";
- case 276: return "WM_HSCROLL";
- case 277: return "WM_VSCROLL";
- case 278: return "WM_INITMENU";
- case 279: return "WM_INITMENUPOPUP";
- case 280: return "WM_SYSTIMER";
- case 287: return "WM_MENUSELECT";
- case 288: return "WM_MENUCHAR";
- case 289: return "WM_ENTERIDLE";
- case 290: return "WM_MENURBUTTONUP";
- case 291: return "WM_MENUDRAG";
- case 292: return "WM_MENUGETOBJECT";
- case 293: return "WM_UNINITMENUPOPUP";
- case 294: return "WM_MENUCOMMAND";
- case 295: return "WM_CHANGEUISTATE";
- case 296: return "WM_UPDATEUISTATE";
- case 297: return "WM_QUERYUISTATE";
- case 306: return "WM_CTLCOLORMSGBOX";
- case 307: return "WM_CTLCOLOREDIT";
- case 308: return "WM_CTLCOLORLISTBOX";
- case 309: return "WM_CTLCOLORBTN";
- case 310: return "WM_CTLCOLORDLG";
- case 311: return "WM_CTLCOLORSCROLLBAR";
- case 312: return "WM_CTLCOLORSTATIC";
- case 512: return "WM_MOUSEMOVE";
- case 513: return "WM_LBUTTONDOWN";
- case 514: return "WM_LBUTTONUP";
- case 515: return "WM_LBUTTONDBLCLK";
- case 516: return "WM_RBUTTONDOWN";
- case 517: return "WM_RBUTTONUP";
- case 518: return "WM_RBUTTONDBLCLK";
- case 519: return "WM_MBUTTONDOWN";
- case 520: return "WM_MBUTTONUP";
- case 521: return "WM_MBUTTONDBLCLK";
- case 522: return "WM_MOUSEWHEEL";
- case 523: return "WM_XBUTTONDOWN";
- case 524: return "WM_XBUTTONUP";
- case 525: return "WM_XBUTTONDBLCLK";
- case 528: return "WM_PARENTNOTIFY";
- case 529: return "WM_ENTERMENULOOP";
- case 530: return "WM_EXITMENULOOP";
- case 531: return "WM_NEXTMENU";
- case 532: return "WM_SIZING";
- case 533: return "WM_CAPTURECHANGED";
- case 534: return "WM_MOVING";
- case 536: return "WM_POWERBROADCAST";
- case 537: return "WM_DEVICECHANGE";
- case 544: return "WM_MDICREATE";
- case 545: return "WM_MDIDESTROY";
- case 546: return "WM_MDIACTIVATE";
- case 547: return "WM_MDIRESTORE";
- case 548: return "WM_MDINEXT";
- case 549: return "WM_MDIMAXIMIZE";
- case 550: return "WM_MDITILE";
- case 551: return "WM_MDICASCADE";
- case 552: return "WM_MDIICONARRANGE";
- case 553: return "WM_MDIGETACTIVE";
- case 560: return "WM_MDISETMENU";
- case 561: return "WM_ENTERSIZEMOVE";
- case 562: return "WM_EXITSIZEMOVE";
- case 563: return "WM_DROPFILES";
- case 564: return "WM_MDIREFRESHMENU";
- case 640: return "WM_IME_REPORT";
- case 641: return "WM_IME_SETCONTEXT";
- case 642: return "WM_IME_NOTIFY";
- case 643: return "WM_IME_CONTROL";
- case 644: return "WM_IME_COMPOSITIONFULL";
- case 645: return "WM_IME_SELECT";
- case 646: return "WM_IME_CHAR";
- case 648: return "WM_IME_REQUEST";
- case 656: return "WM_IME_KEYDOWN";
- case 657: return "WM_IME_KEYUP";
- case 672: return "WM_NCMOUSEHOVER";
- case 673: return "WM_MOUSEHOVER";
- case 674: return "WM_NCMOUSELEAVE";
- case 675: return "WM_MOUSELEAVE";
- case 768: return "WM_CUT";
- case 769: return "WM_COPY";
- case 770: return "WM_PASTE";
- case 771: return "WM_CLEAR";
- case 772: return "WM_UNDO";
- case 773: return "WM_RENDERFORMAT";
- case 774: return "WM_RENDERALLFORMATS";
- case 775: return "WM_DESTROYCLIPBOARD";
- case 776: return "WM_DRAWCLIPBOARD";
- case 777: return "WM_PAINTCLIPBOARD";
- case 778: return "WM_VSCROLLCLIPBOARD";
- case 779: return "WM_SIZECLIPBOARD";
- case 780: return "WM_ASKCBFORMATNAME";
- case 781: return "WM_CHANGECBCHAIN";
- case 782: return "WM_HSCROLLCLIPBOARD";
- case 783: return "WM_QUERYNEWPALETTE";
- case 784: return "WM_PALETTEISCHANGING";
- case 785: return "WM_PALETTECHANGED";
- case 786: return "WM_HOTKEY";
- case 791: return "WM_PRINT";
- case 792: return "WM_PRINTCLIENT";
- case 793: return "WM_APPCOMMAND";
- case 856: return "WM_HANDHELDFIRST";
- case 863: return "WM_HANDHELDLAST";
- case 864: return "WM_AFXFIRST";
- case 895: return "WM_AFXLAST";
- case 896: return "WM_PENWINFIRST";
- case 897: return "WM_RCRESULT";
- case 898: return "WM_HOOKRCRESULT";
- case 899: return "WM_GLOBALRCCHANGE / WM_PENMISCINFO";
- case 900: return "WM_SKB";
- case 901: return "WM_HEDITCTL / WM_PENCTL";
- case 902: return "WM_PENMISC";
- case 903: return "WM_CTLINIT";
- case 904: return "WM_PENEVENT";
- case 911: return "WM_PENWINLAST";
- default:
- return "unknown WM_ message";
- }
-
- return "unknown WM_ message";
-}
-#endif
-#endif
-
-
-static unsigned int zOrderCounterFloating = 0;
-/**
- * Private data class of CFloatingDockContainer class (pimpl)
- */
-struct FloatingDockContainerPrivate
-{
- CFloatingDockContainer *_this;
- CDockContainerWidget *DockContainer;
- unsigned int zOrderIndex = ++zOrderCounterFloating;
- QPointer<CDockManager> DockManager;
- eDragState DraggingState = DraggingInactive;
- QPoint DragStartMousePosition;
- CDockContainerWidget *DropContainer = nullptr;
- CDockAreaWidget *SingleDockArea = nullptr;
- QPoint DragStartPos;
- bool Hiding = false;
- bool AutoHideChildren = true;
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
- QWidget* MouseEventHandler = nullptr;
- CFloatingWidgetTitleBar* TitleBar = nullptr;
- bool IsResizing = false;
- bool MousePressed = false;
-#endif
-
- /**
- * Private data constructor
- */
- FloatingDockContainerPrivate(CFloatingDockContainer *_public);
-
- void titleMouseReleaseEvent();
- void updateDropOverlays(const QPoint &GlobalPos);
-
- /**
- * Returns true if the given config flag is set
- */
- static bool testConfigFlag(CDockManager::eConfigFlag Flag)
- {
- return CDockManager::testConfigFlag(Flag);
- }
-
- /**
- * Tests is a certain state is active
- */
- bool isState(eDragState StateId) const
- {
- return StateId == DraggingState;
- }
-
- /**
- * Sets the dragging state and posts a FloatingWidgetDragStartEvent
- * if dragging starts
- */
- void setState(eDragState StateId)
- {
- if (DraggingState == StateId)
- {
- return;
- }
-
- DraggingState = StateId;
- if (DraggingFloatingWidget == DraggingState)
- {
- qApp->postEvent(_this, new QEvent((QEvent::Type)internal::FloatingWidgetDragStartEvent));
- }
- }
-
- void setWindowTitle(const QString &Text)
- {
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
- if (TitleBar)
- {
- TitleBar->setTitle(Text);
- }
-#endif
- _this->setWindowTitle(Text);
- }
-
- /**
- * Reflect the current dock widget title in the floating widget windowTitle()
- * depending on the CDockManager::FloatingContainerHasWidgetTitle flag
- */
- void reflectCurrentWidget(CDockWidget* CurrentWidget)
- {
- // reflect CurrentWidget's title if configured to do so, otherwise display application name as window title
- if (testConfigFlag(CDockManager::FloatingContainerHasWidgetTitle))
- {
- setWindowTitle(CurrentWidget->windowTitle());
- }
- else
- {
- setWindowTitle(floatingContainersTitle());
- }
-
- // reflect CurrentWidget's icon if configured to do so, otherwise display application icon as window icon
- QIcon CurrentWidgetIcon = CurrentWidget->icon();
- if (testConfigFlag(CDockManager::FloatingContainerHasWidgetIcon)
- && !CurrentWidgetIcon.isNull())
- {
- _this->setWindowIcon(CurrentWidget->icon());
- }
- else
- {
- _this->setWindowIcon(QApplication::windowIcon());
- }
- }
-
- /**
- * 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
-
-//============================================================================
-FloatingDockContainerPrivate::FloatingDockContainerPrivate(
- CFloatingDockContainer *_public) :
- _this(_public)
-{
-
-}
-
-//============================================================================
-void FloatingDockContainerPrivate::titleMouseReleaseEvent()
-{
- setState(DraggingInactive);
- if (!DropContainer)
- {
- return;
- }
-
- if (DockManager->dockAreaOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea
- || DockManager->containerOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea)
- {
- CDockOverlay *Overlay = DockManager->containerOverlay();
- if (!Overlay->dropOverlayRect().isValid())
- {
- Overlay = DockManager->dockAreaOverlay();
- }
-
- // 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()))
- {
- // 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());
- }
-
- DockManager->containerOverlay()->hideOverlay();
- DockManager->dockAreaOverlay()->hideOverlay();
-}
-
-
-//============================================================================
-void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos)
-{
- if (!_this->isVisible() || !DockManager)
- {
- return;
- }
-
-#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())
- {
- return;
- }
-#endif
-
- auto Containers = DockManager->dockContainers();
- CDockContainerWidget *TopContainer = nullptr;
- for (auto ContainerWidget : Containers)
- {
- if (!ContainerWidget->isVisible())
- {
- continue;
- }
-
- if (DockContainer == ContainerWidget)
- {
- continue;
- }
-
- QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos);
- if (ContainerWidget->rect().contains(MappedPos))
- {
- if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer))
- {
- TopContainer = ContainerWidget;
- }
- }
- }
-
- DropContainer = TopContainer;
- auto ContainerOverlay = DockManager->containerOverlay();
- auto DockAreaOverlay = DockManager->dockAreaOverlay();
-
- if (!TopContainer)
- {
- ContainerOverlay->hideOverlay();
- DockAreaOverlay->hideOverlay();
- return;
- }
-
- int VisibleDockAreas = TopContainer->visibleDockAreaCount();
- 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);
- if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0)
- {
- DockAreaOverlay->enableDropPreview(true);
- DockAreaOverlay->setAllowedAreas(
- (VisibleDockAreas == 1) ? NoDockWidgetArea : DockArea->allowedAreas());
- DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea);
-
- // A CenterDockWidgetArea for the dockAreaOverlay() indicates that
- // the mouse is in the title bar. If the ContainerArea is valid
- // then we ignore the dock area of the dockAreaOverlay() and disable
- // the drop preview
- if ((Area == CenterDockWidgetArea)
- && (ContainerArea != InvalidDockWidgetArea))
- {
- DockAreaOverlay->enableDropPreview(false);
- ContainerOverlay->enableDropPreview(true);
- }
- else
- {
- ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area);
- }
- }
- else
- {
- DockAreaOverlay->hideOverlay();
- }
-}
-
-
-//============================================================================
-void FloatingDockContainerPrivate::handleEscapeKey()
-{
- ADS_PRINT("FloatingDockContainerPrivate::handleEscapeKey()");
- setState(DraggingInactive);
- DockManager->containerOverlay()->hideOverlay();
- DockManager->dockAreaOverlay()->hideOverlay();
-}
-
-
-//============================================================================
-CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) :
- tFloatingWidgetBase(DockManager),
- d(new FloatingDockContainerPrivate(this))
-{
- d->DockManager = DockManager;
- d->DockContainer = new CDockContainerWidget(DockManager, this);
- connect(d->DockContainer, SIGNAL(dockAreasAdded()), this,
- SLOT(onDockAreasAddedOrRemoved()));
- connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this,
- SLOT(onDockAreasAddedOrRemoved()));
-
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
- QDockWidget::setWidget(d->DockContainer);
- QDockWidget::setFeatures(QDockWidget::DockWidgetClosable
- | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
-
- bool native_window = true;
-
- // FloatingContainerForce*TitleBar is overwritten by the "ADS_UseNativeTitle" environment variable if set.
- auto env = qgetenv("ADS_UseNativeTitle").toUpper();
- if (env == "1")
- {
- native_window = true;
- }
- else if (env == "0")
- {
- native_window = false;
- }
- else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceNativeTitleBar))
- {
- native_window = true;
- }
- else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceQWidgetTitleBar))
- {
- native_window = false;
- }
- else
- {
- // KDE doesn't seem to fire MoveEvents while moving windows, so for now no native titlebar for everything using KWin.
- QString window_manager = internal::windowManager().toUpper().split(" ")[0];
- 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());
- setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
- }
- else
- {
- d->TitleBar = new CFloatingWidgetTitleBar(this);
- setTitleBarWidget(d->TitleBar);
- setWindowFlags(Qt::Window | Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint);
- d->TitleBar->enableCloseButton(isClosable());
- connect(d->TitleBar, SIGNAL(closeRequested()), SLOT(close()));
- connect(d->TitleBar, &CFloatingWidgetTitleBar::maximizeRequested,
- this, &CFloatingDockContainer::onMaximizeRequest);
- }
-#else
- setWindowFlags(
- Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
- QBoxLayout *l = new QBoxLayout(QBoxLayout::TopToBottom);
- l->setContentsMargins(0, 0, 0, 0);
- l->setSpacing(0);
- setLayout(l);
- l->addWidget(d->DockContainer);
-#endif
-
- DockManager->registerFloatingWidget(this);
-}
-
-//============================================================================
-CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget *DockArea) :
- CFloatingDockContainer(DockArea->dockManager())
-{
- d->DockContainer->addDockArea(DockArea);
-
- auto TopLevelDockWidget = topLevelDockWidget();
- if (TopLevelDockWidget)
- {
- TopLevelDockWidget->emitTopLevelChanged(true);
- }
-
- d->DockManager->notifyWidgetOrAreaRelocation(DockArea);
-}
-
-//============================================================================
-CFloatingDockContainer::CFloatingDockContainer(CDockWidget *DockWidget) :
- CFloatingDockContainer(DockWidget->dockManager())
-{
- d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget);
- auto TopLevelDockWidget = topLevelDockWidget();
- if (TopLevelDockWidget)
- {
- TopLevelDockWidget->emitTopLevelChanged(true);
- }
-
- d->DockManager->notifyWidgetOrAreaRelocation(DockWidget);
-}
-
-
-//============================================================================
-CFloatingDockContainer::~CFloatingDockContainer()
-{
- ADS_PRINT("~CFloatingDockContainer");
- if (d->DockManager)
- {
- d->DockManager->removeFloatingWidget(this);
- }
- delete d;
-}
-
-
-//============================================================================
-void CFloatingDockContainer::deleteContent()
-{
- std::vector<QPointer<ads::CDockAreaWidget>> areas;
- for (int i = 0; i != dockContainer()->dockAreaCount(); ++i)
- {
- areas.push_back( dockContainer()->dockArea(i) );
- }
- for (auto area : areas)
- {
- if (!area)
- {
- continue;
- }
-
- // QPointer delete safety - just in case some dock widget in destruction
- // deletes another related/twin or child dock widget.
- std::vector<QPointer<QWidget>> deleteWidgets;
- for (auto widget : area->dockWidgets())
- {
- deleteWidgets.push_back(widget);
- }
- for (auto ptrWdg : deleteWidgets)
- {
- delete ptrWdg;
- }
- }
-}
-
-//============================================================================
-CDockContainerWidget* CFloatingDockContainer::dockContainer() const
-{
- return d->DockContainer;
-}
-
-//============================================================================
-void CFloatingDockContainer::changeEvent(QEvent *event)
-{
- Super::changeEvent(event);
- switch (event->type())
- {
- case QEvent::ActivationChange:
- if (isActiveWindow())
- {
- ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange ");
- d->zOrderIndex = ++zOrderCounterFloating;
-
-#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
- }
-}
-
-
-#ifdef Q_OS_WIN
-#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
-bool CFloatingDockContainer::nativeEvent(const QByteArray &eventType, void *message, long *result)
-#else
-bool CFloatingDockContainer::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
-#endif
-{
- QWidget::nativeEvent(eventType, message, result);
- MSG *msg = static_cast<MSG*>(message);
- switch (msg->message)
- {
- case WM_MOVING:
- {
- if (d->isState(DraggingFloatingWidget))
- {
- d->updateDropOverlays(QCursor::pos());
- }
- }
- break;
-
- case WM_NCLBUTTONDOWN:
- if (msg->wParam == HTCAPTION && d->isState(DraggingInactive))
- {
- ADS_PRINT("CFloatingDockContainer::nativeEvent WM_NCLBUTTONDOWN");
- d->DragStartPos = pos();
- d->setState(DraggingMousePressed);
- }
- break;
-
- case WM_NCLBUTTONDBLCLK:
- d->setState(DraggingInactive);
- break;
-
- case WM_ENTERSIZEMOVE:
- if (d->isState(DraggingMousePressed))
- {
- ADS_PRINT("CFloatingDockContainer::nativeEvent WM_ENTERSIZEMOVE");
- d->setState(DraggingFloatingWidget);
- d->updateDropOverlays(QCursor::pos());
- }
- break;
-
- case WM_EXITSIZEMOVE:
- if (d->isState(DraggingFloatingWidget))
- {
- ADS_PRINT("CFloatingDockContainer::nativeEvent WM_EXITSIZEMOVE");
- if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)
- {
- d->handleEscapeKey();
- }
- else
- {
- d->titleMouseReleaseEvent();
- }
- }
- break;
- }
- return false;
-}
-#endif
-
-
-//============================================================================
-void CFloatingDockContainer::closeEvent(QCloseEvent *event)
-{
- ADS_PRINT("CFloatingDockContainer closeEvent");
- d->setState(DraggingInactive);
- event->ignore();
- if (!isClosable())
- {
- return;
- }
-
- bool HasOpenDockWidgets = false;
- for (auto DockWidget : d->DockContainer->openedDockWidgets())
- {
- if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) || DockWidget->features().testFlag(CDockWidget::CustomCloseHandling))
- {
- bool Closed = DockWidget->closeDockWidgetInternal();
- if (!Closed)
- {
- HasOpenDockWidgets = true;
- }
- }
- else
- {
- DockWidget->toggleView(false);
- }
- }
-
- if (HasOpenDockWidgets)
- {
- return;
- }
-
- // In Qt version after 5.9.2 there seems to be a bug that causes the
- // QWidget::event() function to not receive any NonClientArea mouse
- // events anymore after a close/show cycle. The bug is reported here:
- // https://bugreports.qt.io/browse/QTBUG-73295
- // The following code is a workaround for Qt versions > 5.9.2 that seems
- // to work
- // Starting from Qt version 5.12.2 this seems to work again. But
- // now the QEvent::NonClientAreaMouseButtonPress function returns always
- // Qt::RightButton even if the left button was pressed
- this->hide();
-}
-
-//============================================================================
-void CFloatingDockContainer::hideEvent(QHideEvent *event)
-{
- Super::hideEvent(event);
- if (event->spontaneous())
- {
- return;
- }
-
- // Prevent toogleView() events during restore state
- if (d->DockManager->isRestoringState())
- {
- return;
- }
-
- if ( d->AutoHideChildren )
- {
- d->Hiding = true;
- for ( auto DockArea : d->DockContainer->openedDockAreas() )
- {
- for ( auto DockWidget : DockArea->openedDockWidgets() )
- {
- DockWidget->toggleView( false );
- }
- }
- d->Hiding = false;
- }
-}
-
-
-//============================================================================
-void CFloatingDockContainer::showEvent(QShowEvent *event)
-{
- Super::showEvent(event);
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
- if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
- {
- this->window()->activateWindow();
- }
-#endif
-}
-
-
-//============================================================================
-void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos,
- const QSize &Size, eDragState DragState, QWidget *MouseEventHandler)
-{
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
- if (!isMaximized())
- {
- resize(Size);
- d->DragStartMousePosition = DragStartMousePos;
- }
- d->setState(DragState);
- if (DraggingFloatingWidget == DragState)
- {
- d->MouseEventHandler = MouseEventHandler;
- if (d->MouseEventHandler)
- {
- d->MouseEventHandler->grabMouse();
- }
- }
-
- if (!isMaximized())
- {
- moveFloating();
- }
- show();
-#else
- Q_UNUSED(MouseEventHandler)
- resize(Size);
- d->DragStartMousePosition = DragStartMousePos;
- d->setState(DragState);
- moveFloating();
- show();
-#endif
-}
-
-//============================================================================
-void CFloatingDockContainer::moveFloating()
-{
- int BorderSize = (frameSize().width() - size().width()) / 2;
- const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition
- - QPoint(BorderSize, 0);
- move(moveToPos);
- switch (d->DraggingState)
- {
- case DraggingMousePressed:
- d->setState(DraggingFloatingWidget);
- d->updateDropOverlays(QCursor::pos());
- break;
-
- case DraggingFloatingWidget:
- d->updateDropOverlays(QCursor::pos());
-#ifdef Q_OS_MACOS
- // In OSX when hiding the DockAreaOverlay the application would set
- // 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.
- activateWindow();
-#endif
- break;
- default:
- break;
- }
-}
-
-//============================================================================
-bool CFloatingDockContainer::isClosable() const
-{
- return d->DockContainer->features().testFlag(
- CDockWidget::DockWidgetClosable);
-}
-
-//============================================================================
-void CFloatingDockContainer::onDockAreasAddedOrRemoved()
-{
- ADS_PRINT("CFloatingDockContainer::onDockAreasAddedOrRemoved()");
- auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
- if (TopLevelDockArea)
- {
- d->SingleDockArea = TopLevelDockArea;
- CDockWidget* CurrentWidget = d->SingleDockArea->currentDockWidget();
- d->reflectCurrentWidget(CurrentWidget);
- connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
- SLOT(onDockAreaCurrentChanged(int)));
- }
- else
- {
- if (d->SingleDockArea)
- {
- disconnect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
- SLOT(onDockAreaCurrentChanged(int)));
- d->SingleDockArea = nullptr;
- }
- d->setWindowTitle(d->floatingContainersTitle());
- setWindowIcon(QApplication::windowIcon());
- }
-}
-
-//============================================================================
-void CFloatingDockContainer::updateWindowTitle()
-{
- // If this floating container will be hidden, then updating the window
- // tile is not required anymore
- if (d->Hiding)
- {
- return;
- }
-
-
- auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
- if (TopLevelDockArea)
- {
- CDockWidget* CurrentWidget = TopLevelDockArea->currentDockWidget();
- if (CurrentWidget)
- {
- d->reflectCurrentWidget(CurrentWidget);
- }
- }
- else
- {
- d->setWindowTitle(d->floatingContainersTitle());
- setWindowIcon(QApplication::windowIcon());
- }
-}
-
-//============================================================================
-void CFloatingDockContainer::onDockAreaCurrentChanged(int Index)
-{
- Q_UNUSED(Index);
- CDockWidget* CurrentWidget = d->SingleDockArea->currentDockWidget();
- d->reflectCurrentWidget(CurrentWidget);
-}
-
-//============================================================================
-bool CFloatingDockContainer::restoreState(CDockingStateReader &Stream,
- bool Testing)
-{
- if (!d->DockContainer->restoreState(Stream, Testing))
- {
- return false;
- }
- onDockAreasAddedOrRemoved();
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
- if(d->TitleBar)
- {
- d->TitleBar->setMaximizedIcon(windowState() == Qt::WindowMaximized);
- }
-#endif
- return true;
-}
-
-
-//============================================================================
-bool CFloatingDockContainer::hasTopLevelDockWidget() const
-{
- return d->DockContainer->hasTopLevelDockWidget();
-}
-
-//============================================================================
-CDockWidget* CFloatingDockContainer::topLevelDockWidget() const
-{
- return d->DockContainer->topLevelDockWidget();
-}
-
-//============================================================================
-QList<CDockWidget*> CFloatingDockContainer::dockWidgets() const
-{
- return d->DockContainer->dockWidgets();
-}
-
-//============================================================================
-void CFloatingDockContainer::finishDropOperation()
-{
- // Widget has been redocked, so it must be hidden right way (see
- // https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/351)
- // but AutoHideChildren must be set to false because "this" still contains
- // dock widgets that shall not be toggled hidden.
- d->AutoHideChildren = false;
- hide();
- // The floating widget will be deleted now. Ensure, that the destructor
- // of the floating widget does not delete any dock areas that have been
- // moved to a new container - simply remove all dock areas before deleting
- // the floating widget
- d->DockContainer->removeAllDockAreas();
- deleteLater();
- if (d->DockManager)
- {
- d->DockManager->removeFloatingWidget(this);
- d->DockManager->removeDockContainer(this->dockContainer());
- }
-}
-
-//============================================================================
-void CFloatingDockContainer::finishDragging()
-{
- ADS_PRINT("CFloatingDockContainer::finishDragging");
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
- setWindowOpacity(1);
- activateWindow();
- if (d->MouseEventHandler)
- {
- d->MouseEventHandler->releaseMouse();
- d->MouseEventHandler = nullptr;
- }
-#endif
- d->titleMouseReleaseEvent();
-}
-
-#ifdef Q_OS_MACOS
-//============================================================================
-bool CFloatingDockContainer::event(QEvent *e)
-{
- switch (d->DraggingState)
- {
- case DraggingInactive:
- {
- // Normally we would check here, if the left mouse button is pressed.
- // But from QT version 5.12.2 on the mouse events from
- // QEvent::NonClientAreaMouseButtonPress return the wrong mouse button
- // The event always returns Qt::RightButton even if the left button
- // is clicked.
- // It is really great to work around the whole NonClientMouseArea
- // bugs
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 2))
- if (e->type() == QEvent::NonClientAreaMouseButtonPress /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/)
-#else
- if (e->type() == QEvent::NonClientAreaMouseButtonPress && QGuiApplication::mouseButtons().testFlag(Qt::LeftButton))
-#endif
- {
- ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type());
- d->DragStartPos = pos();
- d->setState(DraggingMousePressed);
- }
- }
- break;
-
- case DraggingMousePressed:
- switch (e->type())
- {
- case QEvent::NonClientAreaMouseButtonDblClick:
- ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick");
- d->setState(DraggingInactive);
- break;
-
- case QEvent::Resize:
- // If the first event after the mouse press is a resize event, then
- // the user resizes the window instead of dragging it around.
- // But there is one exception. If the window is maximized,
- // then dragging the window via title bar will cause the widget to
- // leave the maximized state. This in turn will trigger a resize event.
- // To know, if the resize event was triggered by user via moving a
- // corner of the window frame or if it was caused by a windows state
- // change, we check, if we are not in maximized state.
- if (!isMaximized())
- {
- d->setState(DraggingInactive);
- }
- break;
-
- default:
- break;
- }
- break;
-
- case DraggingFloatingWidget:
- if (e->type() == QEvent::NonClientAreaMouseButtonRelease)
- {
- ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease");
- d->titleMouseReleaseEvent();
- }
- break;
-
- default:
- break;
- }
-
-#if (ADS_DEBUG_LEVEL > 0)
- qDebug() << QTime::currentTime() << "CFloatingDockContainer::event " << e->type();
-#endif
- return QWidget::event(e);
-}
-
-
-//============================================================================
-void CFloatingDockContainer::moveEvent(QMoveEvent *event)
-{
- QWidget::moveEvent(event);
- switch (d->DraggingState)
- {
- case DraggingMousePressed:
- d->setState(DraggingFloatingWidget);
- d->updateDropOverlays(QCursor::pos());
- break;
-
- case DraggingFloatingWidget:
- d->updateDropOverlays(QCursor::pos());
- // In OSX when hiding the DockAreaOverlay the application would set
- // 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.
- activateWindow();
- break;
- default:
- break;
- }
-
-
-}
-#endif
-
-
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
-//============================================================================
-void CFloatingDockContainer::onMaximizeRequest()
-{
- if (windowState() == Qt::WindowMaximized)
- {
- showNormal();
- }
- else
- {
- showMaximized();
- }
-}
-
-
-//============================================================================
-void CFloatingDockContainer::showNormal(bool fixGeometry)
-{
- if (windowState() == Qt::WindowMaximized)
- {
- QRect oldNormal = normalGeometry();
- Super::showNormal();
- if(fixGeometry)
- {
- setGeometry(oldNormal);
- }
- }
- if(d->TitleBar)
- {
- d->TitleBar->setMaximizedIcon(false);
- }
-}
-
-
-//============================================================================
-void CFloatingDockContainer::showMaximized()
-{
- Super::showMaximized();
- if (d->TitleBar)
- {
- d->TitleBar->setMaximizedIcon(true);
- }
-}
-
-
-//============================================================================
-bool CFloatingDockContainer::isMaximized() const
-{
- return windowState() == Qt::WindowMaximized;
-}
-
-
-//============================================================================
-void CFloatingDockContainer::show()
-{
- // Prevent this window from showing in the taskbar and pager (alt+tab)
- internal::xcb_add_prop(true, winId(), "_NET_WM_STATE", "_NET_WM_STATE_SKIP_TASKBAR");
- internal::xcb_add_prop(true, winId(), "_NET_WM_STATE", "_NET_WM_STATE_SKIP_PAGER");
- Super::show();
-}
-
-
-//============================================================================
-void CFloatingDockContainer::resizeEvent(QResizeEvent *event)
-{
- d->IsResizing = true;
- Super::resizeEvent(event);
-}
-
-
-//============================================================================
-void CFloatingDockContainer::moveEvent(QMoveEvent *event)
-{
- Super::moveEvent(event);
- if (!d->IsResizing && event->spontaneous() && d->MousePressed)
- {
- d->setState(DraggingFloatingWidget);
- d->updateDropOverlays(QCursor::pos());
- }
- d->IsResizing = false;
-}
-
-
-//============================================================================
-bool CFloatingDockContainer::event(QEvent *e)
-{
- bool result = Super::event(e);
- switch (e->type())
- {
- case QEvent::WindowActivate:
- d->MousePressed = false;
- break;
- case QEvent::WindowDeactivate:
- d->MousePressed = true;
- break;
- default:
- break;
- }
- return result;
-}
-
-//============================================================================
-bool CFloatingDockContainer::hasNativeTitleBar()
-{
- return d->TitleBar == nullptr;
-}
-#endif
-
-} // namespace ads
-
-//---------------------------------------------------------------------------
-// EOF FloatingDockContainer.cpp
+/*******************************************************************************
+ ** Qt Advanced Docking System
+ ** Copyright (C) 2017 Uwe Kindler
+ **
+ ** This library is free software; you can redistribute it and/or
+ ** modify it under the terms of the GNU Lesser General Public
+ ** License as published by the Free Software Foundation; either
+ ** version 2.1 of the License, or (at your option) any later version.
+ **
+ ** This library is distributed in the hope that it will be useful,
+ ** but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ ** Lesser General Public License for more details.
+ **
+ ** You should have received a copy of the GNU Lesser General Public
+ ** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+
+//============================================================================
+/// \file FloatingDockContainer.cpp
+/// \author Uwe Kindler
+/// \date 01.03.2017
+/// \brief Implementation of CFloatingDockContainer class
+//============================================================================
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include "FloatingDockContainer.h"
+
+#include <iostream>
+
+#include <QBoxLayout>
+#include <QApplication>
+#include <QMouseEvent>
+#include <QPointer>
+#include <QAction>
+#include <QDebug>
+#include <QAbstractButton>
+#include <QElapsedTimer>
+#include <QTime>
+#include <QDrag>
+#include <QMimeData>
+#include <QDataStream>
+#include <QWindow>
+
+#include "DockContainerWidget.h"
+#include "DockAreaWidget.h"
+#include "DockManager.h"
+#include "DockWidget.h"
+#include "DockOverlay.h"
+#include "FloatingDragPreview.h"
+
+#ifdef Q_OS_WIN
+#include <windows.h>
+#ifdef _MSC_VER
+#pragma comment(lib, "User32.lib")
+#endif
+#endif
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+#include "linux/FloatingWidgetTitleBar.h"
+#include <xcb/xcb.h>
+#endif
+
+namespace ads
+{
+#ifdef Q_OS_WIN
+#if 0 // set to 1 if you need this function for debugging
+/**
+ * Just for debugging to convert windows message identifiers to strings
+ */
+static const char* windowsMessageString(int MessageId)
+{
+ switch (MessageId)
+ {
+ case 0: return "WM_NULL";
+ case 1: return "WM_CREATE";
+ case 2: return "WM_DESTROY";
+ case 3: return "WM_MOVE";
+ case 5: return "WM_SIZE";
+ case 6: return "WM_ACTIVATE";
+ case 7: return "WM_SETFOCUS";
+ case 8: return "WM_KILLFOCUS";
+ case 10: return "WM_ENABLE";
+ case 11: return "WM_SETREDRAW";
+ case 12: return "WM_SETTEXT";
+ case 13: return "WM_GETTEXT";
+ case 14: return "WM_GETTEXTLENGTH";
+ case 15: return "WM_PAINT";
+ case 16: return "WM_CLOSE";
+ case 17: return "WM_QUERYENDSESSION";
+ case 18: return "WM_QUIT";
+ case 19: return "WM_QUERYOPEN";
+ case 20: return "WM_ERASEBKGND";
+ case 21: return "WM_SYSCOLORCHANGE";
+ case 22: return "WM_ENDSESSION";
+ case 24: return "WM_SHOWWINDOW";
+ case 25: return "WM_CTLCOLOR";
+ case 26: return "WM_WININICHANGE";
+ case 27: return "WM_DEVMODECHANGE";
+ case 28: return "WM_ACTIVATEAPP";
+ case 29: return "WM_FONTCHANGE";
+ case 30: return "WM_TIMECHANGE";
+ case 31: return "WM_CANCELMODE";
+ case 32: return "WM_SETCURSOR";
+ case 33: return "WM_MOUSEACTIVATE";
+ case 34: return "WM_CHILDACTIVATE";
+ case 35: return "WM_QUEUESYNC";
+ case 36: return "WM_GETMINMAXINFO";
+ case 38: return "WM_PAINTICON";
+ case 39: return "WM_ICONERASEBKGND";
+ case 40: return "WM_NEXTDLGCTL";
+ case 42: return "WM_SPOOLERSTATUS";
+ case 43: return "WM_DRAWITEM";
+ case 44: return "WM_MEASUREITEM";
+ case 45: return "WM_DELETEITEM";
+ case 46: return "WM_VKEYTOITEM";
+ case 47: return "WM_CHARTOITEM";
+ case 48: return "WM_SETFONT";
+ case 49: return "WM_GETFONT";
+ case 50: return "WM_SETHOTKEY";
+ case 51: return "WM_GETHOTKEY";
+ case 55: return "WM_QUERYDRAGICON";
+ case 57: return "WM_COMPAREITEM";
+ case 61: return "WM_GETOBJECT";
+ case 65: return "WM_COMPACTING";
+ case 68: return "WM_COMMNOTIFY";
+ case 70: return "WM_WINDOWPOSCHANGING";
+ case 71: return "WM_WINDOWPOSCHANGED";
+ case 72: return "WM_POWER";
+ case 73: return "WM_COPYGLOBALDATA";
+ case 74: return "WM_COPYDATA";
+ case 75: return "WM_CANCELJOURNAL";
+ case 78: return "WM_NOTIFY";
+ case 80: return "WM_INPUTLANGCHANGEREQUEST";
+ case 81: return "WM_INPUTLANGCHANGE";
+ case 82: return "WM_TCARD";
+ case 83: return "WM_HELP";
+ case 84: return "WM_USERCHANGED";
+ case 85: return "WM_NOTIFYFORMAT";
+ case 123: return "WM_CONTEXTMENU";
+ case 124: return "WM_STYLECHANGING";
+ case 125: return "WM_STYLECHANGED";
+ case 126: return "WM_DISPLAYCHANGE";
+ case 127: return "WM_GETICON";
+ case 128: return "WM_SETICON";
+ case 129: return "WM_NCCREATE";
+ case 130: return "WM_NCDESTROY";
+ case 131: return "WM_NCCALCSIZE";
+ case 132: return "WM_NCHITTEST";
+ case 133: return "WM_NCPAINT";
+ case 134: return "WM_NCACTIVATE";
+ case 135: return "WM_GETDLGCODE";
+ case 136: return "WM_SYNCPAINT";
+ case 160: return "WM_NCMOUSEMOVE";
+ case 161: return "WM_NCLBUTTONDOWN";
+ case 162: return "WM_NCLBUTTONUP";
+ case 163: return "WM_NCLBUTTONDBLCLK";
+ case 164: return "WM_NCRBUTTONDOWN";
+ case 165: return "WM_NCRBUTTONUP";
+ case 166: return "WM_NCRBUTTONDBLCLK";
+ case 167: return "WM_NCMBUTTONDOWN";
+ case 168: return "WM_NCMBUTTONUP";
+ case 169: return "WM_NCMBUTTONDBLCLK";
+ case 171: return "WM_NCXBUTTONDOWN";
+ case 172: return "WM_NCXBUTTONUP";
+ case 173: return "WM_NCXBUTTONDBLCLK";
+ case 176: return "EM_GETSEL";
+ case 177: return "EM_SETSEL";
+ case 178: return "EM_GETRECT";
+ case 179: return "EM_SETRECT";
+ case 180: return "EM_SETRECTNP";
+ case 181: return "EM_SCROLL";
+ case 182: return "EM_LINESCROLL";
+ case 183: return "EM_SCROLLCARET";
+ case 185: return "EM_GETMODIFY";
+ case 187: return "EM_SETMODIFY";
+ case 188: return "EM_GETLINECOUNT";
+ case 189: return "EM_LINEINDEX";
+ case 190: return "EM_SETHANDLE";
+ case 191: return "EM_GETHANDLE";
+ case 192: return "EM_GETTHUMB";
+ case 193: return "EM_LINELENGTH";
+ case 194: return "EM_REPLACESEL";
+ case 195: return "EM_SETFONT";
+ case 196: return "EM_GETLINE";
+ case 197: return "EM_LIMITTEXT / EM_SETLIMITTEXT";
+ case 198: return "EM_CANUNDO";
+ case 199: return "EM_UNDO";
+ case 200: return "EM_FMTLINES";
+ case 201: return "EM_LINEFROMCHAR";
+ case 202: return "EM_SETWORDBREAK";
+ case 203: return "EM_SETTABSTOPS";
+ case 204: return "EM_SETPASSWORDCHAR";
+ case 205: return "EM_EMPTYUNDOBUFFER";
+ case 206: return "EM_GETFIRSTVISIBLELINE";
+ case 207: return "EM_SETREADONLY";
+ case 209: return "EM_SETWORDBREAKPROC / EM_GETWORDBREAKPROC";
+ case 210: return "EM_GETPASSWORDCHAR";
+ case 211: return "EM_SETMARGINS";
+ case 212: return "EM_GETMARGINS";
+ case 213: return "EM_GETLIMITTEXT";
+ case 214: return "EM_POSFROMCHAR";
+ case 215: return "EM_CHARFROMPOS";
+ case 216: return "EM_SETIMESTATUS";
+ case 217: return "EM_GETIMESTATUS";
+ case 224: return "SBM_SETPOS";
+ case 225: return "SBM_GETPOS";
+ case 226: return "SBM_SETRANGE";
+ case 227: return "SBM_GETRANGE";
+ case 228: return "SBM_ENABLE_ARROWS";
+ case 230: return "SBM_SETRANGEREDRAW";
+ case 233: return "SBM_SETSCROLLINFO";
+ case 234: return "SBM_GETSCROLLINFO";
+ case 235: return "SBM_GETSCROLLBARINFO";
+ case 240: return "BM_GETCHECK";
+ case 241: return "BM_SETCHECK";
+ case 242: return "BM_GETSTATE";
+ case 243: return "BM_SETSTATE";
+ case 244: return "BM_SETSTYLE";
+ case 245: return "BM_CLICK";
+ case 246: return "BM_GETIMAGE";
+ case 247: return "BM_SETIMAGE";
+ case 248: return "BM_SETDONTCLICK";
+ case 255: return "WM_INPUT";
+ case 256: return "WM_KEYDOWN";
+ case 257: return "WM_KEYUP";
+ case 258: return "WM_CHAR";
+ case 259: return "WM_DEADCHAR";
+ case 260: return "WM_SYSKEYDOWN";
+ case 261: return "WM_SYSKEYUP";
+ case 262: return "WM_SYSCHAR";
+ case 263: return "WM_SYSDEADCHAR";
+ case 265: return "WM_UNICHAR / WM_WNT_CONVERTREQUESTEX";
+ case 266: return "WM_CONVERTREQUEST";
+ case 267: return "WM_CONVERTRESULT";
+ case 268: return "WM_INTERIM";
+ case 269: return "WM_IME_STARTCOMPOSITION";
+ case 270: return "WM_IME_ENDCOMPOSITION";
+ case 272: return "WM_INITDIALOG";
+ case 273: return "WM_COMMAND";
+ case 274: return "WM_SYSCOMMAND";
+ case 275: return "WM_TIMER";
+ case 276: return "WM_HSCROLL";
+ case 277: return "WM_VSCROLL";
+ case 278: return "WM_INITMENU";
+ case 279: return "WM_INITMENUPOPUP";
+ case 280: return "WM_SYSTIMER";
+ case 287: return "WM_MENUSELECT";
+ case 288: return "WM_MENUCHAR";
+ case 289: return "WM_ENTERIDLE";
+ case 290: return "WM_MENURBUTTONUP";
+ case 291: return "WM_MENUDRAG";
+ case 292: return "WM_MENUGETOBJECT";
+ case 293: return "WM_UNINITMENUPOPUP";
+ case 294: return "WM_MENUCOMMAND";
+ case 295: return "WM_CHANGEUISTATE";
+ case 296: return "WM_UPDATEUISTATE";
+ case 297: return "WM_QUERYUISTATE";
+ case 306: return "WM_CTLCOLORMSGBOX";
+ case 307: return "WM_CTLCOLOREDIT";
+ case 308: return "WM_CTLCOLORLISTBOX";
+ case 309: return "WM_CTLCOLORBTN";
+ case 310: return "WM_CTLCOLORDLG";
+ case 311: return "WM_CTLCOLORSCROLLBAR";
+ case 312: return "WM_CTLCOLORSTATIC";
+ case 512: return "WM_MOUSEMOVE";
+ case 513: return "WM_LBUTTONDOWN";
+ case 514: return "WM_LBUTTONUP";
+ case 515: return "WM_LBUTTONDBLCLK";
+ case 516: return "WM_RBUTTONDOWN";
+ case 517: return "WM_RBUTTONUP";
+ case 518: return "WM_RBUTTONDBLCLK";
+ case 519: return "WM_MBUTTONDOWN";
+ case 520: return "WM_MBUTTONUP";
+ case 521: return "WM_MBUTTONDBLCLK";
+ case 522: return "WM_MOUSEWHEEL";
+ case 523: return "WM_XBUTTONDOWN";
+ case 524: return "WM_XBUTTONUP";
+ case 525: return "WM_XBUTTONDBLCLK";
+ case 528: return "WM_PARENTNOTIFY";
+ case 529: return "WM_ENTERMENULOOP";
+ case 530: return "WM_EXITMENULOOP";
+ case 531: return "WM_NEXTMENU";
+ case 532: return "WM_SIZING";
+ case 533: return "WM_CAPTURECHANGED";
+ case 534: return "WM_MOVING";
+ case 536: return "WM_POWERBROADCAST";
+ case 537: return "WM_DEVICECHANGE";
+ case 544: return "WM_MDICREATE";
+ case 545: return "WM_MDIDESTROY";
+ case 546: return "WM_MDIACTIVATE";
+ case 547: return "WM_MDIRESTORE";
+ case 548: return "WM_MDINEXT";
+ case 549: return "WM_MDIMAXIMIZE";
+ case 550: return "WM_MDITILE";
+ case 551: return "WM_MDICASCADE";
+ case 552: return "WM_MDIICONARRANGE";
+ case 553: return "WM_MDIGETACTIVE";
+ case 560: return "WM_MDISETMENU";
+ case 561: return "WM_ENTERSIZEMOVE";
+ case 562: return "WM_EXITSIZEMOVE";
+ case 563: return "WM_DROPFILES";
+ case 564: return "WM_MDIREFRESHMENU";
+ case 640: return "WM_IME_REPORT";
+ case 641: return "WM_IME_SETCONTEXT";
+ case 642: return "WM_IME_NOTIFY";
+ case 643: return "WM_IME_CONTROL";
+ case 644: return "WM_IME_COMPOSITIONFULL";
+ case 645: return "WM_IME_SELECT";
+ case 646: return "WM_IME_CHAR";
+ case 648: return "WM_IME_REQUEST";
+ case 656: return "WM_IME_KEYDOWN";
+ case 657: return "WM_IME_KEYUP";
+ case 672: return "WM_NCMOUSEHOVER";
+ case 673: return "WM_MOUSEHOVER";
+ case 674: return "WM_NCMOUSELEAVE";
+ case 675: return "WM_MOUSELEAVE";
+ case 768: return "WM_CUT";
+ case 769: return "WM_COPY";
+ case 770: return "WM_PASTE";
+ case 771: return "WM_CLEAR";
+ case 772: return "WM_UNDO";
+ case 773: return "WM_RENDERFORMAT";
+ case 774: return "WM_RENDERALLFORMATS";
+ case 775: return "WM_DESTROYCLIPBOARD";
+ case 776: return "WM_DRAWCLIPBOARD";
+ case 777: return "WM_PAINTCLIPBOARD";
+ case 778: return "WM_VSCROLLCLIPBOARD";
+ case 779: return "WM_SIZECLIPBOARD";
+ case 780: return "WM_ASKCBFORMATNAME";
+ case 781: return "WM_CHANGECBCHAIN";
+ case 782: return "WM_HSCROLLCLIPBOARD";
+ case 783: return "WM_QUERYNEWPALETTE";
+ case 784: return "WM_PALETTEISCHANGING";
+ case 785: return "WM_PALETTECHANGED";
+ case 786: return "WM_HOTKEY";
+ case 791: return "WM_PRINT";
+ case 792: return "WM_PRINTCLIENT";
+ case 793: return "WM_APPCOMMAND";
+ case 856: return "WM_HANDHELDFIRST";
+ case 863: return "WM_HANDHELDLAST";
+ case 864: return "WM_AFXFIRST";
+ case 895: return "WM_AFXLAST";
+ case 896: return "WM_PENWINFIRST";
+ case 897: return "WM_RCRESULT";
+ case 898: return "WM_HOOKRCRESULT";
+ case 899: return "WM_GLOBALRCCHANGE / WM_PENMISCINFO";
+ case 900: return "WM_SKB";
+ case 901: return "WM_HEDITCTL / WM_PENCTL";
+ case 902: return "WM_PENMISC";
+ case 903: return "WM_CTLINIT";
+ case 904: return "WM_PENEVENT";
+ case 911: return "WM_PENWINLAST";
+ default:
+ return "unknown WM_ message";
+ }
+
+ return "unknown WM_ message";
+}
+#endif
+#endif
+
+
+static unsigned int zOrderCounterFloating = 0;
+/**
+ * Private data class of CFloatingDockContainer class (pimpl)
+ */
+struct FloatingDockContainerPrivate
+{
+ CFloatingDockContainer *_this;
+ CDockContainerWidget *DockContainer;
+ unsigned int zOrderIndex = ++zOrderCounterFloating;
+ QPointer<CDockManager> DockManager;
+ eDragState DraggingState = DraggingInactive;
+ QPoint DragStartMousePosition;
+ CDockContainerWidget *DropContainer = nullptr;
+ CDockAreaWidget *SingleDockArea = nullptr;
+ QPoint DragStartPos;
+ bool Hiding = false;
+ bool AutoHideChildren = true;
+ bool HideContentOnNextHide = false;
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ QWidget* MouseEventHandler = nullptr;
+ CFloatingWidgetTitleBar* TitleBar = nullptr;
+ bool IsResizing = false;
+ bool MousePressed = false;
+#endif
+
+ /**
+ * Private data constructor
+ */
+ FloatingDockContainerPrivate(CFloatingDockContainer *_public);
+
+ void titleMouseReleaseEvent();
+ void updateDropOverlays(const QPoint &GlobalPos);
+
+ /**
+ * Returns true if the given config flag is set
+ */
+ static bool testConfigFlag(CDockManager::eConfigFlag Flag)
+ {
+ return CDockManager::testConfigFlag(Flag);
+ }
+
+ /**
+ * Tests is a certain state is active
+ */
+ bool isState(eDragState StateId) const
+ {
+ return StateId == DraggingState;
+ }
+
+ /**
+ * Sets the dragging state and posts a FloatingWidgetDragStartEvent
+ * if dragging starts
+ */
+ void setState(eDragState StateId)
+ {
+ if (DraggingState == StateId)
+ {
+ return;
+ }
+
+ DraggingState = StateId;
+ if (DraggingFloatingWidget == DraggingState)
+ {
+ qApp->postEvent(_this, new QEvent((QEvent::Type)internal::FloatingWidgetDragStartEvent));
+ }
+ }
+
+ void setWindowTitle(const QString &Text)
+ {
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ if (TitleBar)
+ {
+ TitleBar->setTitle(Text);
+ }
+#endif
+ _this->setWindowTitle(Text);
+ }
+
+ /**
+ * Reflect the current dock widget title in the floating widget windowTitle()
+ * depending on the CDockManager::FloatingContainerHasWidgetTitle flag
+ */
+ void reflectCurrentWidget(CDockWidget* CurrentWidget)
+ {
+ // reflect CurrentWidget's title if configured to do so, otherwise display application name as window title
+ if (testConfigFlag(CDockManager::FloatingContainerHasWidgetTitle))
+ {
+ setWindowTitle(CurrentWidget->windowTitle());
+ }
+ else
+ {
+ setWindowTitle(floatingContainersTitle());
+ }
+
+ // reflect CurrentWidget's icon if configured to do so, otherwise display application icon as window icon
+ QIcon CurrentWidgetIcon = CurrentWidget->icon();
+ if (testConfigFlag(CDockManager::FloatingContainerHasWidgetIcon)
+ && !CurrentWidgetIcon.isNull())
+ {
+ _this->setWindowIcon(CurrentWidget->icon());
+ }
+ else
+ {
+ _this->setWindowIcon(CurrentWidget->windowIcon());
+ }
+ }
+
+ /**
+ * 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
+
+//============================================================================
+FloatingDockContainerPrivate::FloatingDockContainerPrivate(
+ CFloatingDockContainer *_public) :
+ _this(_public)
+{
+
+}
+
+//============================================================================
+void FloatingDockContainerPrivate::titleMouseReleaseEvent()
+{
+ setState(DraggingInactive);
+ if (!DropContainer)
+ {
+ return;
+ }
+
+ // DockManager will be unlinked from this within DropContainer->dropFloatingWidget
+ const auto OriginalDockManager = this->DockManager.data();
+
+ if (DockManager->dockAreaOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea
+ || DockManager->containerOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea)
+ {
+ CDockOverlay *Overlay = DockManager->containerOverlay();
+ if (!Overlay->dropOverlayRect().isValid())
+ {
+ Overlay = DockManager->dockAreaOverlay();
+ }
+
+ // 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()))
+ {
+ // 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());
+ }
+
+ OriginalDockManager->containerOverlay()->hideOverlay();
+ OriginalDockManager->dockAreaOverlay()->hideOverlay();
+}
+
+
+//============================================================================
+void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos)
+{
+ if (!_this->isVisible() || !DockManager)
+ {
+ return;
+ }
+
+#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())
+ {
+ return;
+ }
+#endif
+
+ auto Containers = DockManager->dockContainers();
+ CDockContainerWidget *TopContainer = nullptr;
+ for (auto ContainerWidget : Containers)
+ {
+ if (!ContainerWidget->isVisible())
+ {
+ continue;
+ }
+
+ if (DockContainer == ContainerWidget)
+ {
+ continue;
+ }
+
+ QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos);
+ if (ContainerWidget->rect().contains(MappedPos))
+ {
+ if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer))
+ {
+ TopContainer = ContainerWidget;
+ }
+ }
+ }
+
+ DropContainer = TopContainer;
+ if (!TopContainer)
+ {
+ DockManager->containerOverlay()->hideOverlay();
+ DockManager->dockAreaOverlay()->hideOverlay();
+ return;
+ }
+
+ CDockContainerWidget::showDropOverlays(DockManager, TopContainer, GlobalPos,
+ DockContainer->features().testFlag(CDockWidget::DockWidgetPinnable));
+}
+
+
+//============================================================================
+void FloatingDockContainerPrivate::handleEscapeKey()
+{
+ ADS_PRINT("FloatingDockContainerPrivate::handleEscapeKey()");
+ setState(DraggingInactive);
+ DockManager->containerOverlay()->hideOverlay();
+ DockManager->dockAreaOverlay()->hideOverlay();
+}
+
+
+//============================================================================
+// Wayland: a floating widget that is a child of the dock manager makes Qt
+// turn the dock manager and all of its child widgets into native windows
+// when the floating widget is shown. Native child widgets are
+// wl_subsurfaces that take part in the compositors drag and drop target
+// picking and steal the drop focus from the dock container during a
+// platform drag. The dock manager deletes the registered floating widgets
+// in its destructor, so the floating widget does not need a parent for
+// memory management.
+CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) :
+ tFloatingWidgetBase(internal::isWayland() ? nullptr : static_cast<QWidget*>(DockManager)),
+ d(new FloatingDockContainerPrivate(this))
+{
+ d->DockManager = DockManager;
+ d->DockContainer = new CDockContainerWidget(DockManager, this);
+ connect(d->DockContainer, SIGNAL(dockAreasAdded()), this,
+ SLOT(onDockAreasAddedOrRemoved()));
+ connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this,
+ SLOT(onDockAreasAddedOrRemoved()));
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ QDockWidget::setWidget(d->DockContainer);
+ QDockWidget::setFeatures(QDockWidget::DockWidgetClosable
+ | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
+
+ bool native_window = true;
+
+ // FloatingContainerForce*TitleBar is overwritten by the "ADS_UseNativeTitle" environment variable if set.
+ auto env = qgetenv("ADS_UseNativeTitle").toUpper();
+ if (env == "1")
+ {
+ native_window = true;
+ }
+ else if (env == "0")
+ {
+ native_window = false;
+ }
+ else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceNativeTitleBar))
+ {
+ native_window = true;
+ }
+ else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceQWidgetTitleBar))
+ {
+ native_window = false;
+ }
+ else
+ {
+ // KDE doesn't seem to fire MoveEvents while moving windows, so for now no native titlebar for everything using KWin.
+ QString window_manager = internal::windowManager().toUpper().split(" ")[0];
+ native_window = window_manager != "KWIN";
+ }
+
+ // Wayland does not allow clients to move windows, so the custom title
+ // bar cannot work there - dragging it would not move the window. Always
+ // use a native window so that the user can move the floating widget
+ // via the window decoration provided by the compositor or by Qt.
+ if (internal::isWayland())
+ {
+ native_window = true;
+ }
+
+ if (native_window)
+ {
+ setTitleBarWidget(new QWidget());
+ setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
+ }
+ else
+ {
+ d->TitleBar = new CFloatingWidgetTitleBar(this);
+ setTitleBarWidget(d->TitleBar);
+ setWindowFlags(Qt::Window | Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint);
+ d->TitleBar->enableCloseButton(isClosable());
+ connect(d->TitleBar, SIGNAL(closeRequested()), SLOT(close()));
+ connect(d->TitleBar, &CFloatingWidgetTitleBar::maximizeRequested,
+ this, &CFloatingDockContainer::onMaximizeRequest);
+ }
+#else
+ setWindowFlags(
+ Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
+ QBoxLayout *l = new QBoxLayout(QBoxLayout::TopToBottom);
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+ setLayout(l);
+ l->addWidget(d->DockContainer);
+#endif
+
+ if (CDockManager::testConfigFlag(CDockManager::UseNativeWindows))
+ {
+ winId();
+ }
+
+ // Wayland: the floating widget has no parent widget (see above), so it
+ // does not inherit the dock manager's effective style sheet through the
+ // widget hierarchy. Apply the style sheets along the dock manager parent
+ // chain explicitly, so the floating widget looks like the docked content.
+ // CDockManager::changeEvent() keeps this up to date when the style sheet
+ // changes while the widget is already floating.
+ if (internal::isWayland())
+ {
+ const QString StyleSheet = waylandInheritedStyleSheet(DockManager);
+ if (!StyleSheet.isEmpty())
+ {
+ setStyleSheet(StyleSheet);
+ }
+ }
+
+ DockManager->registerFloatingWidget(this);
+}
+
+//============================================================================
+CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget *DockArea) :
+ CFloatingDockContainer(DockArea->dockManager())
+{
+ d->DockContainer->addDockArea(DockArea);
+
+ auto TopLevelDockWidget = topLevelDockWidget();
+ if (TopLevelDockWidget)
+ {
+ TopLevelDockWidget->emitTopLevelChanged(true);
+ }
+
+ d->DockManager->notifyWidgetOrAreaRelocation(DockArea);
+}
+
+//============================================================================
+CFloatingDockContainer::CFloatingDockContainer(CDockWidget *DockWidget) :
+ CFloatingDockContainer(DockWidget->dockManager())
+{
+ d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget);
+ auto TopLevelDockWidget = topLevelDockWidget();
+ if (TopLevelDockWidget)
+ {
+ TopLevelDockWidget->emitTopLevelChanged(true);
+ }
+
+ d->DockManager->notifyWidgetOrAreaRelocation(DockWidget);
+}
+
+
+//============================================================================
+CFloatingDockContainer::~CFloatingDockContainer()
+{
+ ADS_PRINT("~CFloatingDockContainer");
+ if (d->DockManager)
+ {
+ d->DockManager->removeFloatingWidget(this);
+ }
+ delete d;
+}
+
+
+//============================================================================
+void CFloatingDockContainer::deleteContent()
+{
+ std::vector<QPointer<ads::CDockAreaWidget>> areas;
+ for (int i = 0; i != dockContainer()->dockAreaCount(); ++i)
+ {
+ areas.push_back( dockContainer()->dockArea(i) );
+ }
+ for (auto area : areas)
+ {
+ if (!area)
+ {
+ continue;
+ }
+
+ // QPointer delete safety - just in case some dock widget in destruction
+ // deletes another related/twin or child dock widget.
+ std::vector<QPointer<QWidget>> deleteWidgets;
+ for (auto widget : area->dockWidgets())
+ {
+ deleteWidgets.push_back(widget);
+ }
+ for (auto ptrWdg : deleteWidgets)
+ {
+ delete ptrWdg;
+ }
+ }
+}
+
+//============================================================================
+CDockContainerWidget* CFloatingDockContainer::dockContainer() const
+{
+ return d->DockContainer;
+}
+
+//============================================================================
+bool CFloatingDockContainer::isDraggingActive() const
+{
+ return d->isState(DraggingFloatingWidget);
+}
+
+//============================================================================
+void CFloatingDockContainer::changeEvent(QEvent *event)
+{
+ Super::changeEvent(event);
+ switch (event->type())
+ {
+ case QEvent::ActivationChange:
+ if (isActiveWindow())
+ {
+ ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange ");
+ d->zOrderIndex = ++zOrderCounterFloating;
+
+#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();
+ }
+ }
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ if (d->TitleBar)
+ {
+ d->TitleBar->setVisible(!(isFloating() && isFullScreen()));
+ }
+#endif
+ break;
+
+ default:
+ break; // do nothing
+ }
+}
+
+
+#ifdef Q_OS_WIN
+#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
+bool CFloatingDockContainer::nativeEvent(const QByteArray &eventType, void *message, long *result)
+#else
+bool CFloatingDockContainer::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
+#endif
+{
+ QWidget::nativeEvent(eventType, message, result);
+ MSG *msg = static_cast<MSG*>(message);
+ switch (msg->message)
+ {
+ case WM_MOVING:
+ {
+ if (d->isState(DraggingFloatingWidget))
+ {
+ d->updateDropOverlays(QCursor::pos());
+ }
+ }
+ break;
+
+ case WM_NCLBUTTONDOWN:
+ if (msg->wParam == HTCAPTION && d->isState(DraggingInactive))
+ {
+ ADS_PRINT("CFloatingDockContainer::nativeEvent WM_NCLBUTTONDOWN");
+ d->DragStartPos = pos();
+ d->setState(DraggingMousePressed);
+ }
+ break;
+
+ case WM_NCLBUTTONDBLCLK:
+ d->setState(DraggingInactive);
+ break;
+
+ case WM_ENTERSIZEMOVE:
+ if (d->isState(DraggingMousePressed))
+ {
+ ADS_PRINT("CFloatingDockContainer::nativeEvent WM_ENTERSIZEMOVE");
+ d->setState(DraggingFloatingWidget);
+ d->updateDropOverlays(QCursor::pos());
+ }
+ break;
+
+ case WM_EXITSIZEMOVE:
+ if (d->isState(DraggingFloatingWidget))
+ {
+ ADS_PRINT("CFloatingDockContainer::nativeEvent WM_EXITSIZEMOVE");
+ if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)
+ {
+ d->handleEscapeKey();
+ }
+ else
+ {
+ d->titleMouseReleaseEvent();
+ }
+ }
+ break;
+ }
+ return false;
+}
+#endif
+
+
+//============================================================================
+void CFloatingDockContainer::closeEvent(QCloseEvent *event)
+{
+ ADS_PRINT("CFloatingDockContainer closeEvent");
+ d->setState(DraggingInactive);
+ event->ignore();
+ if (!isClosable())
+ {
+ return;
+ }
+
+ bool HasOpenDockWidgets = false;
+ for (auto DockWidget : d->DockContainer->openedDockWidgets())
+ {
+ if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) || DockWidget->features().testFlag(CDockWidget::CustomCloseHandling))
+ {
+ bool Closed = DockWidget->closeDockWidgetInternal();
+ if (!Closed)
+ {
+ HasOpenDockWidgets = true;
+ }
+ }
+ else
+ {
+ DockWidget->toggleView(false);
+ }
+ }
+
+ if (HasOpenDockWidgets)
+ {
+ return;
+ }
+
+ // New bug (QWebEngineView reload side effect):
+ // when a WebEngine-based dock is tabified into a floating container, the
+ // embedded native/web process can trigger delayed hide/show cycles on the
+ // floating window. If every non-spontaneous hide propagates to
+ // DockWidget->toggleView(false), unrelated tabs are marked closed and seem
+ // to "disappear". We therefore arm HideContentOnNextHide only for the
+ // explicit close path.
+ d->HideContentOnNextHide = true;
+
+ // In Qt version after 5.9.2 there seems to be a bug that causes the
+ // QWidget::event() function to not receive any NonClientArea mouse
+ // events anymore after a close/show cycle. The bug is reported here:
+ // https://bugreports.qt.io/browse/QTBUG-73295
+ // The following code is a workaround for Qt versions > 5.9.2 that seems
+ // to work
+ // Starting from Qt version 5.12.2 this seems to work again. But
+ // now the QEvent::NonClientAreaMouseButtonPress function returns always
+ // Qt::RightButton even if the left button was pressed
+ this->hide();
+}
+
+//============================================================================
+void CFloatingDockContainer::hideEvent(QHideEvent *event)
+{
+ Super::hideEvent(event);
+ if (event->spontaneous())
+ {
+ return;
+ }
+
+ // Prevent toogleView() events during restore state
+ if (d->DockManager->isRestoringState())
+ {
+ return;
+ }
+
+ // Only a close operation should propagate hide->toggleView(false) to
+ // child dock widgets. Generic hide/show cycles (e.g. from platform or
+ // embedded native content) must not change dock open/closed state.
+ if (!d->HideContentOnNextHide)
+ {
+ return;
+ }
+ d->HideContentOnNextHide = false;
+
+ if ( d->AutoHideChildren )
+ {
+ d->Hiding = true;
+ for ( auto DockArea : d->DockContainer->openedDockAreas() )
+ {
+ for ( auto DockWidget : DockArea->openedDockWidgets() )
+ {
+ DockWidget->toggleView( false );
+ }
+ }
+ d->Hiding = false;
+ }
+}
+
+
+//============================================================================
+void CFloatingDockContainer::showEvent(QShowEvent *event)
+{
+ Super::showEvent(event);
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
+ {
+ this->window()->activateWindow();
+ }
+#endif
+}
+
+
+//============================================================================
+void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos,
+ const QSize &Size, eDragState DragState, QWidget *MouseEventHandler)
+{
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ if (!isMaximized())
+ {
+ resize(Size);
+ d->DragStartMousePosition = DragStartMousePos;
+ }
+ d->setState(DragState);
+ if (DraggingFloatingWidget == DragState)
+ {
+ d->MouseEventHandler = MouseEventHandler;
+ if (d->MouseEventHandler)
+ {
+ d->MouseEventHandler->grabMouse();
+ }
+ }
+
+ if (!isMaximized())
+ {
+ moveFloating();
+ }
+ show();
+#else
+ Q_UNUSED(MouseEventHandler)
+ resize(Size);
+ d->DragStartMousePosition = DragStartMousePos;
+ d->setState(DragState);
+ moveFloating();
+ show();
+#endif
+}
+
+//============================================================================
+void CFloatingDockContainer::moveFloating()
+{
+ int BorderSize = (frameSize().width() - size().width()) / 2;
+ const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition
+ - QPoint(BorderSize, 0);
+ move(moveToPos);
+ switch (d->DraggingState)
+ {
+ case DraggingMousePressed:
+ d->setState(DraggingFloatingWidget);
+ d->updateDropOverlays(QCursor::pos());
+ break;
+
+ case DraggingFloatingWidget:
+ d->updateDropOverlays(QCursor::pos());
+#ifdef Q_OS_MACOS
+ // In OSX when hiding the DockAreaOverlay the application would set
+ // 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.
+ activateWindow();
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
+//============================================================================
+bool CFloatingDockContainer::isClosable() const
+{
+ return d->DockContainer->features().testFlag(
+ CDockWidget::DockWidgetClosable);
+}
+
+//============================================================================
+void CFloatingDockContainer::onDockAreasAddedOrRemoved()
+{
+ ADS_PRINT("CFloatingDockContainer::onDockAreasAddedOrRemoved()");
+ auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
+ if (TopLevelDockArea)
+ {
+ d->SingleDockArea = TopLevelDockArea;
+ CDockWidget* CurrentWidget = d->SingleDockArea->currentDockWidget();
+ d->reflectCurrentWidget(CurrentWidget);
+ connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
+ SLOT(onDockAreaCurrentChanged(int)));
+ }
+ else
+ {
+ if (d->SingleDockArea)
+ {
+ disconnect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
+ SLOT(onDockAreaCurrentChanged(int)));
+ d->SingleDockArea = nullptr;
+ }
+ d->setWindowTitle(d->floatingContainersTitle());
+ setWindowIcon(QApplication::windowIcon());
+ }
+}
+
+//============================================================================
+void CFloatingDockContainer::updateWindowTitle()
+{
+ // If this floating container will be hidden, then updating the window
+ // tile is not required anymore
+ if (d->Hiding)
+ {
+ return;
+ }
+
+
+ auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
+ if (TopLevelDockArea)
+ {
+ CDockWidget* CurrentWidget = TopLevelDockArea->currentDockWidget();
+ if (CurrentWidget)
+ {
+ d->reflectCurrentWidget(CurrentWidget);
+ }
+ }
+ else
+ {
+ d->setWindowTitle(d->floatingContainersTitle());
+ setWindowIcon(QApplication::windowIcon());
+ }
+}
+
+//============================================================================
+void CFloatingDockContainer::onDockAreaCurrentChanged(int Index)
+{
+ Q_UNUSED(Index);
+ CDockWidget* CurrentWidget = d->SingleDockArea->currentDockWidget();
+ d->reflectCurrentWidget(CurrentWidget);
+}
+
+//============================================================================
+bool CFloatingDockContainer::restoreState(CDockingStateReader &Stream,
+ bool Testing)
+{
+ if (!d->DockContainer->restoreState(Stream, Testing))
+ {
+ return false;
+ }
+ onDockAreasAddedOrRemoved();
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ if(d->TitleBar)
+ {
+ d->TitleBar->setMaximizedIcon(windowState() == Qt::WindowMaximized);
+ }
+#endif
+ return true;
+}
+
+
+//============================================================================
+bool CFloatingDockContainer::hasTopLevelDockWidget() const
+{
+ return d->DockContainer->hasTopLevelDockWidget();
+}
+
+//============================================================================
+CDockWidget* CFloatingDockContainer::topLevelDockWidget() const
+{
+ return d->DockContainer->topLevelDockWidget();
+}
+
+//============================================================================
+QList<CDockWidget*> CFloatingDockContainer::dockWidgets() const
+{
+ return d->DockContainer->dockWidgets();
+}
+
+//============================================================================
+void CFloatingDockContainer::finishDropOperation()
+{
+ // Widget has been redocked, so it must be hidden right way (see
+ // https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/351)
+ // but AutoHideChildren must be set to false because "this" still contains
+ // dock widgets that shall not be toggled hidden.
+ d->AutoHideChildren = false;
+ hide();
+ // The floating widget will be deleted now. Ensure, that the destructor
+ // of the floating widget does not delete any dock areas that have been
+ // moved to a new container - simply remove all dock areas before deleting
+ // the floating widget
+ d->DockContainer->removeAllDockAreas();
+ deleteLater();
+ if (d->DockManager)
+ {
+ d->DockManager->removeFloatingWidget(this);
+ d->DockManager.clear();
+ }
+ this->dockContainer()->removeFromDockManager();
+}
+
+//============================================================================
+void CFloatingDockContainer::finishDragging()
+{
+ ADS_PRINT("CFloatingDockContainer::finishDragging");
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ setWindowOpacity(1);
+ activateWindow();
+ if (d->MouseEventHandler)
+ {
+ d->MouseEventHandler->releaseMouse();
+ d->MouseEventHandler = nullptr;
+ }
+#endif
+ d->titleMouseReleaseEvent();
+}
+
+
+//============================================================================
+// MIME type that transports the CFloatingDockContainer pointer between the
+// drag source and the CDockContainerWidget drop targets within this
+// application
+static const char* const FloatingWidgetMimeType = "application/x-ads-floating-dock-container";
+
+// MIME types that QWaylandDataDevice translates into an
+// xdg_toplevel_drag_v1 request so that the compositor attaches the floating
+// widget window to the drag cursor. The format matches
+// QMainWindowLayout::performPlatformWidgetDrag() in qtbase
+static const char* const PlatformDragWindowMimeType = "application/x-qt-mainwindowdrag-window";
+static const char* const PlatformDragPositionMimeType = "application/x-qt-mainwindowdrag-position";
+
+// Maximum age of the recorded drop candidate that startPlatformDrag() still
+// accepts as a drop. It must be longer than the interval between drag move
+// events (so a drop right after the last move counts) but short enough to
+// reject a release far away from the last drop area
+static const int PlatformDragDropCandidateTimeoutMs = 400;
+
+
+// Records the last drop candidate during a Wayland platform drag. Some
+// compositors do not deliver a drop event when the dragged window overlaps
+// the drop target (they send a leave event instead), so startPlatformDrag()
+// falls back to this candidate when no drop event was delivered.
+struct PlatformDragDropCandidate
+{
+ QPointer<CDockContainerWidget> Container;
+ QPoint GlobalPos;
+ bool ValidDropArea = false;
+ bool DropHandled = false;
+ QElapsedTimer SinceLastUpdate;
+};
+static PlatformDragDropCandidate s_PlatformDragDropCandidate;
+
+
+//============================================================================
+void CFloatingDockContainer::platformDragUpdateDropCandidate(
+ CDockContainerWidget* Container, const QPoint& GlobalPos, bool ValidDropArea)
+{
+ s_PlatformDragDropCandidate.Container = Container;
+ s_PlatformDragDropCandidate.GlobalPos = GlobalPos;
+ s_PlatformDragDropCandidate.ValidDropArea = ValidDropArea;
+ s_PlatformDragDropCandidate.SinceLastUpdate.start();
+}
+
+
+//============================================================================
+void CFloatingDockContainer::platformDragNotifyDropHandled()
+{
+ s_PlatformDragDropCandidate.DropHandled = true;
+}
+
+
+//============================================================================
+QString CFloatingDockContainer::waylandInheritedStyleSheet(QWidget* DockManager)
+{
+ QString StyleSheet;
+ for (QWidget* Widget = DockManager; Widget; Widget = Widget->parentWidget())
+ {
+ const QString WidgetStyleSheet = Widget->styleSheet();
+ if (!WidgetStyleSheet.isEmpty())
+ {
+ StyleSheet = WidgetStyleSheet + QLatin1Char('\n') + StyleSheet;
+ }
+ }
+ return StyleSheet;
+}
+
+
+//============================================================================
+Qt::DropAction CFloatingDockContainer::startPlatformDrag(
+ CFloatingDockContainer* FloatingWidget, const QPoint& GlobalPressPos,
+ QWidget* DragSource, const QPoint* DragOffset)
+{
+ auto serialize = [](const auto &object)
+ {
+ QByteArray Data;
+ QDataStream DataStream(&Data, QIODevice::WriteOnly);
+ DataStream << object;
+ return Data;
+ };
+
+ // xdg_toplevel_drag_v1: the attach offset that places the new window under
+ // the cursor is only honoured by the compositor while the toplevel is still
+ // UNMAPPED. The protocol says the client "issues a xdg_toplevel_drag_v1.attach
+ // request before mapping it", and the offset "might only be used when an
+ // unmapped window is attached". Qt's QWaylandDataDevice::startDrag() performs
+ // the attach when the data drag starts, reading the xdg_toplevel surface role
+ // off the window handle.
+ //
+ // The caller already show()'d the floating widget, which creates the
+ // xdg_toplevel role, but the surface is only mapped (a buffer committed)
+ // once the event loop is pumped. We therefore deliberately do NOT wait for
+ // exposure here: pumping events would map the window before exec() runs the
+ // attach, after which the compositor ignores the offset and leaves the
+ // window at its default position (typically screen center). Proceeding
+ // straight to exec() keeps the toplevel created-but-unmapped so the attach
+ // offset positions it under the cursor.
+
+ // The offset is the press position relative to the floating widget top
+ // left corner, so the compositor keeps the cursor at the same spot on
+ // the window during the drag. For a freshly created floating window the
+ // caller supplies it explicitly (DragOffset): on Wayland the new window has
+ // no meaningful geometry yet, so mapFromGlobal() would give a wrong/random
+ // offset and the compositor would place the window randomly.
+ QPoint DragStartOffset;
+ if (DragOffset)
+ {
+ DragStartOffset = *DragOffset;
+ // The new floating window is a native window on Wayland (forced in the
+ // constructor), so it has a title bar / decoration around the content -
+ // drawn either by the compositor or by Qt's client-side decoration.
+ // The supplied offset is relative to the source tab/area content, so
+ // shift it by the window frame's top and left margins to keep the
+ // grabbed content point - not the decoration - under the cursor. With
+ // server-side decorations the margins are 0 and no shift is applied.
+ if (FloatingWidget->windowHandle())
+ {
+ const QMargins Frame = FloatingWidget->windowHandle()->frameMargins();
+ DragStartOffset.rx() += Frame.left();
+ DragStartOffset.ry() += Frame.top();
+ }
+ }
+ else
+ {
+ DragStartOffset = FloatingWidget->mapFromGlobal(GlobalPressPos);
+ }
+
+ auto Drag = new QDrag(DragSource);
+ auto MimeData = new QMimeData();
+ MimeData->setData(QLatin1String(PlatformDragWindowMimeType),
+ serialize(reinterpret_cast<qintptr>(FloatingWidget->windowHandle())));
+ MimeData->setData(QLatin1String(PlatformDragPositionMimeType),
+ serialize(DragStartOffset));
+ MimeData->setData(QLatin1String(FloatingWidgetMimeType),
+ serialize(reinterpret_cast<qintptr>(FloatingWidget)));
+ Drag->setMimeData(MimeData);
+
+ // The drop targets dock the floating widget in their dropEvent() handler,
+ // which deletes the floating widget before exec() returns
+ QPointer<CFloatingDockContainer> GuardedFloatingWidget(FloatingWidget);
+ auto DockManager = FloatingWidget->dockContainer()->dockManager();
+ s_PlatformDragDropCandidate = PlatformDragDropCandidate();
+ // The QDrag::exec() return value does not reliably encode whether the
+ // floating widget was docked on Wayland (e.g. compositors that send a
+ // leave event instead of a drop event report Qt::IgnoreAction even though
+ // the drag ended over a drop area). Track the docking outcome explicitly
+ // instead and translate it into the documented return value below.
+ Drag->exec();
+
+ // Some compositors (e.g. Mutter) do not deliver a drop event to the
+ // target container when the dragged window overlaps it - they send a
+ // leave event on release instead. If no drop event was delivered, but
+ // the drag ended over a valid drop area, dock the floating widget into
+ // the recorded candidate. A short timeout distinguishes a drop on a
+ // drop area from a release outside of any drop area to keep the widget
+ // floating
+ auto& Candidate = s_PlatformDragDropCandidate;
+ bool Docked = Candidate.DropHandled;
+ if (!Candidate.DropHandled && !GuardedFloatingWidget.isNull()
+ && Candidate.Container && Candidate.ValidDropArea
+ && Candidate.SinceLastUpdate.isValid()
+ && Candidate.SinceLastUpdate.elapsed() < PlatformDragDropCandidateTimeoutMs)
+ {
+ Candidate.Container->dropFloatingWidget(GuardedFloatingWidget,
+ Candidate.GlobalPos);
+ Docked = true;
+ }
+ s_PlatformDragDropCandidate = PlatformDragDropCandidate();
+ DockManager->containerOverlay()->hideOverlay();
+ DockManager->dockAreaOverlay()->hideOverlay();
+ Drag->deleteLater();
+
+ if (GuardedFloatingWidget)
+ {
+ GuardedFloatingWidget->d->setState(DraggingInactive);
+ }
+
+ return Docked ? Qt::MoveAction : Qt::IgnoreAction;
+}
+
+
+//============================================================================
+bool CFloatingDockContainer::waylandMoveOrLeaveInWindowPreview(
+ CFloatingDragPreview* Preview, QWidget* SourceWindow, const QPoint& GlobalPos)
+{
+ const QPoint InWindow = SourceWindow->mapFromGlobal(GlobalPos);
+ if (SourceWindow->rect().contains(InWindow))
+ {
+ if (Preview)
+ {
+ Preview->moveFloating(GlobalPos);
+ }
+ return true;
+ }
+
+ // Boundary cross: tear down the in-window preview without performing a
+ // drop. The caller converts the gesture into a native compositor platform
+ // drag while the implicit pointer grab from the original press is still
+ // active, which is what QDrag::exec() / xdg_toplevel_drag_v1 requires.
+ if (Preview)
+ {
+ Preview->cancelDraggingSilently();
+ }
+ return false;
+}
+
+
+//============================================================================
+Qt::DropAction CFloatingDockContainer::startPlatformDragForFloatingWidget(
+ IFloatingWidget* FloatingWidget, const QPoint& GrabOffset, const QSize& Size,
+ const QPoint& GlobalGrabPos, QWidget* DragSource)
+{
+ FloatingWidget->startFloating(GrabOffset, Size, DraggingInactive, nullptr);
+ // Keep the grab point under the cursor across the conversion. A client
+ // cannot position a Wayland top-level and the new window has no usable
+ // geometry yet, so pass the surface-local grab offset explicitly rather
+ // than letting startPlatformDrag() derive it from the press via
+ // mapFromGlobal() (which would be random on Wayland). We must NOT move()
+ // the window here either: besides being ignored by the compositor, a
+ // geometry change between show() and exec() risks mapping the surface
+ // before the attach, which would discard the offset.
+ QPoint Offset = GrabOffset;
+ return startPlatformDrag(static_cast<CFloatingDockContainer*>(FloatingWidget),
+ GlobalGrabPos, DragSource, &Offset);
+}
+
+
+//============================================================================
+CFloatingDockContainer* CFloatingDockContainer::floatingWidgetFromMimeData(
+ const QMimeData* MimeData)
+{
+ if (!MimeData || !MimeData->hasFormat(QLatin1String(FloatingWidgetMimeType)))
+ {
+ return nullptr;
+ }
+
+ qintptr FloatingWidgetPtr = 0;
+ QDataStream DataStream(MimeData->data(QLatin1String(FloatingWidgetMimeType)));
+ DataStream >> FloatingWidgetPtr;
+ return reinterpret_cast<CFloatingDockContainer*>(FloatingWidgetPtr);
+}
+
+#ifdef Q_OS_MACOS
+//============================================================================
+bool CFloatingDockContainer::event(QEvent *e)
+{
+ switch (d->DraggingState)
+ {
+ case DraggingInactive:
+ {
+ // Normally we would check here, if the left mouse button is pressed.
+ // But from QT version 5.12.2 on the mouse events from
+ // QEvent::NonClientAreaMouseButtonPress return the wrong mouse button
+ // The event always returns Qt::RightButton even if the left button
+ // is clicked.
+ // It is really great to work around the whole NonClientMouseArea
+ // bugs
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 2))
+ if (e->type() == QEvent::NonClientAreaMouseButtonPress /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/)
+#else
+ if (e->type() == QEvent::NonClientAreaMouseButtonPress && QGuiApplication::mouseButtons().testFlag(Qt::LeftButton))
+#endif
+ {
+ ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type());
+ d->DragStartPos = pos();
+ d->setState(DraggingMousePressed);
+ }
+ }
+ break;
+
+ case DraggingMousePressed:
+ switch (e->type())
+ {
+ case QEvent::NonClientAreaMouseButtonDblClick:
+ ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick");
+ d->setState(DraggingInactive);
+ break;
+
+ case QEvent::Resize:
+ // If the first event after the mouse press is a resize event, then
+ // the user resizes the window instead of dragging it around.
+ // But there is one exception. If the window is maximized,
+ // then dragging the window via title bar will cause the widget to
+ // leave the maximized state. This in turn will trigger a resize event.
+ // To know, if the resize event was triggered by user via moving a
+ // corner of the window frame or if it was caused by a windows state
+ // change, we check, if we are not in maximized state.
+ if (!isMaximized())
+ {
+ d->setState(DraggingInactive);
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case DraggingFloatingWidget:
+ if (e->type() == QEvent::NonClientAreaMouseButtonRelease)
+ {
+ ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease");
+ d->titleMouseReleaseEvent();
+ }
+ break;
+
+ default:
+ break;
+ }
+
+#if (ADS_DEBUG_LEVEL > 0)
+ qDebug() << QTime::currentTime() << "CFloatingDockContainer::event " << e->type();
+#endif
+ return QWidget::event(e);
+}
+
+
+//============================================================================
+void CFloatingDockContainer::moveEvent(QMoveEvent *event)
+{
+ QWidget::moveEvent(event);
+ switch (d->DraggingState)
+ {
+ case DraggingMousePressed:
+ d->setState(DraggingFloatingWidget);
+ d->updateDropOverlays(QCursor::pos());
+ break;
+
+ case DraggingFloatingWidget:
+ d->updateDropOverlays(QCursor::pos());
+ // In OSX when hiding the DockAreaOverlay the application would set
+ // 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.
+ activateWindow();
+ break;
+ default:
+ break;
+ }
+
+
+}
+#endif
+
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+//============================================================================
+void CFloatingDockContainer::onMaximizeRequest()
+{
+ if (windowState() == Qt::WindowMaximized)
+ {
+ showNormal();
+ }
+ else
+ {
+ showMaximized();
+ }
+}
+
+
+//============================================================================
+void CFloatingDockContainer::showNormal(bool fixGeometry)
+{
+ if ( (windowState() & Qt::WindowMaximized) != 0 ||
+ (windowState() & Qt::WindowFullScreen) != 0)
+ {
+ QRect oldNormal = normalGeometry();
+ Super::showNormal();
+ if(fixGeometry)
+ {
+ setGeometry(oldNormal);
+ }
+ }
+ if(d->TitleBar)
+ {
+ d->TitleBar->setMaximizedIcon(false);
+ }
+}
+
+
+//============================================================================
+void CFloatingDockContainer::showMaximized()
+{
+ Super::showMaximized();
+ if (d->TitleBar)
+ {
+ d->TitleBar->setMaximizedIcon(true);
+ }
+}
+
+
+//============================================================================
+bool CFloatingDockContainer::isMaximized() const
+{
+ return windowState() == Qt::WindowMaximized;
+}
+
+
+//============================================================================
+void CFloatingDockContainer::show()
+{
+ // Prevent this window from showing in the taskbar and pager (alt+tab)
+ internal::xcb_add_prop(true, winId(), "_NET_WM_STATE", "_NET_WM_STATE_SKIP_TASKBAR");
+ internal::xcb_add_prop(true, winId(), "_NET_WM_STATE", "_NET_WM_STATE_SKIP_PAGER");
+ Super::show();
+}
+
+
+//============================================================================
+void CFloatingDockContainer::resizeEvent(QResizeEvent *event)
+{
+ d->IsResizing = true;
+ Super::resizeEvent(event);
+}
+
+
+//============================================================================
+void CFloatingDockContainer::moveEvent(QMoveEvent *event)
+{
+ Super::moveEvent(event);
+ // On Wayland, the global cursor position is not available and the
+ // compositor does not report window moves, so the docking via window
+ // moves cannot work. Floating widgets are docked via the platform drag
+ // and drop implemented in CDockContainerWidget instead
+ if (!d->IsResizing && event->spontaneous() && d->MousePressed
+ && !internal::isWayland())
+ {
+ d->setState(DraggingFloatingWidget);
+ d->updateDropOverlays(QCursor::pos());
+ }
+ d->IsResizing = false;
+}
+
+
+//============================================================================
+bool CFloatingDockContainer::event(QEvent *e)
+{
+ bool result = Super::event(e);
+ switch (e->type())
+ {
+ case QEvent::WindowActivate:
+ d->MousePressed = false;
+ break;
+ case QEvent::WindowDeactivate:
+ d->MousePressed = true;
+ break;
+ default:
+ break;
+ }
+ return result;
+}
+
+//============================================================================
+bool CFloatingDockContainer::hasNativeTitleBar()
+{
+ return d->TitleBar == nullptr;
+}
+#endif
+
+} // namespace ads
+
+//---------------------------------------------------------------------------
+// EOF FloatingDockContainer.cpp
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDockContainer.h b/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDockContainer.h
index 9bcb6f667..fcaa0bcfb 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDockContainer.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDockContainer.h
@@ -1,312 +1,406 @@
-#ifndef FloatingDockContainerH
-#define FloatingDockContainerH
-/*******************************************************************************
-** Qt Advanced Docking System
-** Copyright (C) 2017 Uwe Kindler
-**
-** This library is free software; you can redistribute it and/or
-** modify it under the terms of the GNU Lesser General Public
-** License as published by the Free Software Foundation; either
-** version 2.1 of the License, or (at your option) any later version.
-**
-** This library is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-** Lesser General Public License for more details.
-**
-** You should have received a copy of the GNU Lesser General Public
-** License along with this library; If not, see <http://www.gnu.org/licenses/>.
-******************************************************************************/
-
-
-//============================================================================
-/// \file FloatingDockContainer.h
-/// \author Uwe Kindler
-/// \date 01.03.2017
-/// \brief Declaration of CFloatingDockContainer class
-//============================================================================
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include "ads_globals.h"
-
-#include <QRubberBand>
-
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
-#include <QDockWidget>
-#define tFloatingWidgetBase QDockWidget
-#else
-#include <QWidget>
-#define tFloatingWidgetBase QWidget
-#endif
-
-class CDockingStateReader;
-
-namespace ads
-{
-struct FloatingDockContainerPrivate;
-class CDockManager;
-struct DockManagerPrivate;
-class CDockAreaWidget;
-class CDockContainerWidget;
-class CDockWidget;
-class CDockManager;
-class CDockAreaTabBar;
-class CDockWidgetTab;
-struct DockWidgetTabPrivate;
-class CDockAreaTitleBar;
-struct DockAreaTitleBarPrivate;
-class CFloatingWidgetTitleBar;
-class CDockingStateReader;
-
-/**
- * Pure virtual interface for floating widgets.
- * This interface is used for opaque and non-opaque undocking. If opaque
- * undocking is used, the a real CFloatingDockContainer widget will be created
- */
-class ADS_EXPORT IFloatingWidget
-{
-public:
- virtual ~IFloatingWidget() = default;
-
- /**
- * Starts floating.
- * This function should get called typically from a mouse press event
- * handler
- */
- virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
- eDragState DragState, QWidget* MouseEventHandler) = 0;
-
- /**
- * Moves the widget to a new position relative to the position given when
- * startFloating() was called.
- * This function should be called from a mouse mouve event handler to
- * move the floating widget on mouse move events.
- */
- virtual void moveFloating() = 0;
-
- /**
- * Tells the widget that to finish dragging if the mouse is released.
- * This function should be called from a mouse release event handler
- * to finish the dragging
- */
- virtual void finishDragging() = 0;
-};
-
-
-/**
- * This implements a floating widget that is a dock container that accepts
- * docking of dock widgets like the main window and that can be docked into
- * another dock container.
- * Every floating window of the docking system is a FloatingDockContainer.
- */
-class ADS_EXPORT CFloatingDockContainer : public tFloatingWidgetBase, public IFloatingWidget
-{
- Q_OBJECT
-private:
- FloatingDockContainerPrivate* d; ///< private data (pimpl)
- friend struct FloatingDockContainerPrivate;
- friend class CDockManager;
- friend struct DockManagerPrivate;
- friend class CDockAreaTabBar;
- friend struct DockWidgetTabPrivate;
- friend class CDockWidgetTab;
- friend class CDockAreaTitleBar;
- friend struct DockAreaTitleBarPrivate;
- friend class CDockWidget;
- friend class CDockAreaWidget;
- friend class CFloatingWidgetTitleBar;
-
-private Q_SLOTS:
- void onDockAreasAddedOrRemoved();
- void onDockAreaCurrentChanged(int Index);
-
-protected:
- /**
- * Starts floating at the given global position.
- * Use moveToGlobalPos() to move the widget to a new position
- * depending on the start position given in Pos parameter
- */
- virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
- eDragState DragState, QWidget* MouseEventHandler) override;
-
- /**
- * Call this function to start dragging the floating widget
- */
- void startDragging(const QPoint& DragStartMousePos, const QSize& Size,
- QWidget* MouseEventHandler)
- {
- startFloating(DragStartMousePos, Size, DraggingFloatingWidget, MouseEventHandler);
- }
-
- /**
- * Call this function if you explicitly want to signal that dragging has
- * finished
- */
- virtual void finishDragging() override;
-
- /**
- * This function deletes all dock widgets in it.
- * This functions should be called only from dock manager in its
- * destructor before deleting the floating widget
- */
- void deleteContent();
-
- /**
- * Call this function if you just want to initialize the position
- * and size of the floating widget
- */
- void initFloatingGeometry(const QPoint& DragStartMousePos, const QSize& Size)
- {
- startFloating(DragStartMousePos, Size, DraggingInactive, nullptr);
- }
-
- /**
- * Moves the widget to a new position relative to the position given when
- * startFloating() was called
- */
- void moveFloating() override;
-
- /**
- * Restores the state from given stream.
- * If Testing is true, the function only parses the data from the given
- * stream but does not restore anything. You can use this check for
- * faulty files before you start restoring the state
- */
- bool restoreState(CDockingStateReader& Stream, bool Testing);
-
- /**
- * Call this function to update the window title
- */
- void updateWindowTitle();
-
-protected: // reimplements QWidget
- virtual void changeEvent(QEvent *event) override;
- virtual void closeEvent(QCloseEvent *event) override;
- virtual void hideEvent(QHideEvent *event) override;
- virtual void showEvent(QShowEvent *event) override;
-
-#ifdef Q_OS_MACOS
- virtual bool event(QEvent *e) override;
- 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;
-#endif
-
-#ifdef Q_OS_WIN
- /**
- * Native event filter for handling WM_MOVING messages on Windows
- */
-#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
- virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
-#else
- virtual bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
-#endif
-#endif
-
-
-public:
- using Super = tFloatingWidgetBase;
-
- /**
- * Create empty floating widget - required for restore state
- */
- CFloatingDockContainer(CDockManager* DockManager);
-
- /**
- * Create floating widget with the given dock area
- */
- CFloatingDockContainer(CDockAreaWidget* DockArea);
-
- /**
- * Create floating widget with the given dock widget
- */
- CFloatingDockContainer(CDockWidget* DockWidget);
-
- /**
- * Virtual Destructor
- */
- virtual ~CFloatingDockContainer();
-
- /**
- * Access function for the internal dock container
- */
- CDockContainerWidget* dockContainer() const;
-
- /**
- * This function returns true, if it can be closed.
- * It can be closed, if all dock widgets in all dock areas can be closed
- */
- bool isClosable() const;
-
- /**
- * This function returns true, if this floating widget has only one single
- * visible dock widget in a single visible dock area.
- * The single dock widget is a real top level floating widget because no
- * other widgets are docked.
- */
- bool hasTopLevelDockWidget() const;
-
- /**
- * This function returns the first dock widget in the first dock area.
- * If the function hasSingleDockWidget() returns true, then this function
- * returns this single dock widget.
- */
- CDockWidget* topLevelDockWidget() const;
-
- /**
- * This function returns a list of all dock widget in this floating widget.
- * This is a simple convenience function that simply calls the dockWidgets()
- * function of the internal container widget.
- */
- QList<CDockWidget*> dockWidgets() const;
-
- /**
- * This function hides the floating widget instantly and delete it later.
- */
- void finishDropOperation();
-
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
- /**
- * This is a function that responds to FloatingWidgetTitleBar::maximizeRequest()
- * Maximize or normalize the container size.
- */
- void onMaximizeRequest();
-
- /**
- * Normalize (Unmaximize) the window.
- * fixGeometry parameter fixes a "bug" in QT where immediately after calling showNormal
- * geometry is not set properly.
- * Set this true when moving the window immediately after normalizing.
- */
- void showNormal(bool fixGeometry=false);
-
- /**
- * Maximizes the window.
- */
- void showMaximized();
-
- /**
- * Returns if the window is currently maximized or not.
- */
- bool isMaximized() const;
-
- /**
- * Patched show to prevent the window from appearing in the taskbar.
- */
- void show();
-
- /**
- * Returns true if the floating widget has a native titlebar or false if
- * the floating widget has a QWidget based title bar
- */
- bool hasNativeTitleBar();
-#endif
-}; // class FloatingDockContainer
-}
- // namespace ads
-//-----------------------------------------------------------------------------
-#endif // FloatingDockContainerH
+#ifndef FloatingDockContainerH
+#define FloatingDockContainerH
+/*******************************************************************************
+** Qt Advanced Docking System
+** Copyright (C) 2017 Uwe Kindler
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+
+//============================================================================
+/// \file FloatingDockContainer.h
+/// \author Uwe Kindler
+/// \date 01.03.2017
+/// \brief Declaration of CFloatingDockContainer class
+//============================================================================
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include "ads_globals.h"
+
+#include <QRubberBand>
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+#include <QDockWidget>
+#define tFloatingWidgetBase QDockWidget
+#else
+#include <QWidget>
+#define tFloatingWidgetBase QWidget
+#endif
+
+class CDockingStateReader;
+class QMimeData;
+
+namespace ads
+{
+struct FloatingDockContainerPrivate;
+class CDockManager;
+struct DockManagerPrivate;
+class CDockAreaWidget;
+class CDockContainerWidget;
+class CDockWidget;
+class CDockManager;
+class CDockAreaTabBar;
+class CDockWidgetTab;
+struct DockWidgetTabPrivate;
+class CDockAreaTitleBar;
+struct DockAreaTitleBarPrivate;
+class CFloatingWidgetTitleBar;
+class CDockingStateReader;
+class CFloatingDragPreview;
+
+/**
+ * Pure virtual interface for floating widgets.
+ * This interface is used for opaque and non-opaque undocking. If opaque
+ * undocking is used, the a real CFloatingDockContainer widget will be created
+ */
+class ADS_EXPORT IFloatingWidget
+{
+public:
+ virtual ~IFloatingWidget() = default;
+
+ /**
+ * Starts floating.
+ * This function should get called typically from a mouse press event
+ * handler
+ */
+ virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
+ eDragState DragState, QWidget* MouseEventHandler) = 0;
+
+ /**
+ * Moves the widget to a new position relative to the position given when
+ * startFloating() was called.
+ * This function should be called from a mouse mouve event handler to
+ * move the floating widget on mouse move events.
+ */
+ virtual void moveFloating() = 0;
+
+ /**
+ * Tells the widget that to finish dragging if the mouse is released.
+ * This function should be called from a mouse release event handler
+ * to finish the dragging
+ */
+ virtual void finishDragging() = 0;
+};
+
+
+/**
+ * This implements a floating widget that is a dock container that accepts
+ * docking of dock widgets like the main window and that can be docked into
+ * another dock container.
+ * Every floating window of the docking system is a FloatingDockContainer.
+ */
+class ADS_EXPORT CFloatingDockContainer : public tFloatingWidgetBase, public IFloatingWidget
+{
+ Q_OBJECT
+private:
+ FloatingDockContainerPrivate* d; ///< private data (pimpl)
+ friend struct FloatingDockContainerPrivate;
+ friend class CDockManager;
+ friend struct DockManagerPrivate;
+ friend class CDockAreaTabBar;
+ friend struct DockWidgetTabPrivate;
+ friend class CDockWidgetTab;
+ friend class CDockAreaTitleBar;
+ friend struct DockAreaTitleBarPrivate;
+ friend class CDockWidget;
+ friend class CDockAreaWidget;
+ friend class CFloatingWidgetTitleBar;
+ friend class CDockContainerWidget;
+
+ /**
+ * Returns the floating widget that is transported in the mime data of
+ * a drag and drop operation started by startPlatformDrag() and nullptr,
+ * if the mime data does not contain a floating widget
+ */
+ static CFloatingDockContainer* floatingWidgetFromMimeData(const QMimeData* MimeData);
+
+ /**
+ * Records the drop candidate while a platform drag is hovering over a
+ * dock container. Called from CDockContainerWidget::dragMoveEvent().
+ * Some compositors (e.g. Mutter) do not deliver a drop event when the
+ * dragged window overlaps the drop target. startPlatformDrag() then docks
+ * the floating widget into the last recorded candidate, if the drag ended
+ * over a valid drop area
+ */
+ static void platformDragUpdateDropCandidate(CDockContainerWidget* Container,
+ const QPoint& GlobalPos, bool ValidDropArea);
+
+ /**
+ * Marks the platform drag drop as handled by a delivered drop event, so
+ * that startPlatformDrag() does not dock the floating widget a second time
+ */
+ static void platformDragNotifyDropHandled();
+
+ /**
+ * Wayland: returns the concatenated style sheets along the dock manager
+ * parent chain. A floating widget has no parent widget on Wayland, so it
+ * does not inherit the dock manager's effective style sheet through the
+ * widget hierarchy and gets this style sheet applied explicitly instead
+ * (an application wide qApp style sheet is still applied automatically by
+ * Qt and is therefore not included here). Used at construction and when
+ * the dock manager re-applies the style sheet after a style change.
+ */
+ static QString waylandInheritedStyleSheet(QWidget* DockManager);
+
+private Q_SLOTS:
+ void onDockAreasAddedOrRemoved();
+ void onDockAreaCurrentChanged(int Index);
+
+protected:
+ /**
+ * Starts floating at the given global position.
+ * Use moveToGlobalPos() to move the widget to a new position
+ * depending on the start position given in Pos parameter
+ */
+ virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
+ eDragState DragState, QWidget* MouseEventHandler) override;
+
+ /**
+ * Call this function if you explicitly want to signal that dragging has
+ * finished
+ */
+ virtual void finishDragging() override;
+
+ /**
+ * This function deletes all dock widgets in it.
+ * This functions should be called only from dock manager in its
+ * destructor before deleting the floating widget
+ */
+ void deleteContent();
+
+ /**
+ * Call this function if you just want to initialize the position
+ * and size of the floating widget
+ */
+ void initFloatingGeometry(const QPoint& DragStartMousePos, const QSize& Size)
+ {
+ startFloating(DragStartMousePos, Size, DraggingInactive, nullptr);
+ }
+
+ /**
+ * Moves the widget to a new position relative to the position given when
+ * startFloating() was called
+ */
+ void moveFloating() override;
+
+ /**
+ * Restores the state from given stream.
+ * If Testing is true, the function only parses the data from the given
+ * stream but does not restore anything. You can use this check for
+ * faulty files before you start restoring the state
+ */
+ bool restoreState(CDockingStateReader& Stream, bool Testing);
+
+ /**
+ * Call this function to update the window title
+ */
+ void updateWindowTitle();
+
+protected: // reimplements QWidget
+ virtual void changeEvent(QEvent *event) override;
+ virtual void closeEvent(QCloseEvent *event) override;
+ virtual void hideEvent(QHideEvent *event) override;
+ virtual void showEvent(QShowEvent *event) override;
+
+#ifdef Q_OS_MACOS
+ virtual bool event(QEvent *e) override;
+ 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;
+#endif
+
+#ifdef Q_OS_WIN
+ /**
+ * Native event filter for handling WM_MOVING messages on Windows
+ */
+#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
+ virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
+#else
+ virtual bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
+#endif
+#endif
+
+
+public:
+ using Super = tFloatingWidgetBase;
+
+ /**
+ * Create empty floating widget - required for restore state
+ */
+ CFloatingDockContainer(CDockManager* DockManager);
+
+ /**
+ * Create floating widget with the given dock area
+ */
+ CFloatingDockContainer(CDockAreaWidget* DockArea);
+
+ /**
+ * Create floating widget with the given dock widget
+ */
+ CFloatingDockContainer(CDockWidget* DockWidget);
+
+ /**
+ * Virtual Destructor
+ */
+ ~CFloatingDockContainer() override;
+
+ /**
+ * Access function for the internal dock container
+ */
+ CDockContainerWidget* dockContainer() const;
+
+ /**
+ * Call this function to start dragging the floating widget
+ */
+ void startDragging(const QPoint& DragStartMousePos, const QSize& Size,
+ QWidget* MouseEventHandler)
+ {
+ startFloating(DragStartMousePos, Size, DraggingFloatingWidget, MouseEventHandler);
+ }
+
+ /**
+ * Starts a compositor driven drag of the given floating widget on
+ * Wayland.
+ * Wayland neither reports the global cursor position nor allows clients
+ * to move top level windows, so the mouse tracked dragging that is used
+ * on the other platforms cannot work. Instead, this function executes a
+ * QDrag with the MIME types that QWaylandDataDevice translates into an
+ * xdg_toplevel_drag_v1 request, so the compositor moves the floating
+ * widget with the cursor. The CDockContainerWidget drag and drop event
+ * handlers show the drop overlays and dock the widget on drop.
+ * GlobalPressPos is the mouse press position in global coordinates and
+ * DragSource is the widget that received the mouse press event.
+ * DragOffset, when non-null, is the surface-local point of the floating
+ * widget that should stay under the cursor (the xdg_toplevel_drag attach
+ * offset). It must be supplied for a freshly created floating window: on
+ * Wayland such a window has no meaningful geometry yet, so deriving the
+ * offset from GlobalPressPos via mapFromGlobal() would place it randomly.
+ * When null (e.g. dragging an already-mapped floating window) the offset is
+ * derived from GlobalPressPos.
+ * The function blocks until the user drops or cancels the drag. It
+ * returns Qt::MoveAction, if the floating widget was docked into a
+ * drop area and Qt::IgnoreAction, if the floating widget was dropped
+ * outside of any drop area and remains floating.
+ */
+ static Qt::DropAction startPlatformDrag(CFloatingDockContainer* FloatingWidget,
+ const QPoint& GlobalPressPos, QWidget* DragSource,
+ const QPoint* DragOffset = nullptr);
+
+ /**
+ * Wayland hybrid drag helper, shared by the tab and the title bar drag
+ * paths. While the cursor stays inside SourceWindow the in-window Preview
+ * is moved to GlobalPos and this returns true. Once the cursor leaves
+ * SourceWindow the Preview is torn down without performing a drop and this
+ * returns false - the caller then creates the real floating widget and
+ * hands it to startPlatformDragForFloatingWidget(). Preview may be null.
+ */
+ static bool waylandMoveOrLeaveInWindowPreview(CFloatingDragPreview* Preview,
+ QWidget* SourceWindow, const QPoint& GlobalPos);
+
+ /**
+ * Wayland hybrid drag helper, shared by the tab and the title bar drag
+ * paths. Floats the freshly created FloatingWidget at the given Size and
+ * starts the compositor driven platform drag, keeping GrabOffset (the
+ * surface-local grab point) under the cursor. See startPlatformDrag() for
+ * why the offset is passed explicitly instead of being derived from the
+ * press position on Wayland.
+ */
+ static Qt::DropAction startPlatformDragForFloatingWidget(
+ IFloatingWidget* FloatingWidget, const QPoint& GrabOffset,
+ const QSize& Size, const QPoint& GlobalGrabPos, QWidget* DragSource);
+
+ /**
+ * This function returns true, if it can be closed.
+ * It can be closed, if all dock widgets in all dock areas can be closed
+ */
+ bool isClosable() const;
+
+ /**
+ * This function returns true, if this floating widget has only one single
+ * visible dock widget in a single visible dock area.
+ * The single dock widget is a real top level floating widget because no
+ * other widgets are docked.
+ */
+ bool hasTopLevelDockWidget() const;
+
+ /**
+ * This function returns the first dock widget in the first dock area.
+ * If the function hasSingleDockWidget() returns true, then this function
+ * returns this single dock widget.
+ */
+ CDockWidget* topLevelDockWidget() const;
+
+ /**
+ * This function returns a list of all dock widget in this floating widget.
+ * This is a simple convenience function that simply calls the dockWidgets()
+ * function of the internal container widget.
+ */
+ QList<CDockWidget*> dockWidgets() const;
+
+ /**
+ * This function hides the floating widget instantly and delete it later.
+ */
+ void finishDropOperation();
+
+ /**
+ * Returns true while this floating widget is actively being dragged.
+ */
+ bool isDraggingActive() const;
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ /**
+ * This is a function that responds to FloatingWidgetTitleBar::maximizeRequest()
+ * Maximize or normalize the container size.
+ */
+ void onMaximizeRequest();
+
+ /**
+ * Normalize (Unmaximize) the window.
+ * fixGeometry parameter fixes a "bug" in QT where immediately after calling showNormal
+ * geometry is not set properly.
+ * Set this true when moving the window immediately after normalizing.
+ */
+ void showNormal(bool fixGeometry=false);
+
+ /**
+ * Maximizes the window.
+ */
+ void showMaximized();
+
+ /**
+ * Returns if the window is currently maximized or not.
+ */
+ bool isMaximized() const;
+
+ /**
+ * Patched show to prevent the window from appearing in the taskbar.
+ */
+ void show();
+
+ /**
+ * Returns true if the floating widget has a native titlebar or false if
+ * the floating widget has a QWidget based title bar
+ */
+ bool hasNativeTitleBar();
+#endif
+}; // class FloatingDockContainer
+}
+ // namespace ads
+//-----------------------------------------------------------------------------
+#endif // FloatingDockContainerH
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDragPreview.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDragPreview.cpp
index f7a45a2b2..6b2c96d7e 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDragPreview.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDragPreview.cpp
@@ -45,6 +45,22 @@ struct FloatingDragPreviewPrivate
QPixmap ContentPreviewPixmap;
bool Canceled = false;
+ // Wayland hybrid drag: during the in-window phase, hit-testing and overlays
+ // are confined to this container and driven by an explicit, event-supplied
+ // global position instead of the unreliable QCursor::pos().
+ CDockContainerWidget* SourceContainer = nullptr;
+ QPoint LastGlobalPos;
+ bool HasLastGlobalPos = false;
+
+ /**
+ * Returns the last event-supplied global position when available (Wayland
+ * hybrid drag), otherwise the live cursor position.
+ */
+ QPoint cursorPos() const
+ {
+ return HasLastGlobalPos ? LastGlobalPos : QCursor::pos();
+ }
+
/**
* Private data constructor
@@ -123,21 +139,38 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos)
return;
}
- auto Containers = DockManager->dockContainers();
CDockContainerWidget *TopContainer = nullptr;
- for (auto ContainerWidget : Containers)
+ if (SourceContainer)
{
- if (!ContainerWidget->isVisible())
+ // Wayland in-window phase: the source container is the only candidate.
+ // This avoids relying on cross-window global coordinates (unreliable on
+ // Wayland) and keeps overlays from leaking onto other top-level windows.
+ if (SourceContainer->isVisible())
{
- continue;
+ QPoint MappedPos = SourceContainer->mapFromGlobal(GlobalPos);
+ if (SourceContainer->rect().contains(MappedPos))
+ {
+ TopContainer = SourceContainer;
+ }
}
-
- QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos);
- if (ContainerWidget->rect().contains(MappedPos))
+ }
+ else
+ {
+ auto Containers = DockManager->dockContainers();
+ for (auto ContainerWidget : Containers)
{
- if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer))
+ if (!ContainerWidget->isVisible())
+ {
+ continue;
+ }
+
+ QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos);
+ if (ContainerWidget->rect().contains(MappedPos))
{
- TopContainer = ContainerWidget;
+ if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer))
+ {
+ TopContainer = ContainerWidget;
+ }
}
}
}
@@ -157,8 +190,8 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos)
return;
}
- auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor();
- auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor();
+ auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor(GlobalPos);
+ auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor(GlobalPos);
int VisibleDockAreas = TopContainer->visibleDockAreaCount();
@@ -190,7 +223,7 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos)
{
DockAreaOverlay->enableDropPreview(true);
DockAreaOverlay->setAllowedAreas( (VisibleDockAreas == 1) ? NoDockWidgetArea : DockArea->allowedAreas());
- DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea);
+ DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea, GlobalPos);
// A CenterDockWidgetArea for the dockAreaOverlay() indicates that
// the mouse is in the title bar. If the ContainerArea is valid
@@ -205,7 +238,7 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos)
{
ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area);
}
- ContainerOverlay->showOverlay(TopContainer);
+ ContainerOverlay->showOverlay(TopContainer, GlobalPos);
}
else
{
@@ -218,7 +251,7 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos)
{
ContainerOverlay->setAllowedAreas(AutoHideDockAreas);
}
- ContainerOverlay->showOverlay(TopContainer);
+ ContainerOverlay->showOverlay(TopContainer, GlobalPos);
if (DockArea == ContentSourceArea && InvalidDockWidgetArea == ContainerDropArea)
@@ -276,8 +309,19 @@ void FloatingDragPreviewPrivate::createFloatingWidget()
//============================================================================
+// Wayland: in the frameless config, parent the preview to the source content's
+// top-level window so it renders as a translucent child instead of a Qt::Tool
+// top-level. Wayland refuses client-driven move() of top-levels in screen
+// coordinates; child widgets composite correctly on every backend. We parent to
+// Content->window() (the window the dragged widget/area currently lives in) and
+// NOT to parent->window(): parent is the dock manager, whose window is always
+// the main window, so a drag started in a floating window would otherwise show
+// the preview on the main window. Non-Wayland behavior is unchanged.
CFloatingDragPreview::CFloatingDragPreview(QWidget* Content, QWidget* parent) :
- QWidget(parent),
+ QWidget((internal::isWayland() && Content
+ && !CDockManager::testConfigFlag(CDockManager::DragPreviewHasWindowFrame))
+ ? Content->window()
+ : parent),
d(new FloatingDragPreviewPrivate(this))
{
d->Content = Content;
@@ -287,19 +331,32 @@ CFloatingDragPreview::CFloatingDragPreview(QWidget* Content, QWidget* parent) :
{
setWindowFlags(
Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ auto Flags = windowFlags();
+ Flags |= Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint;
+ setWindowFlags(Flags);
+#endif
+ }
+ else if (internal::isWayland())
+ {
+ // Translucent child of the source window. Transparent for mouse events
+ // so a release over a drop indicator falls through to it; positioning
+ // is driven by the grabbing tab/title-bar, not by this preview.
+ setAttribute(Qt::WA_NoSystemBackground);
+ setAttribute(Qt::WA_TranslucentBackground);
+ setAttribute(Qt::WA_TransparentForMouseEvents);
}
else
{
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TranslucentBackground);
- }
-
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
- auto Flags = windowFlags();
- Flags |= Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint;
- setWindowFlags(Flags);
+ auto Flags = windowFlags();
+ Flags |= Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint;
+ setWindowFlags(Flags);
#endif
+ }
// Create a static image of the widget that should get undocked
// This is like some kind preview image like it is uses in drag and drop
@@ -352,11 +409,53 @@ CFloatingDragPreview::~CFloatingDragPreview()
//============================================================================
void CFloatingDragPreview::moveFloating()
{
- int BorderSize = (frameSize().width() - size().width()) / 2;
- const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition
+ moveFloating(QCursor::pos());
+}
+
+
+//============================================================================
+void CFloatingDragPreview::moveFloating(const QPoint& GlobalPos)
+{
+ // Only stash the event-supplied position on Wayland, where QCursor::pos()
+ // is unreliable and finishDragging() must reuse it. On other platforms
+ // finishDragging() keeps using the live QCursor::pos() (unchanged behavior).
+ if (internal::isWayland())
+ {
+ d->LastGlobalPos = GlobalPos;
+ d->HasLastGlobalPos = true;
+ }
+ const int BorderSize = (frameSize().width() - size().width()) / 2;
+ const QPoint TargetGlobal = GlobalPos - d->DragStartMousePosition
- QPoint(BorderSize, 0);
- move(moveToPos);
- d->updateDropOverlays(QCursor::pos());
+ // When parented as a child (Wayland frameless), translate the screen-coord
+ // target into parent-local space so move() places us under the cursor.
+ if (isWindow() || !parentWidget())
+ {
+ move(TargetGlobal);
+ }
+ else
+ {
+ move(parentWidget()->mapFromGlobal(TargetGlobal));
+ }
+ d->updateDropOverlays(GlobalPos);
+}
+
+
+//============================================================================
+void CFloatingDragPreview::setSourceContainer(CDockContainerWidget* Container)
+{
+ d->SourceContainer = Container;
+}
+
+
+//============================================================================
+void CFloatingDragPreview::cancelDraggingSilently()
+{
+ // Tear down without performing a drop and without emitting draggingCanceled.
+ d->Canceled = true;
+ d->DockManager->containerOverlay()->hideOverlay();
+ d->DockManager->dockAreaOverlay()->hideOverlay();
+ close();
}
@@ -370,7 +469,14 @@ void CFloatingDragPreview::startFloating(const QPoint &DragStartMousePos,
d->DragStartMousePosition = DragStartMousePos;
moveFloating();
show();
-
+ if (internal::isWayland())
+ {
+ // On Wayland the preview is a child widget of the source window; raise
+ // it above its siblings. On other platforms it is a Qt::Tool window
+ // that is already kept on top, so raising is unnecessary here (keeps
+ // non-Wayland behavior unchanged).
+ raise();
+ }
}
@@ -379,8 +485,9 @@ void CFloatingDragPreview::finishDragging()
{
ADS_PRINT("CFloatingDragPreview::finishDragging");
- auto DockDropArea = d->DockManager->dockAreaOverlay()->visibleDropAreaUnderCursor();
- auto ContainerDropArea = d->DockManager->containerOverlay()->visibleDropAreaUnderCursor();
+ const QPoint GlobalPos = d->cursorPos();
+ auto DockDropArea = d->DockManager->dockAreaOverlay()->visibleDropAreaUnderCursor(GlobalPos);
+ auto ContainerDropArea = d->DockManager->containerOverlay()->visibleDropAreaUnderCursor(GlobalPos);
bool ValidDropArea = (DockDropArea != InvalidDockWidgetArea) || (ContainerDropArea != InvalidDockWidgetArea);
// Non floatable auto hide widgets should stay in its current auto hide
@@ -396,7 +503,7 @@ void CFloatingDragPreview::finishDragging()
}
else if (DockDropArea != InvalidDockWidgetArea)
{
- d->DropContainer->dropWidget(d->Content, DockDropArea, d->DropContainer->dockAreaAt(QCursor::pos()),
+ d->DropContainer->dropWidget(d->Content, DockDropArea, d->DropContainer->dockAreaAt(GlobalPos),
d->DockManager->dockAreaOverlay()->tabIndexUnderCursor());
}
else if (ContainerDropArea != InvalidDockWidgetArea)
@@ -406,7 +513,7 @@ void CFloatingDragPreview::finishDragging()
// then we tabify the dropped widget into the only visible dock area
if (d->DropContainer->visibleDockAreaCount() <= 1 && CenterDockWidgetArea == ContainerDropArea)
{
- DockArea = d->DropContainer->dockAreaAt(QCursor::pos());
+ DockArea = d->DropContainer->dockAreaAt(GlobalPos);
}
d->DropContainer->dropWidget(d->Content, ContainerDropArea, DockArea,
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDragPreview.h b/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDragPreview.h
index 68e3e5cf9..a07988094 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDragPreview.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/FloatingDragPreview.h
@@ -17,6 +17,7 @@ namespace ads
{
class CDockWidget;
class CDockAreaWidget;
+class CDockContainerWidget;
struct FloatingDragPreviewPrivate;
/**
@@ -85,6 +86,28 @@ public: // implements IFloatingWidget -----------------------------------------
*/
virtual void moveFloating() override;
+ /**
+ * Wayland hybrid drag: move the preview using an explicit global position
+ * supplied by the grabbing tab/title-bar mouse event instead of
+ * QCursor::pos(), which is unreliable on Wayland. Also drives the drop
+ * overlays from the supplied position.
+ */
+ void moveFloating(const QPoint& GlobalPos);
+
+ /**
+ * Wayland hybrid drag: confine drop-target hit-testing and overlays to a
+ * single source container during the in-window phase, so nothing leaks to
+ * other top-level windows and no cross-window global coordinate is needed.
+ */
+ void setSourceContainer(CDockContainerWidget* Container);
+
+ /**
+ * Wayland hybrid drag: tear the preview down without performing a drop and
+ * without emitting draggingCanceled. Used when the in-window drag converts
+ * to a native platform drag on a window-boundary cross.
+ */
+ void cancelDraggingSilently();
+
/**
* Finishes dragging.
* Hides the dock overlays and executes the real undocking and docking
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/ads.qrc b/scribus/third_party/Qt-Advanced-Docking-System/src/ads.qrc
index 307e93b1f..dad98f91a 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/ads.qrc
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/ads.qrc
@@ -23,5 +23,28 @@
<file>images/minimize-button.svg</file>
<file>images/minimize-button-focused.svg</file>
<file>images/vs-pin-button-disabled.svg</file>
+ <file>stylesheets/default_dark.css</file>
+ <file>images/close-button_dark.svg</file>
+ <file>images/pin-button_dark.svg</file>
+ <file>images/close-button-disabled_dark.svg</file>
+ <file>stylesheets/default_linux_dark.css</file>
+ <file>images/close-button-focused_dark.svg</file>
+ <file>stylesheets/focus_highlighting_dark.css</file>
+ <file>stylesheets/focus_highlighting_linux_dark.css</file>
+ <file>images/tabs-menu-button_dark.svg</file>
+ <file>images/detach-button_dark.svg</file>
+ <file>images/detach-button-disabled_dark.svg</file>
+ <file>images/maximize-button_dark.svg</file>
+ <file>images/maximize-button-focused_dark.svg</file>
+ <file>images/restore-button_dark.svg</file>
+ <file>images/restore-button-focused_dark.svg</file>
+ <file>images/vs-pin-button_dark.svg</file>
+ <file>images/vs-pin-button-pinned_dark.svg</file>
+ <file>images/vs-pin-button-pinned-focused_dark.svg</file>
+ <file>images/vs-pin-button_45_dark.svg</file>
+ <file>images/pin-button-big_dark.svg</file>
+ <file>images/minimize-button_dark.svg</file>
+ <file>images/minimize-button-focused_dark.svg</file>
+ <file>images/vs-pin-button-disabled_dark.svg</file>
</qresource>
</RCC>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/ads_globals.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/ads_globals.cpp
index 7d3cf7e6f..13beca5b8 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/ads_globals.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/ads_globals.cpp
@@ -32,6 +32,7 @@
#include <QPainter>
#include <QAbstractButton>
#include <QStyle>
+#include <QGuiApplication>
#include "DockSplitter.h"
#include "DockManager.h"
@@ -283,7 +284,7 @@ QString detectWindowManagerX11()
}
if(sup_windows.length() == 0)
{
- ADS_PRINT("Failed to get the supporting window on non EWMH comform WM.");
+ ADS_PRINT("Failed to get the supporting window on non EWMH conform WM.");
return "UNKNOWN";
}
support_win = sup_windows[0];
@@ -374,6 +375,14 @@ bool isSideBarArea(DockWidgetArea Area)
}
+//============================================================================
+bool isWayland()
+{
+ return QGuiApplication::platformName().startsWith(
+ QLatin1String("wayland"), Qt::CaseInsensitive);
+}
+
+
//============================================================================
QPixmap createTransparentPixmap(const QPixmap& Source, qreal Opacity)
{
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/ads_globals.h b/scribus/third_party/Qt-Advanced-Docking-System/src/ads_globals.h
index 0de464b92..42150912c 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/ads_globals.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/ads_globals.h
@@ -158,7 +158,7 @@ enum SideBarLocation
SideBarBottom,
SideBarNone
};
-Q_ENUMS(SideBarLocation);
+Q_ENUMS(SideBarLocation)
namespace internal
@@ -229,6 +229,15 @@ public:
CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area);
+/**
+ * Returns true, if the application runs on the Wayland display server
+ * protocol. Wayland does not allow clients to move top level windows in
+ * screen coordinates or to query the global cursor position, so docking
+ * requires a different implementation on Wayland.
+ */
+bool isWayland();
+
+
/**
* Returns the SieBarLocation for the AutoHide dock widget areas
*/
@@ -236,7 +245,7 @@ SideBarLocation toSideBarLocation(DockWidgetArea Area);
/**
- * Returns true for the top or bottom side bar ansd false for the
+ * Returns true for the top or bottom side bar and false for the
* left and right side bar
*/
bool isHorizontalSideBarLocation(SideBarLocation Location);
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/close-button-disabled_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/close-button-disabled_dark.svg
new file mode 100644
index 000000000..9ff5e4377
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/close-button-disabled_dark.svg
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docname="close-button-disabled.svg"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ version="1.1"
+ id="svg2"
+ viewBox="0 0 16 16"
+ height="16px"
+ width="16px">
+ <style
+ id="style2"></style>
+ <defs
+ id="defs4">
+ <pattern
+ id="EMFhbasepattern"
+ patternUnits="userSpaceOnUse"
+ width="6"
+ height="6"
+ x="0"
+ y="0" />
+ <pattern
+ id="EMFhbasepattern-4"
+ patternUnits="userSpaceOnUse"
+ width="6"
+ height="6"
+ x="0"
+ y="0" />
+ <pattern
+ id="EMFhbasepattern-3"
+ patternUnits="userSpaceOnUse"
+ width="6"
+ height="6"
+ x="0"
+ y="0" />
+ <pattern
+ id="EMFhbasepattern-8"
+ patternUnits="userSpaceOnUse"
+ width="6"
+ height="6"
+ x="0"
+ y="0" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:guide-bbox="true"
+ showguides="true"
+ inkscape:document-rotation="0"
+ inkscape:snap-global="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:bbox-nodes="true"
+ inkscape:bbox-paths="true"
+ inkscape:snap-bbox="true"
+ inkscape:window-maximized="1"
+ inkscape:window-y="-8"
+ inkscape:window-x="1912"
+ inkscape:window-height="1017"
+ inkscape:window-width="1920"
+ units="px"
+ showgrid="true"
+ inkscape:current-layer="g5228"
+ inkscape:document-units="px"
+ inkscape:cy="13.17691"
+ inkscape:cx="6.2316889"
+ inkscape:zoom="22.627417"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base">
+ <inkscape:grid
+ id="grid3336"
+ type="xygrid" />
+ <sodipodi:guide
+ id="guide883"
+ orientation="1,0"
+ position="4,10" />
+ <sodipodi:guide
+ id="guide885"
+ orientation="0,-1"
+ position="10,12" />
+ <sodipodi:guide
+ id="guide887"
+ orientation="1,0"
+ position="12,2" />
+ <sodipodi:guide
+ id="guide889"
+ orientation="0,-1"
+ position="14,4" />
+ </sodipodi:namedview>
+ <g
+ transform="translate(0,-1036.3622)"
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1">
+ <g
+ id="g5228"
+ transform="translate(628,-140.49998)">
+ <path
+ id="path846"
+ style="color:#FFFFFF;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#FFFFFF;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#FFFFFF;solid-opacity:1;vector-effect:none;fill:#707070;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#FFFFFF;stop-opacity:1;opacity:1"
+ d="M 4.4765625 4.0019531 A 0.5 0.5 0 0 0 4.1464844 4.1464844 A 0.5 0.5 0 0 0 4.1464844 4.8535156 L 7.2929688 8 L 4.1464844 11.146484 A 0.5 0.5 0 0 0 4.1464844 11.853516 A 0.5 0.5 0 0 0 4.8535156 11.853516 L 8 8.7070312 L 11.146484 11.853516 A 0.5 0.5 0 0 0 11.853516 11.853516 A 0.5 0.5 0 0 0 11.853516 11.146484 L 8.7070312 8 L 11.853516 4.8535156 A 0.5 0.5 0 0 0 11.853516 4.1464844 A 0.5 0.5 0 0 0 11.476562 4.0019531 A 0.5 0.5 0 0 0 11.146484 4.1464844 L 8 7.2929688 L 4.8535156 4.1464844 A 0.5 0.5 0 0 0 4.4765625 4.0019531 z "
+ transform="translate(-628,1176.8622)" />
+ </g>
+ </g>
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <rdf:Description
+ dc:language="en"
+ dc:format="image/svg+xml"
+ dc:date="2016-12-14"
+ dc:publisher="Iconscout"
+ dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ about="https://iconscout.com/legal#licenses">
+ <dc:creator>
+ <rdf:Bag>
+ <rdf:li>Jemis Mali</rdf:li>
+ </rdf:Bag>
+ </dc:creator>
+ </rdf:Description>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+</svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/close-button-focused_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/close-button-focused_dark.svg
new file mode 100644
index 000000000..b9a6fad93
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/close-button-focused_dark.svg
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docname="close-button-focused.svg"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ version="1.1"
+ id="svg2"
+ viewBox="0 0 16 16"
+ height="16px"
+ width="16px">
+ <style
+ id="style2"></style>
+ <defs
+ id="defs4">
+ <pattern
+ id="EMFhbasepattern"
+ patternUnits="userSpaceOnUse"
+ width="6"
+ height="6"
+ x="0"
+ y="0" />
+ <pattern
+ id="EMFhbasepattern-4"
+ patternUnits="userSpaceOnUse"
+ width="6"
+ height="6"
+ x="0"
+ y="0" />
+ <pattern
+ id="EMFhbasepattern-3"
+ patternUnits="userSpaceOnUse"
+ width="6"
+ height="6"
+ x="0"
+ y="0" />
+ <pattern
+ id="EMFhbasepattern-8"
+ patternUnits="userSpaceOnUse"
+ width="6"
+ height="6"
+ x="0"
+ y="0" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:guide-bbox="true"
+ showguides="true"
+ inkscape:document-rotation="0"
+ inkscape:snap-global="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:bbox-nodes="true"
+ inkscape:bbox-paths="true"
+ inkscape:snap-bbox="true"
+ inkscape:window-maximized="1"
+ inkscape:window-y="-8"
+ inkscape:window-x="-8"
+ inkscape:window-height="1017"
+ inkscape:window-width="1920"
+ units="px"
+ showgrid="true"
+ inkscape:current-layer="g5228"
+ inkscape:document-units="px"
+ inkscape:cy="13.17691"
+ inkscape:cx="6.2316889"
+ inkscape:zoom="22.627417"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base">
+ <inkscape:grid
+ id="grid3336"
+ type="xygrid" />
+ <sodipodi:guide
+ id="guide883"
+ orientation="1,0"
+ position="4,10" />
+ <sodipodi:guide
+ id="guide885"
+ orientation="0,-1"
+ position="10,12" />
+ <sodipodi:guide
+ id="guide887"
+ orientation="1,0"
+ position="12,2" />
+ <sodipodi:guide
+ id="guide889"
+ orientation="0,-1"
+ position="14,4" />
+ </sodipodi:namedview>
+ <g
+ transform="translate(0,-1036.3622)"
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1">
+ <g
+ id="g5228"
+ transform="translate(628,-140.49998)">
+ <path
+ id="path846"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1"
+ d="M 4.4765625 4.0019531 A 0.5 0.5 0 0 0 4.1464844 4.1464844 A 0.5 0.5 0 0 0 4.1464844 4.8535156 L 7.2929688 8 L 4.1464844 11.146484 A 0.5 0.5 0 0 0 4.1464844 11.853516 A 0.5 0.5 0 0 0 4.8535156 11.853516 L 8 8.7070312 L 11.146484 11.853516 A 0.5 0.5 0 0 0 11.853516 11.853516 A 0.5 0.5 0 0 0 11.853516 11.146484 L 8.7070312 8 L 11.853516 4.8535156 A 0.5 0.5 0 0 0 11.853516 4.1464844 A 0.5 0.5 0 0 0 11.476562 4.0019531 A 0.5 0.5 0 0 0 11.146484 4.1464844 L 8 7.2929688 L 4.8535156 4.1464844 A 0.5 0.5 0 0 0 4.4765625 4.0019531 z "
+ transform="translate(-628,1176.8622)" />
+ </g>
+ </g>
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <rdf:Description
+ dc:language="en"
+ dc:format="image/svg+xml"
+ dc:date="2016-12-14"
+ dc:publisher="Iconscout"
+ dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ about="https://iconscout.com/legal#licenses">
+ <dc:creator>
+ <rdf:Bag>
+ <rdf:li>Jemis Mali</rdf:li>
+ </rdf:Bag>
+ </dc:creator>
+ </rdf:Description>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+</svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/close-button_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/close-button_dark.svg
new file mode 100644
index 000000000..5b3f282b0
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/close-button_dark.svg
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16px"
+ height="16px"
+ viewBox="0 0 16 16"
+ id="svg2"
+ version="1.1"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ sodipodi:docname="close-button2.svg">
+ <style
+ id="style2"></style>
+ <defs
+ id="defs4">
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-4" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-3" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-8" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.627417"
+ inkscape:cx="6.2316889"
+ inkscape:cy="13.17691"
+ inkscape:document-units="px"
+ inkscape:current-layer="g5228"
+ showgrid="true"
+ units="px"
+ inkscape:window-width="1920"
+ inkscape:window-height="1017"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-global="true"
+ inkscape:document-rotation="0"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3336" />
+ <sodipodi:guide
+ position="4,10"
+ orientation="1,0"
+ id="guide883" />
+ <sodipodi:guide
+ position="10,12"
+ orientation="0,-1"
+ id="guide885" />
+ <sodipodi:guide
+ position="12,2"
+ orientation="1,0"
+ id="guide887" />
+ <sodipodi:guide
+ position="14,4"
+ orientation="0,-1"
+ id="guide889" />
+ </sodipodi:namedview>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <g
+ transform="translate(628,-140.49998)"
+ id="g5228">
+ <path
+ transform="translate(-628,1176.8622)"
+ d="M 4.4765625 4.0019531 A 0.5 0.5 0 0 0 4.1464844 4.1464844 A 0.5 0.5 0 0 0 4.1464844 4.8535156 L 7.2929688 8 L 4.1464844 11.146484 A 0.5 0.5 0 0 0 4.1464844 11.853516 A 0.5 0.5 0 0 0 4.8535156 11.853516 L 8 8.7070312 L 11.146484 11.853516 A 0.5 0.5 0 0 0 11.853516 11.853516 A 0.5 0.5 0 0 0 11.853516 11.146484 L 8.7070312 8 L 11.853516 4.8535156 A 0.5 0.5 0 0 0 11.853516 4.1464844 A 0.5 0.5 0 0 0 11.476562 4.0019531 A 0.5 0.5 0 0 0 11.146484 4.1464844 L 8 7.2929688 L 4.8535156 4.1464844 A 0.5 0.5 0 0 0 4.4765625 4.0019531 z "
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1"
+ id="path846" />
+ </g>
+ </g>
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <rdf:Description
+ about="https://iconscout.com/legal#licenses"
+ dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:publisher="Iconscout"
+ dc:date="2016-12-14"
+ dc:format="image/svg+xml"
+ dc:language="en">
+ <dc:creator>
+ <rdf:Bag>
+ <rdf:li>Jemis Mali</rdf:li>
+ </rdf:Bag>
+ </dc:creator>
+ </rdf:Description>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+</svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/detach-button-disabled_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/detach-button-disabled_dark.svg
new file mode 100644
index 000000000..82616c6b2
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/detach-button-disabled_dark.svg
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16px"
+ height="16px"
+ viewBox="0 0 16 16"
+ id="svg2"
+ version="1.1"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ sodipodi:docname="detach-button-disabled.svg">
+ <style
+ id="style2"></style>
+ <defs
+ id="defs4">
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-4" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-3" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-8" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-2" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-9" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-4-8" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-3-7" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-8-0" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-41" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-4-5" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-3-0" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-8-2" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.627417"
+ inkscape:cx="6.2316889"
+ inkscape:cy="12.734968"
+ inkscape:document-units="px"
+ inkscape:current-layer="g5228"
+ showgrid="true"
+ units="px"
+ inkscape:window-width="1920"
+ inkscape:window-height="1017"
+ inkscape:window-x="1912"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-global="true"
+ inkscape:document-rotation="0"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3336" />
+ <sodipodi:guide
+ position="4,10"
+ orientation="1,0"
+ id="guide883" />
+ <sodipodi:guide
+ position="10,12"
+ orientation="0,-1"
+ id="guide885" />
+ <sodipodi:guide
+ position="12,2"
+ orientation="1,0"
+ id="guide887" />
+ <sodipodi:guide
+ position="14,4"
+ orientation="0,-1"
+ id="guide889" />
+ </sodipodi:namedview>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <g
+ transform="translate(628,-140.49998)"
+ id="g5228">
+ <path
+ id="path893"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#707070;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:9.2;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
+ d="m -622,1179.8622 v 0.5 1.5 1 h -2 v 0.5 1.5 4 h 6 v -3 h 2 v -4 -2 z m 1,2 h 4 v 3 h -1 v -2 h -3 z m -2,3 h 4 v 3 h -4 z" />
+ </g>
+ </g>
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <rdf:Description
+ about="https://iconscout.com/legal#licenses"
+ dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:publisher="Iconscout"
+ dc:date="2016-12-14"
+ dc:format="image/svg+xml"
+ dc:language="en">
+ <dc:creator>
+ <rdf:Bag>
+ <rdf:li>Jemis Mali</rdf:li>
+ </rdf:Bag>
+ </dc:creator>
+ </rdf:Description>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <style
+ id="style2-3" />
+ <style
+ id="style2-1" />
+</svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/detach-button_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/detach-button_dark.svg
new file mode 100644
index 000000000..d8f6f3af5
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/detach-button_dark.svg
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16px"
+ height="16px"
+ viewBox="0 0 16 16"
+ id="svg2"
+ version="1.1"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ sodipodi:docname="detach-button.svg">
+ <style
+ id="style2"></style>
+ <defs
+ id="defs4">
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-4" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-3" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-8" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-2" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-9" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-4-8" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-3-7" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-8-0" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.627417"
+ inkscape:cx="6.2316889"
+ inkscape:cy="12.734968"
+ inkscape:document-units="px"
+ inkscape:current-layer="g5228"
+ showgrid="true"
+ units="px"
+ inkscape:window-width="1920"
+ inkscape:window-height="1017"
+ inkscape:window-x="1912"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-global="true"
+ inkscape:document-rotation="0"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3336" />
+ <sodipodi:guide
+ position="4,10"
+ orientation="1,0"
+ id="guide883" />
+ <sodipodi:guide
+ position="10,12"
+ orientation="0,-1"
+ id="guide885" />
+ <sodipodi:guide
+ position="12,2"
+ orientation="1,0"
+ id="guide887" />
+ <sodipodi:guide
+ position="14,4"
+ orientation="0,-1"
+ id="guide889" />
+ </sodipodi:namedview>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <g
+ transform="translate(628,-140.49998)"
+ id="g5228">
+ <path
+ id="path893"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:9.2;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
+ d="m -622,1179.8622 v 0.5 1.5 1 h -2 v 0.5 1.5 4 h 6 v -3 h 2 v -4 -2 z m 1,2 h 4 v 3 h -1 v -2 h -3 z m -2,3 h 4 v 3 h -4 z" />
+ </g>
+ </g>
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <rdf:Description
+ about="https://iconscout.com/legal#licenses"
+ dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:publisher="Iconscout"
+ dc:date="2016-12-14"
+ dc:format="image/svg+xml"
+ dc:language="en">
+ <dc:creator>
+ <rdf:Bag>
+ <rdf:li>Jemis Mali</rdf:li>
+ </rdf:Bag>
+ </dc:creator>
+ </rdf:Description>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <style
+ id="style2-3" />
+</svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/maximize-button-focused_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/maximize-button-focused_dark.svg
new file mode 100644
index 000000000..cdbb56d4d
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/maximize-button-focused_dark.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16px"
+ height="16px"
+ viewBox="0 0 16 16"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
+ sodipodi:docname="maximize-button-focused.svg">
+ <style
+ id="style2" />
+ <defs
+ id="defs4">
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-4" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-3" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-8" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="32"
+ inkscape:cx="-7.4143106"
+ inkscape:cy="6.591104"
+ inkscape:document-units="px"
+ inkscape:current-layer="g5228"
+ showgrid="true"
+ units="px"
+ inkscape:window-width="1848"
+ inkscape:window-height="920"
+ inkscape:window-x="72"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-global="true"
+ inkscape:document-rotation="0"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3336" />
+ <sodipodi:guide
+ position="4,10"
+ orientation="1,0"
+ id="guide883"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="10,12"
+ orientation="0,-1"
+ id="guide885"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="12,2"
+ orientation="1,0"
+ id="guide887"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="14,4"
+ orientation="0,-1"
+ id="guide889"
+ inkscape:locked="false" />
+ </sodipodi:namedview>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <g
+ transform="translate(628,-140.49998)"
+ id="g5228">
+ <rect
+ id="rect4094"
+ width="7"
+ height="7"
+ x="-623.5"
+ y="1181.3622"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
+ </g>
+ </g>
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <rdf:Description
+ about="https://iconscout.com/legal#licenses"
+ dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:publisher="Iconscout"
+ dc:date="2016-12-14"
+ dc:format="image/svg+xml"
+ dc:language="en">
+ <dc:creator>
+ <rdf:Bag>
+ <rdf:li>Jemis Mali</rdf:li>
+ </rdf:Bag>
+ </dc:creator>
+ </rdf:Description>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+</svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/maximize-button_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/maximize-button_dark.svg
new file mode 100644
index 000000000..4dc165ebc
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/maximize-button_dark.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16px"
+ height="16px"
+ viewBox="0 0 16 16"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
+ sodipodi:docname="maximize-button.svg">
+ <style
+ id="style2" />
+ <defs
+ id="defs4">
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-4" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-3" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-8" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="32"
+ inkscape:cx="-1.8674356"
+ inkscape:cy="6.591104"
+ inkscape:document-units="px"
+ inkscape:current-layer="g5228"
+ showgrid="true"
+ units="px"
+ inkscape:window-width="1848"
+ inkscape:window-height="920"
+ inkscape:window-x="72"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-global="true"
+ inkscape:document-rotation="0"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3336" />
+ <sodipodi:guide
+ position="4,10"
+ orientation="1,0"
+ id="guide883"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="10,12"
+ orientation="0,-1"
+ id="guide885"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="12,2"
+ orientation="1,0"
+ id="guide887"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="14,4"
+ orientation="0,-1"
+ id="guide889"
+ inkscape:locked="false" />
+ </sodipodi:namedview>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <g
+ transform="translate(628,-140.49998)"
+ id="g5228">
+ <rect
+ id="rect4094"
+ width="7"
+ height="7"
+ x="-623.5"
+ y="1181.3622"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
+ </g>
+ </g>
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <rdf:Description
+ about="https://iconscout.com/legal#licenses"
+ dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:publisher="Iconscout"
+ dc:date="2016-12-14"
+ dc:format="image/svg+xml"
+ dc:language="en">
+ <dc:creator>
+ <rdf:Bag>
+ <rdf:li>Jemis Mali</rdf:li>
+ </rdf:Bag>
+ </dc:creator>
+ </rdf:Description>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+</svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/minimize-button-focused_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/minimize-button-focused_dark.svg
new file mode 100644
index 000000000..c473a1333
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/minimize-button-focused_dark.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16" height="16" enable-background="new 0 0 122.879 122.867" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="4" y="10" width="7" height="2" fill="#fff"/><style/><style/><style/><style/></svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/minimize-button_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/minimize-button_dark.svg
new file mode 100644
index 000000000..8c3aed764
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/minimize-button_dark.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16" height="16" enable-background="new 0 0 122.879 122.867" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="4" y="10" width="7" height="2" fill="#ffffff"/></svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/pin-button-big_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/pin-button-big_dark.svg
new file mode 100644
index 000000000..c99d4ba25
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/pin-button-big_dark.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16" height="16" enable-background="new 0 0 122.879 122.867" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(.12293 0 0 .12294 .39712 .49812)" fill="#000000" stroke="#ffffff" stroke-width="8.1347"><path d="m83.88 0.451 38.547 38.549c0.603 0.601 0.603 1.585 0 2.188l-13.128 13.125c-0.602 0.604-1.586 0.604-2.187 0l-3.732-3.73-17.303 17.3c3.882 14.621 0.095 30.857-11.37 42.32-0.266 0.268-0.535 0.529-0.808 0.787-1.004 0.955-0.843 0.949-1.813-0.021l-24.489-24.489-47.597 36.387 36.399-47.584-24.525-24.523c-0.978-0.98-0.896-0.826 0.066-1.837 0.24-0.251 0.485-0.503 0.734-0.753 11.463-11.463 27.702-15.253 42.322-11.37l17.301-17.3-3.733-3.732c-0.601-0.601-0.601-1.585 0-2.188l13.127-13.129c0.604-0.601 1.588-0.601 2.189 0z" clip-rule="evenodd" fill="#000000" fill-rule="evenodd" stroke="#ffffff" stroke-width="8.1347"/></g></svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/pin-button_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/pin-button_dark.svg
new file mode 100644
index 000000000..73c688579
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/pin-button_dark.svg
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ enable-background="new 0 0 122.879 122.867"
+ xml:space="preserve"
+ sodipodi:docname="pin-button-inkscape.svg"
+ inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"><metadata
+ id="metadata53"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs51" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1017"
+ id="namedview49"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="19.037734"
+ inkscape:cx="4.5643376"
+ inkscape:cy="2.7353223"
+ inkscape:window-x="1912"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="Layer_1" /><g
+ id="g46"
+ transform="matrix(0.08138071,0,0,0.08138898,3.0000001,2.99998)"><path
+ fill="#ffffff"
+ fill-rule="evenodd"
+ clip-rule="evenodd"
+ d="M 83.88,0.451 122.427,39 c 0.603,0.601 0.603,1.585 0,2.188 l -13.128,13.125 c -0.602,0.604 -1.586,0.604 -2.187,0 l -3.732,-3.73 -17.303,17.3 c 3.882,14.621 0.095,30.857 -11.37,42.32 -0.266,0.268 -0.535,0.529 -0.808,0.787 -1.004,0.955 -0.843,0.949 -1.813,-0.021 L 47.597,86.48 0,122.867 36.399,75.283 11.874,50.76 C 10.896,49.78 10.978,49.934 11.94,48.923 12.18,48.672 12.425,48.42 12.674,48.17 24.137,36.707 40.376,32.917 54.996,36.8 L 72.297,19.5 68.564,15.768 c -0.601,-0.601 -0.601,-1.585 0,-2.188 L 81.691,0.451 c 0.604,-0.601 1.588,-0.601 2.189,0 z"
+ id="path44" /></g></svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/restore-button-focused_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/restore-button-focused_dark.svg
new file mode 100644
index 000000000..45b32e9b5
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/restore-button-focused_dark.svg
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16px"
+ height="16px"
+ viewBox="0 0 16 16"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
+ sodipodi:docname="restore-button-focused.svg">
+ <style
+ id="style2" />
+ <defs
+ id="defs4">
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-4" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-3" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-8" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="32"
+ inkscape:cx="3.6794394"
+ inkscape:cy="7.841104"
+ inkscape:document-units="px"
+ inkscape:current-layer="g5228"
+ showgrid="true"
+ units="px"
+ inkscape:window-width="1848"
+ inkscape:window-height="920"
+ inkscape:window-x="72"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-global="true"
+ inkscape:document-rotation="0"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3336" />
+ <sodipodi:guide
+ position="4,10"
+ orientation="1,0"
+ id="guide883"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="10,12"
+ orientation="0,-1"
+ id="guide885"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="12,2"
+ orientation="1,0"
+ id="guide887"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="14,4"
+ orientation="0,-1"
+ id="guide889"
+ inkscape:locked="false" />
+ </sodipodi:namedview>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <g
+ transform="translate(628,-140.49998)"
+ id="g5228">
+ <rect
+ id="rect4094"
+ width="5.055603"
+ height="5.0555329"
+ x="-623.5556"
+ y="1183.3622"
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -621.98958,1181.3414 h 5.51042 v 5.4999"
+ id="path6127"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <rdf:Description
+ about="https://iconscout.com/legal#licenses"
+ dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:publisher="Iconscout"
+ dc:date="2016-12-14"
+ dc:format="image/svg+xml"
+ dc:language="en">
+ <dc:creator>
+ <rdf:Bag>
+ <rdf:li>Jemis Mali</rdf:li>
+ </rdf:Bag>
+ </dc:creator>
+ </rdf:Description>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+</svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/restore-button_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/restore-button_dark.svg
new file mode 100644
index 000000000..d6fd5059c
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/restore-button_dark.svg
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16px"
+ height="16px"
+ viewBox="0 0 16 16"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
+ sodipodi:docname="restore-button.svg">
+ <style
+ id="style2" />
+ <defs
+ id="defs4">
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-4" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-3" />
+ <pattern
+ y="0"
+ x="0"
+ height="6"
+ width="6"
+ patternUnits="userSpaceOnUse"
+ id="EMFhbasepattern-8" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="32"
+ inkscape:cx="3.6794394"
+ inkscape:cy="7.841104"
+ inkscape:document-units="px"
+ inkscape:current-layer="g5228"
+ showgrid="true"
+ units="px"
+ inkscape:window-width="1848"
+ inkscape:window-height="920"
+ inkscape:window-x="72"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-global="true"
+ inkscape:document-rotation="0"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3336" />
+ <sodipodi:guide
+ position="4,10"
+ orientation="1,0"
+ id="guide883"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="10,12"
+ orientation="0,-1"
+ id="guide885"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="12,2"
+ orientation="1,0"
+ id="guide887"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="14,4"
+ orientation="0,-1"
+ id="guide889"
+ inkscape:locked="false" />
+ </sodipodi:namedview>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <g
+ transform="translate(628,-140.49998)"
+ id="g5228">
+ <rect
+ id="rect4094"
+ width="5.055603"
+ height="5.0555329"
+ x="-623.5556"
+ y="1183.3622"
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -621.98958,1181.3414 h 5.51042 v 5.4999"
+ id="path6127"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <rdf:Description
+ about="https://iconscout.com/legal#licenses"
+ dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:publisher="Iconscout"
+ dc:date="2016-12-14"
+ dc:format="image/svg+xml"
+ dc:language="en">
+ <dc:creator>
+ <rdf:Bag>
+ <rdf:li>Jemis Mali</rdf:li>
+ </rdf:Bag>
+ </dc:creator>
+ </rdf:Description>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+</svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/tabs-menu-button_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/tabs-menu-button_dark.svg
new file mode 100644
index 000000000..d5e2e2b44
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/tabs-menu-button_dark.svg
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docname="tabs-menu-button.svg"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ version="1.1"
+ id="svg2"
+ viewBox="0 0 16 16"
+ height="16px"
+ width="16px">
+ <style
+ id="style2"></style>
+ <defs
+ id="defs4">
+ <pattern
+ id="EMFhbasepattern"
+ patternUnits="userSpaceOnUse"
+ width="6"
+ height="6"
+ x="0"
+ y="0" />
+ <pattern
+ id="EMFhbasepattern-4"
+ patternUnits="userSpaceOnUse"
+ width="6"
+ height="6"
+ x="0"
+ y="0" />
+ <pattern
+ id="EMFhbasepattern-3"
+ patternUnits="userSpaceOnUse"
+ width="6"
+ height="6"
+ x="0"
+ y="0" />
+ <pattern
+ id="EMFhbasepattern-8"
+ patternUnits="userSpaceOnUse"
+ width="6"
+ height="6"
+ x="0"
+ y="0" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:guide-bbox="true"
+ showguides="true"
+ inkscape:document-rotation="0"
+ inkscape:snap-global="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:bbox-nodes="true"
+ inkscape:bbox-paths="true"
+ inkscape:snap-bbox="true"
+ inkscape:window-maximized="1"
+ inkscape:window-y="-8"
+ inkscape:window-x="-8"
+ inkscape:window-height="1017"
+ inkscape:window-width="1920"
+ units="px"
+ showgrid="true"
+ inkscape:current-layer="g5228"
+ inkscape:document-units="px"
+ inkscape:cy="13.17691"
+ inkscape:cx="6.2316889"
+ inkscape:zoom="22.627417"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base">
+ <inkscape:grid
+ id="grid3336"
+ type="xygrid" />
+ <sodipodi:guide
+ id="guide883"
+ orientation="1,0"
+ position="4,10" />
+ <sodipodi:guide
+ id="guide885"
+ orientation="0,-1"
+ position="10,12" />
+ <sodipodi:guide
+ id="guide887"
+ orientation="1,0"
+ position="12,2" />
+ <sodipodi:guide
+ id="guide889"
+ orientation="0,-1"
+ position="14,4" />
+ </sodipodi:namedview>
+ <g
+ transform="translate(0,-1036.3622)"
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1">
+ <g
+ id="g5228"
+ transform="translate(628,-140.49998)">
+ <path
+ id="path842"
+ d="m -624,1182.8622 4,4 4,-4 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ </g>
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <rdf:Description
+ dc:language="en"
+ dc:format="image/svg+xml"
+ dc:date="2016-12-14"
+ dc:publisher="Iconscout"
+ dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
+ about="https://iconscout.com/legal#licenses">
+ <dc:creator>
+ <rdf:Bag>
+ <rdf:li>Jemis Mali</rdf:li>
+ </rdf:Bag>
+ </dc:creator>
+ </rdf:Description>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+</svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button-disabled_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button-disabled_dark.svg
new file mode 100644
index 000000000..f5b31b9b3
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button-disabled_dark.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16" height="16" enable-background="new 0 0 122.879 122.867" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m6 3v6h-1v1h3v4h1v-4h3v-1h-1v-6h-4zm1 1h2v5h-2z" color="#ffffff" fill="#ffffff" fill-opacity=".25" style="-inkscape-stroke:none"/></svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button-pinned-focused_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button-pinned-focused_dark.svg
new file mode 100644
index 000000000..6608545ec
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button-pinned-focused_dark.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16" height="16" enable-background="new 0 0 122.879 122.867" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m14 6h-6v-1h-1v3h-4v1h4v3h1v-1h6v-4zm-1 1v2h-5v-2z" color="#000000" fill="#fff" style="-inkscape-stroke:none"/><style/></svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button-pinned_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button-pinned_dark.svg
new file mode 100644
index 000000000..0e9c5d535
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button-pinned_dark.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16" height="16" enable-background="new 0 0 122.879 122.867" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m14 6h-6v-1h-1v3h-4v1h4v3h1v-1h6v-4zm-1 1v2h-5v-2z" color="#ffffff" fill="#ffffff" style="-inkscape-stroke:none"/></svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button_45_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button_45_dark.svg
new file mode 100644
index 000000000..7333762ae
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button_45_dark.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16" height="16" enable-background="new 0 0 122.879 122.867" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m10.286-1.055e-6 -6.8571 6.8571-1.1429-1.1429-1.1429 1.1429 3.4286 3.4286-4.5714 4.5714 1.1429 1.1429 4.5714-4.5714 3.4286 3.4286 1.1429-1.1429-1.1429-1.1429 6.8571-6.8571-4.5714-4.5714zm0 2.2857 2.2857 2.2857-5.7143 5.7143-2.2857-2.2857z" fill="#ffffff"/></svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button_dark.svg b/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button_dark.svg
new file mode 100644
index 000000000..137eb441e
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/images/vs-pin-button_dark.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16" height="16" enable-background="new 0 0 122.879 122.867" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m6 3v6h-1v1h3v4h1v-4h3v-1h-1v-6h-4zm1 1h2v5h-2z" color="#ffffff" fill="#ffffff" style="-inkscape-stroke:none"/></svg>
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/linux/FloatingWidgetTitleBar.cpp b/scribus/third_party/Qt-Advanced-Docking-System/src/linux/FloatingWidgetTitleBar.cpp
index 00e6fcd4d..77a631d69 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/linux/FloatingWidgetTitleBar.cpp
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/linux/FloatingWidgetTitleBar.cpp
@@ -238,6 +238,20 @@ void CFloatingWidgetTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
}
}
+//============================================================================
+QSize CFloatingWidgetTitleBar::sizeHint() const
+{
+ if (isVisible())
+ {
+ return QFrame::sizeHint();
+ }
+ else
+ {
+ // Allow titlebar to collapse when set invisible.
+ return QSize();
+ }
+}
+
//============================================================================
void CFloatingWidgetTitleBar::setMaximizedIcon(bool maximized)
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/linux/FloatingWidgetTitleBar.h b/scribus/third_party/Qt-Advanced-Docking-System/src/linux/FloatingWidgetTitleBar.h
index ad6904f65..4a6cedaf1 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/linux/FloatingWidgetTitleBar.h
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/linux/FloatingWidgetTitleBar.h
@@ -59,6 +59,7 @@ protected:
virtual void mouseReleaseEvent(QMouseEvent *ev) override;
virtual void mouseMoveEvent(QMouseEvent *ev) override;
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
+ virtual QSize sizeHint() const override;
void setMaximizeIcon(const QIcon& Icon);
QIcon maximizeIcon() const;
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default.css b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default.css
index 19c5ab1dd..064118bbb 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default.css
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default.css
@@ -75,13 +75,17 @@ ads--CDockWidgetTab[activeTab="true"] {
}
ads--CDockWidgetTab QLabel {
- color: palette(dark);
+ color: palette(text);
}
ads--CDockWidgetTab[activeTab="true"] QLabel {
color: palette(foreground);
}
+#autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(foreground);
+}
#tabCloseButton {
margin-top: 2px;
@@ -278,7 +282,7 @@ ads--CAutoHideDockContainer ads--CDockAreaWidget[focused="true"] ads--CDockAreaT
}
-#autoHideTitleLabel {
+ads--CAutoHideDockContainer #autoHideTitleLabel {
padding-left: 4px;
color: palette(light);
}
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default_dark.css b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default_dark.css
new file mode 100644
index 000000000..33f01ac27
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default_dark.css
@@ -0,0 +1,354 @@
+/*
+ * Default style sheet on Windows Platforms
+ */
+
+/*****************************************************************************
+ * CDockContainerWidget
+ *****************************************************************************/
+ads--CDockContainerWidget {
+ background: palette(window);
+}
+
+
+/*****************************************************************************
+ * CDockSplitter
+ *****************************************************************************/
+ads--CDockContainerWidget > QSplitter {
+ padding: 1 0 1 0;
+}
+
+ads--CDockContainerWidget ads--CDockSplitter::handle {
+ background: palette(light);
+}
+
+
+/*****************************************************************************
+ * CDockAreaWidget
+ *****************************************************************************/
+ads--CDockAreaWidget {
+ background: palette(window);
+}
+
+ads--CTitleBarButton {
+ padding: 0px 0px;
+}
+
+
+#tabsMenuButton::menu-indicator {
+ image: none;
+}
+
+#tabsMenuButton {
+ qproperty-icon: url(:/ads/images/tabs-menu-button_dark.svg);
+ qproperty-iconSize: 16px;
+}
+
+#dockAreaCloseButton {
+ qproperty-icon: url(:/ads/images/close-button_dark.svg),
+ url(:/ads/images/close-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+#detachGroupButton {
+ qproperty-icon: url(:/ads/images/detach-button_dark.svg),
+ url(:/ads/images/detach-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+
+
+/*****************************************************************************
+ * CDockWidgetTab and close button styling
+ *****************************************************************************/
+ads--CDockWidgetTab {
+ background: palette(window);
+ border-color: palette(dark);
+ border-style: solid;
+ border-width: 0 1px 0 0;
+ padding: 0 0px;
+}
+
+ads--CDockWidgetTab[activeTab="true"] {
+ background: qlineargradient(spread : pad, x1 : 0, y1 : 0, x2 : 0, y2 : 0.5, stop : 0
+ palette(window), stop:1 palette(dark));
+ /*background: palette(highlight);*/
+}
+
+ads--CDockWidgetTab QLabel {
+ color: palette(light);
+}
+
+ads--CDockWidgetTab[activeTab="true"] QLabel {
+ color: palette(foreground);
+}
+
+#autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(foreground);
+}
+
+#tabCloseButton {
+ margin-top: 2px;
+ background: none;
+ border: none;
+ padding: 0px -2px;
+ qproperty-icon: url(:/ads/images/close-button_dark.svg),
+ url(:/ads/images/close-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+#tabCloseButton:hover {
+ border: 1px solid rgba(255, 255, 255, 32);
+ background: rgba(255, 255, 255, 16);
+}
+
+#tabCloseButton:pressed {
+ background: rgba(255, 255, 255, 32);
+}
+
+
+/*****************************************************************************
+ * CDockWidget
+ *****************************************************************************/
+ads--CDockWidget {
+ background: palette(dark);
+ border-color: palette(dark);
+ border-style: solid;
+ border-width: 1px 0 0 0;
+}
+
+
+QScrollArea#dockWidgetScrollArea {
+ padding: 0px;
+ border: none;
+}
+
+
+/*****************************************************************************
+ *
+ * Styling of auto hide functionality
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * CAutoHideTab
+ *****************************************************************************/
+ads--CAutoHideTab {
+ qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/
+ background: none;
+ border: none;
+ padding-left: 2px;
+ padding-right: 0px;
+ text-align: center;
+ min-height: 20px;
+ padding-bottom: 2px;
+}
+
+
+ads--CAutoHideTab:hover
+{
+ color: palette(highlight);
+}
+
+
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="0"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="2"] {
+ border-top: 6px solid rgba(255, 255, 255, 48);
+}
+
+
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="1"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="3"] {
+ border-bottom: 6px solid rgba(255, 255, 255, 48);
+}
+
+
+
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="0"],
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="2"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="0"][activeTab="true"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="2"][activeTab="true"] {
+ border-top: 6px solid palette(highlight);
+}
+
+
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="1"],
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="3"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="1"][activeTab="true"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="3"][activeTab="true"] {
+ border-bottom: 6px solid palette(highlight);
+}
+
+
+/**
+ * Auto hide tabs with icon only
+ */
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="0"] {
+ border-top: 6px solid rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="1"] {
+ border-left: 6px solid rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="2"] {
+ border-right: 6px solid rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="3"] {
+ border-bottom: 6px solid rgba(255, 255, 255, 48);
+}
+
+
+/**
+ * Auto hide tabs with icon only hover
+ */
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="0"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="0"][activeTab="true"] {
+ border-top: 6px solid palette(highlight);
+}
+
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="1"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="1"][activeTab="true"] {
+ border-left: 6px solid palette(highlight);
+}
+
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="2"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="2"][activeTab="true"] {
+ border-right: 6px solid palette(highlight);
+}
+
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="3"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="3"][activeTab="true"] {
+ border-bottom: 6px solid palette(highlight);
+}
+
+
+/*****************************************************************************
+ * CAutoHideSideBar
+ *****************************************************************************/
+ads--CAutoHideSideBar{
+ background: palette(window);
+ border: none;
+ qproperty-spacing: 12;
+}
+
+#sideTabsContainerWidget {
+ background: transparent;
+}
+
+
+ads--CAutoHideSideBar[sideBarLocation="0"] {
+ border-bottom: 1px solid palette(light);
+}
+
+ads--CAutoHideSideBar[sideBarLocation="1"] {
+ border-right: 1px solid palette(light);
+}
+
+ads--CAutoHideSideBar[sideBarLocation="2"] {
+ border-left: 1px solid palette(light);
+}
+
+ads--CAutoHideSideBar[sideBarLocation="3"] {
+ border-top: 1px solid palette(light);
+}
+
+
+/*****************************************************************************
+ * CAutoHideDockContainer
+ *****************************************************************************/
+ads--CAutoHideDockContainer {
+ background: palette(window);
+}
+
+
+ads--CAutoHideDockContainer ads--CDockAreaTitleBar {
+ background: palette(highlight);
+ padding: 0px;
+ border: none;
+}
+
+
+/*
+ * This is required because the ads--CDockAreaWidget[focused="true"] will
+ * overwrite the ads--CAutoHideDockContainer ads--CDockAreaTitleBar rule
+ */
+ads--CAutoHideDockContainer ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar {
+ background: palette(highlight);
+ padding: 0px;
+ border: none;
+}
+
+
+ads--CAutoHideDockContainer #autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(dark);
+}
+
+
+/*****************************************************************************
+ * CAutoHideDockContainer titlebar buttons
+ *****************************************************************************/
+#dockAreaAutoHideButton {
+ qproperty-icon: url(:/ads/images/vs-pin-button_dark.svg),
+ url(:/ads/images/vs-pin-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+ads--CAutoHideDockContainer #dockAreaAutoHideButton {
+ qproperty-icon: url(:/ads/images/vs-pin-button-pinned-focused_dark.svg);
+ qproperty-iconSize: 16px;
+}
+
+
+ads--CAutoHideDockContainer #dockAreaMinimizeButton {
+ qproperty-icon: url(:/ads/images/minimize-button-focused_dark.svg);
+ qproperty-iconSize: 16px;
+}
+
+
+ads--CAutoHideDockContainer #dockAreaCloseButton{
+ qproperty-icon: url(:/ads/images/close-button-focused_dark.svg)
+}
+
+
+ads--CAutoHideDockContainer ads--CTitleBarButton:hover {
+ background: rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideDockContainer ads--CTitleBarButton:pressed {
+ background: rgba(255, 255, 255, 96);
+}
+
+/*****************************************************************************
+ * CAutoHideDockContainer Titlebar and Buttons
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * CResizeHandle
+ *****************************************************************************/
+ads--CResizeHandle {
+ background: palette(window);
+}
+
+
+ads--CAutoHideDockContainer[sideBarLocation="0"] ads--CResizeHandle {
+ border-top: 1px solid palette(light);
+}
+
+ads--CAutoHideDockContainer[sideBarLocation="1"] ads--CResizeHandle {
+ border-left: 1px solid palette(light);
+}
+
+ads--CAutoHideDockContainer[sideBarLocation="2"] ads--CResizeHandle {
+ border-right: 1px solid palette(light);
+}
+
+ads--CAutoHideDockContainer[sideBarLocation="3"] ads--CResizeHandle {
+ border-top: 1px solid palette(light);
+}
+
+
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default_linux.css b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default_linux.css
index d9bc03d99..85c27e972 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default_linux.css
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default_linux.css
@@ -39,6 +39,12 @@ ads--CTitleBarButton {
}
+#autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(foreground);
+}
+
+
#tabsMenuButton {
qproperty-icon: url(:/ads/images/tabs-menu-button.svg);
qproperty-iconSize: 16px;
@@ -79,7 +85,7 @@ ads--CDockWidgetTab[activeTab="true"] {
ads--CDockWidgetTab QLabel {
- color: palette(dark);
+ color: palette(text);
}
@@ -88,6 +94,12 @@ ads--CDockWidgetTab[activeTab="true"] QLabel {
}
+#autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(foreground);
+}
+
+
#tabCloseButton {
margin-top: 2px;
background: none;
@@ -314,7 +326,7 @@ ads--CAutoHideDockContainer ads--CDockAreaWidget[focused="true"] ads--CDockAreaT
}
-#autoHideTitleLabel {
+ads--CAutoHideDockContainer #autoHideTitleLabel {
padding-left: 4px;
color: palette(light);
}
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default_linux_dark.css b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default_linux_dark.css
new file mode 100644
index 000000000..1e6cf9c80
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/default_linux_dark.css
@@ -0,0 +1,401 @@
+/*
+ * Default style sheet on Linux Platforms
+ */
+
+/*****************************************************************************
+ * CDockContainerWidget
+ *****************************************************************************/
+ads--CDockContainerWidget {
+ background: palette(window);
+}
+
+
+/*****************************************************************************
+ * CDockSplitter
+ *****************************************************************************/
+ads--CDockContainerWidget > QSplitter{
+ padding: 1 0 1 0;
+}
+
+ads--CDockContainerWidget ads--CDockSplitter::handle {
+ background: palette(light);
+}
+
+
+/*****************************************************************************
+ * CDockAreaWidget
+ *****************************************************************************/
+ads--CDockAreaWidget {
+ background: palette(window);
+}
+
+ads--CDockAreaWidget #tabsMenuButton::menu-indicator {
+ image: none;
+}
+
+
+ads--CTitleBarButton {
+ padding: 0px 0px;
+}
+
+
+#autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(foreground);
+}
+
+
+#tabsMenuButton {
+ qproperty-icon: url(:/ads/images/tabs-menu-button_dark.svg);
+ qproperty-iconSize: 16px;
+}
+
+
+#dockAreaCloseButton {
+ qproperty-icon: url(:/ads/images/close-button_dark.svg),
+ url(:/ads/images/close-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+
+#detachGroupButton {
+ qproperty-icon: url(:/ads/images/detach-button_dark.svg),
+ url(:/ads/images/detach-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+
+/*****************************************************************************
+ * CDockWidgetTab and close button styling
+ *****************************************************************************/
+ads--CDockWidgetTab {
+ background: palette(window);
+ border-color: palette(dark);
+ border-style: solid;
+ border-width: 0 1px 0 0;
+ padding: 0 0px;
+}
+
+
+ads--CDockWidgetTab[activeTab="true"] {
+ background: qlineargradient(spread : pad, x1 : 0, y1 : 0, x2 : 0, y2 : 0.5, stop : 0
+ palette(window), stop:1 palette(dark));
+ /*background: palette(highlight);*/
+}
+
+
+ads--CDockWidgetTab QLabel {
+ color: palette(light);
+}
+
+
+ads--CDockWidgetTab[activeTab="true"] QLabel {
+ color: palette(foreground);
+}
+
+
+#autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(foreground);
+}
+
+
+#tabCloseButton {
+ margin-top: 2px;
+ background: none;
+ border: none;
+ padding: 0px -2px;
+ qproperty-icon: url(:/ads/images/close-button_dark.svg),
+ url(:/ads/images/close-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+#tabCloseButton:hover {
+ border: 1px solid rgba(255, 255, 255, 32);
+ background: rgba(255, 255, 255, 16);
+}
+
+#tabCloseButton:pressed {
+ background: rgba(255, 255, 255, 32);
+}
+
+
+/*****************************************************************************
+ * CDockWidget
+ *****************************************************************************/
+ads--CDockWidget {
+ background: palette(dark);
+ border-color: palette(dark);
+ border-style: solid;
+ border-width: 1px 0 0 0;
+}
+
+
+QScrollArea#dockWidgetScrollArea {
+ padding: 0px;
+ border: none;
+}
+
+
+/*****************************************************************************
+ * Floating widget styling
+ *****************************************************************************/
+ads--CFloatingWidgetTitleBar {
+ background: palette(mid);
+ qproperty-maximizeIcon: url(:/ads/images/maximize-button_dark.svg);
+ qproperty-normalIcon: url(:/ads/images/restore-button_dark.svg);
+}
+
+
+#floatingTitleCloseButton, #floatingTitleMaximizeButton {
+ qproperty-iconSize: 16px;
+ border: none;
+ margin: 3px;
+}
+
+
+#floatingTitleCloseButton {
+ qproperty-icon: url(:/ads/images/close-button_dark.svg);
+}
+
+#floatingTitleCloseButton:hover {
+ background: rgba(255, 255, 255, 24);
+ border: none;
+}
+
+#floatingTitleCloseButton:pressed {
+ background: rgba(255, 255, 255, 48);
+}
+
+
+/*****************************************************************************
+ *
+ * Styling of auto hide functionality
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * CAutoHideTab
+ *****************************************************************************/
+ads--CAutoHideTab {
+ qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/
+ background: none;
+ border: none;
+ padding-left: 2px;
+ padding-right: 0px;
+ text-align: center;
+ min-height: 20px;
+ padding-bottom: 2px;
+}
+
+
+ads--CAutoHideTab:hover
+{
+ color: palette(highlight);
+}
+
+
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="0"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="2"] {
+ border-top: 6px solid rgba(255, 255, 255, 48);
+}
+
+
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="1"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="3"] {
+ border-bottom: 6px solid rgba(255, 255, 255, 48);
+}
+
+
+
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="0"],
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="2"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="0"][activeTab="true"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="2"][activeTab="true"] {
+ border-top: 6px solid palette(highlight);
+}
+
+
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="1"],
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="3"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="1"][activeTab="true"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="3"][activeTab="true"] {
+ border-bottom: 6px solid palette(highlight);
+}
+
+
+/**
+ * Auto hide tabs with icon only
+ */
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="0"] {
+ border-top: 6px solid rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="1"] {
+ border-left: 6px solid rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="2"] {
+ border-right: 6px solid rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="3"] {
+ border-bottom: 6px solid rgba(255, 255, 255, 48);
+}
+
+
+/**
+ * Auto hide tabs with icon only hover
+ */
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="0"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="0"][activeTab="true"] {
+ border-top: 6px solid palette(highlight);
+}
+
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="1"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="1"][activeTab="true"] {
+ border-left: 6px solid palette(highlight);
+}
+
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="2"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="2"][activeTab="true"] {
+ border-right: 6px solid palette(highlight);
+}
+
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="3"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="3"][activeTab="true"] {
+ border-bottom: 6px solid palette(highlight);
+}
+
+
+/*****************************************************************************
+ * CAutoHideSideBar
+ *****************************************************************************/
+ads--CAutoHideSideBar{
+ background: palette(window);
+ border: none;
+ qproperty-spacing: 12;
+}
+
+#sideTabsContainerWidget {
+ background: transparent;
+}
+
+
+ads--CAutoHideSideBar[sideBarLocation="0"] {
+ border-bottom: 1px solid palette(light);
+}
+
+ads--CAutoHideSideBar[sideBarLocation="1"] {
+ border-right: 1px solid palette(light);
+}
+
+ads--CAutoHideSideBar[sideBarLocation="2"] {
+ border-left: 1px solid palette(light);
+}
+
+ads--CAutoHideSideBar[sideBarLocation="3"] {
+ border-top: 1px solid palette(light);
+}
+
+
+/*****************************************************************************
+ * CAutoHideDockContainer
+ *****************************************************************************/
+ads--CAutoHideDockContainer {
+ background: palette(window);
+}
+
+
+ads--CAutoHideDockContainer ads--CDockAreaTitleBar {
+ background: palette(highlight);
+ padding: 0px;
+ border: none;
+}
+
+
+/*
+ * This is required because the ads--CDockAreaWidget[focused="true"] will
+ * overwrite the ads--CAutoHideDockContainer ads--CDockAreaTitleBar rule
+ */
+ads--CAutoHideDockContainer ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar {
+ background: palette(highlight);
+ padding: 0px;
+ border: none;
+}
+
+
+ads--CAutoHideDockContainer #autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(dark);
+}
+
+
+/*****************************************************************************
+ * CAutoHideDockContainer titlebar buttons
+ *****************************************************************************/
+#dockAreaAutoHideButton {
+ qproperty-icon: url(:/ads/images/vs-pin-button_dark.svg),
+ url(:/ads/images/vs-pin-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+ads--CAutoHideDockContainer #dockAreaAutoHideButton {
+ qproperty-icon: url(:/ads/images/vs-pin-button-pinned-focused_dark.svg);
+ qproperty-iconSize: 16px;
+}
+
+
+ads--CAutoHideDockContainer #dockAreaMinimizeButton {
+ qproperty-icon: url(:/ads/images/minimize-button-focused_dark.svg);
+ qproperty-iconSize: 16px;
+}
+
+
+ads--CAutoHideDockContainer #dockAreaCloseButton{
+ qproperty-icon: url(:/ads/images/close-button-focused_dark.svg)
+}
+
+
+ads--CAutoHideDockContainer ads--CTitleBarButton:hover {
+ background: rgba(255, 255, 255, 48);
+ border: none;
+}
+
+ads--CAutoHideDockContainer ads--CTitleBarButton:pressed {
+ background: rgba(255, 255, 255, 96);
+ border: none;
+}
+
+/*****************************************************************************
+ * CAutoHideDockContainer Titlebar and Buttons
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * CResizeHandle
+ *****************************************************************************/
+ads--CResizeHandle {
+ background: palette(window);
+}
+
+
+ads--CAutoHideDockContainer[sideBarLocation="0"] ads--CResizeHandle {
+ border-top: 1px solid palette(light);
+}
+
+ads--CAutoHideDockContainer[sideBarLocation="1"] ads--CResizeHandle {
+ border-left: 1px solid palette(light);
+}
+
+ads--CAutoHideDockContainer[sideBarLocation="2"] ads--CResizeHandle {
+ border-right: 1px solid palette(light);
+}
+
+ads--CAutoHideDockContainer[sideBarLocation="3"] ads--CResizeHandle {
+ border-top: 1px solid palette(light);
+}
+
+
+
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting.css b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting.css
index 758f58613..96f6fe8fd 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting.css
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting.css
@@ -54,6 +54,10 @@ ads--CTitleBarButton {
image: none;
}
+#tabsMenuButton {
+ qproperty-icon: url(:/ads/images/tabs-menu-button.svg);
+ qproperty-iconSize: 16px;
+}
#dockAreaCloseButton {
qproperty-icon: url(:/ads/images/close-button.svg),
@@ -88,13 +92,17 @@ ads--CDockWidgetTab[activeTab="true"] {
}
ads--CDockWidgetTab QLabel {
- color: palette(dark);
+ color: palette(text);
}
ads--CDockWidgetTab[activeTab="true"] QLabel {
color: palette(foreground);
}
+#autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(foreground);
+}
#tabCloseButton {
margin-top: 2px;
@@ -134,7 +142,7 @@ ads--CDockWidgetTab[focused="true"] > #tabCloseButton:pressed {
}
ads--CDockWidgetTab[focused="true"] QLabel {
- color: palette(light);
+ color: palette(highlighted-text);
}
@@ -316,7 +324,7 @@ ads--CAutoHideDockContainer ads--CDockAreaWidget[focused="true"] ads--CDockAreaT
}
-#autoHideTitleLabel {
+ads--CAutoHideDockContainer #autoHideTitleLabel {
padding-left: 4px;
color: palette(light);
}
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting_dark.css b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting_dark.css
new file mode 100644
index 000000000..941a4b6b7
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting_dark.css
@@ -0,0 +1,395 @@
+/*
+ * Default style sheet on Windows Platforms with focus highlighting flag enabled
+ */
+
+
+/*****************************************************************************
+ * CDockContainerWidget
+ *****************************************************************************/
+ads--CDockContainerWidget {
+ background: palette(window);
+}
+
+
+/*****************************************************************************
+ * CDockSplitter
+ *****************************************************************************/
+ads--CDockContainerWidget > QSplitter {
+ padding: 1 0 1 0;
+}
+
+
+ads--CDockSplitter::handle {
+ background-color: palette(light);
+ /* uncomment the following line if you would like to change the size of
+ the splitter handles */
+ /* height: 1px; */
+}
+
+
+/*****************************************************************************
+ * CDockAreaWidget
+ *****************************************************************************/
+ads--CDockAreaWidget {
+ background: palette(window);
+}
+
+
+ads--CDockAreaTitleBar {
+ background: transparent;
+ border-bottom: 2px solid palette(dark);
+ padding-bottom: 0px;
+}
+
+ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar {
+ border-bottom: 2px solid palette(highlight);
+}
+
+ads--CTitleBarButton {
+ padding: 0px 0px;
+}
+
+
+#tabsMenuButton::menu-indicator {
+ image: none;
+}
+
+#tabsMenuButton {
+ qproperty-icon: url(:/ads/images/tabs-menu-button_dark.svg);
+ qproperty-iconSize: 16px;
+}
+
+#dockAreaCloseButton {
+ qproperty-icon: url(:/ads/images/close-button_dark.svg),
+ url(:/ads/images/close-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+#detachGroupButton {
+ qproperty-icon: url(:/ads/images/detach-button_dark.svg),
+ url(:/ads/images/detach-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+
+
+/*****************************************************************************
+ * CDockWidgetTab
+ *****************************************************************************/
+ads--CDockWidgetTab {
+ background: palette(window);
+ border-color: palette(dark);
+ border-style: solid;
+ border-width: 0 1px 0 0;
+ padding: 0 0px;
+ qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/
+}
+
+ads--CDockWidgetTab[activeTab="true"] {
+ background: qlineargradient(spread : pad, x1 : 0, y1 : 0, x2 : 0, y2 : 0.5, stop : 0
+ palette(window), stop:1 palette(dark));
+ /*background: palette(highlight);*/
+}
+
+ads--CDockWidgetTab QLabel {
+ color: palette(light);
+}
+
+ads--CDockWidgetTab[activeTab="true"] QLabel {
+ color: palette(foreground);
+}
+
+#autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(foreground);
+}
+
+#tabCloseButton {
+ margin-top: 2px;
+ background: none;
+ border: none;
+ padding: 0px -2px;
+ qproperty-icon: url(:/ads/images/close-button_dark.svg),
+ url(:/ads/images/close-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+#tabCloseButton:hover {
+ /*border: 1px solid rgba(0, 0, 0, 32);*/
+ background: rgba(255, 255, 255, 24);
+}
+
+#tabCloseButton:pressed {
+ background: rgba(255, 255, 255, 48);
+}
+
+/* Focus related styling */
+ads--CDockWidgetTab[focused="true"] {
+ background: palette(highlight);
+ border-color: palette(highlight);
+}
+
+ads--CDockWidgetTab[focused="true"] > #tabCloseButton {
+ qproperty-icon: url(:/ads/images/close-button-focused_dark.svg)
+}
+
+ads--CDockWidgetTab[focused="true"] > #tabCloseButton:hover {
+ background: rgba(0, 0, 0, 48);
+}
+
+ads--CDockWidgetTab[focused="true"] > #tabCloseButton:pressed {
+ background: rgba(0, 0, 0, 92);
+}
+
+ads--CDockWidgetTab[focused="true"] QLabel {
+ color: palette(highlighted-text);
+}
+
+
+
+/*****************************************************************************
+ * CDockWidget
+ *****************************************************************************/
+ads--CDockWidget {
+ background: palette(dark);
+ border-color: palette(dark);
+ border-style: solid;
+ border-width: 1px 0 0 0;
+}
+
+
+QScrollArea#dockWidgetScrollArea {
+ padding: 0px;
+ border: none;
+}
+
+
+
+/*****************************************************************************
+ *
+ * Styling of auto hide functionality
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * CAutoHideTab
+ *****************************************************************************/
+ads--CAutoHideTab {
+ qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/
+ background: none;
+ border: none;
+ padding-left: 2px;
+ padding-right: 0px;
+ text-align: center;
+ min-height: 20px;
+ padding-bottom: 2px;
+}
+
+
+ads--CAutoHideTab:hover
+{
+ color: palette(highlight);
+}
+
+
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="0"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="2"] {
+ border-top: 6px solid rgba(255, 255, 255, 48);
+}
+
+
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="1"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="3"] {
+ border-bottom: 6px solid rgba(255, 255, 255, 48);
+}
+
+
+
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="0"],
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="2"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="0"][activeTab="true"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="2"][activeTab="true"] {
+ border-top: 6px solid palette(highlight);
+}
+
+
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="1"],
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="3"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="1"][activeTab="true"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="3"][activeTab="true"] {
+ border-bottom: 6px solid palette(highlight);
+}
+
+
+/**
+ * Auto hide tabs with icon only
+ */
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="0"] {
+ border-top: 6px solid rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="1"] {
+ border-left: 6px solid rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="2"] {
+ border-right: 6px solid rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="3"] {
+ border-bottom: 6px solid rgba(255, 255, 255, 48);
+}
+
+
+/**
+ * Auto hide tabs with icon only hover
+ */
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="0"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="0"][activeTab="true"] {
+ border-top: 6px solid palette(highlight);
+}
+
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="1"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="1"][activeTab="true"] {
+ border-left: 6px solid palette(highlight);
+}
+
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="2"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="2"][activeTab="true"] {
+ border-right: 6px solid palette(highlight);
+}
+
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="3"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="3"][activeTab="true"] {
+ border-bottom: 6px solid palette(highlight);
+}
+
+
+
+/*****************************************************************************
+ * CAutoHideSideBar
+ *****************************************************************************/
+ads--CAutoHideSideBar{
+ background: palette(window);
+ border: none;
+ qproperty-spacing: 12;
+}
+
+#sideTabsContainerWidget {
+ background: transparent;
+}
+
+
+ads--CAutoHideSideBar[sideBarLocation="0"] {
+ border-bottom: 1px solid palette(light);
+}
+
+ads--CAutoHideSideBar[sideBarLocation="1"] {
+ border-right: 1px solid palette(light);
+}
+
+ads--CAutoHideSideBar[sideBarLocation="2"] {
+ border-left: 1px solid palette(light);
+}
+
+ads--CAutoHideSideBar[sideBarLocation="3"] {
+ border-top: 1px solid palette(light);
+}
+
+
+/*****************************************************************************
+ * CAutoHideDockContainer
+ *****************************************************************************/
+ads--CAutoHideDockContainer {
+ background: palette(window);
+}
+
+
+ads--CAutoHideDockContainer ads--CDockAreaTitleBar {
+ background: palette(highlight);
+ padding: 0px;
+ border: none;
+}
+
+
+/*
+ * This is required because the ads--CDockAreaWidget[focused="true"] will
+ * overwrite the ads--CAutoHideDockContainer ads--CDockAreaTitleBar rule
+ */
+ads--CAutoHideDockContainer ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar {
+ background: palette(highlight);
+ padding: 0px;
+ border: none;
+}
+
+
+ads--CAutoHideDockContainer #autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(dark);
+}
+
+
+/*****************************************************************************
+ * CAutoHideDockContainer titlebar buttons
+ *****************************************************************************/
+#dockAreaAutoHideButton {
+ qproperty-icon: url(:/ads/images/vs-pin-button_dark.svg),
+ url(:/ads/images/vs-pin-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+
+ads--CAutoHideDockContainer #dockAreaAutoHideButton {
+ qproperty-icon: url(:/ads/images/vs-pin-button-pinned-focused_dark.svg);
+ qproperty-iconSize: 16px;
+}
+
+
+ads--CAutoHideDockContainer #dockAreaMinimizeButton {
+ qproperty-icon: url(:/ads/images/minimize-button-focused_dark.svg);
+ qproperty-iconSize: 16px;
+}
+
+
+ads--CAutoHideDockContainer #dockAreaCloseButton{
+ qproperty-icon: url(:/ads/images/close-button-focused_dark.svg)
+}
+
+
+ads--CAutoHideDockContainer ads--CTitleBarButton:hover {
+ background: rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideDockContainer ads--CTitleBarButton:pressed {
+ background: rgba(255, 255, 255, 96);
+}
+
+/*****************************************************************************
+ * CAutoHideDockContainer Titlebar and Buttons
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * CResizeHandle
+ *****************************************************************************/
+ads--CResizeHandle {
+ background: palette(window);
+}
+
+
+ads--CAutoHideDockContainer[sideBarLocation="0"] ads--CResizeHandle {
+ border-top: 1px solid palette(light);
+}
+
+ads--CAutoHideDockContainer[sideBarLocation="1"] ads--CResizeHandle {
+ border-left: 1px solid palette(light);
+}
+
+ads--CAutoHideDockContainer[sideBarLocation="2"] ads--CResizeHandle {
+ border-right: 1px solid palette(light);
+}
+
+ads--CAutoHideDockContainer[sideBarLocation="3"] ads--CResizeHandle {
+ border-top: 1px solid palette(light);
+}
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting_linux.css b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting_linux.css
index cfedf8f77..80d7759f7 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting_linux.css
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting_linux.css
@@ -40,6 +40,12 @@ ads--CTitleBarButton {
}
+#autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(foreground);
+}
+
+
#tabsMenuButton {
qproperty-icon: url(:/ads/images/tabs-menu-button.svg);
qproperty-iconSize: 16px;
@@ -95,7 +101,7 @@ ads--CDockWidgetTab[activeTab="true"] {
}
ads--CDockWidgetTab QLabel {
- color: palette(dark);
+ color: palette(text);
}
ads--CDockWidgetTab[activeTab="true"] QLabel {
@@ -142,7 +148,7 @@ ads--CDockWidgetTab[focused="true"] > #tabCloseButton:pressed {
}
ads--CDockWidgetTab[focused="true"] QLabel {
- color: palette(light);
+ color: palette(highlighted-text);
}
@@ -391,7 +397,7 @@ ads--CAutoHideDockContainer ads--CDockAreaWidget[focused="true"] ads--CDockAreaT
}
-#autoHideTitleLabel {
+ads--CAutoHideDockContainer #autoHideTitleLabel {
padding-left: 4px;
color: palette(light);
}
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting_linux_dark.css b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting_linux_dark.css
new file mode 100644
index 000000000..d904ae0c0
--- /dev/null
+++ b/scribus/third_party/Qt-Advanced-Docking-System/src/stylesheets/focus_highlighting_linux_dark.css
@@ -0,0 +1,470 @@
+/*
+ * Default style sheet on Linux Platforms with focus highlighting flag enabled
+ */
+
+/*****************************************************************************
+ * CDockContainerWidget
+ *****************************************************************************/
+ads--CDockContainerWidget {
+ background: palette(window);
+}
+
+
+/*****************************************************************************
+ * CDockSplitter
+ *****************************************************************************/
+ads--CDockContainerWidget > QSplitter{
+ padding: 1 0 1 0;
+}
+
+
+ads--CDockContainerWidget ads--CDockSplitter::handle {
+ background: palette(light);
+}
+
+
+/*****************************************************************************
+ * CDockAreaWidget
+ *****************************************************************************/
+ads--CDockAreaWidget {
+ background: palette(window);
+}
+
+ads--CDockAreaWidget #tabsMenuButton::menu-indicator {
+ image: none;
+}
+
+
+ads--CTitleBarButton {
+ padding: 0px 0px;
+}
+
+
+#autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(foreground);
+}
+
+
+#tabsMenuButton {
+ qproperty-icon: url(:/ads/images/tabs-menu-button_dark.svg);
+ qproperty-iconSize: 16px;
+}
+
+
+#dockAreaCloseButton {
+ qproperty-icon: url(:/ads/images/close-button_dark.svg),
+ url(:/ads/images/close-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+
+#detachGroupButton {
+ qproperty-icon: url(:/ads/images/detach-button_dark.svg),
+ url(:/ads/images/detach-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+
+
+/*****************************************************************************
+ * CDockAreaTitleBar
+ *****************************************************************************/
+ads--CDockAreaTitleBar {
+ background: transparent;
+ border-bottom: 2px solid palette(dark);
+ padding-bottom: 0px;
+}
+
+ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar {
+ background: transparent;
+ border-bottom: 2px solid palette(highlight);
+ padding-bottom: 0px;
+}
+
+
+/*****************************************************************************
+ * CDockWidgetTab and close button styling
+ *****************************************************************************/
+ads--CDockWidgetTab {
+ background: palette(window);
+ border-color: palette(dark);
+ border-style: solid;
+ border-width: 0 1px 0 0;
+ padding: 0 0px;
+}
+
+ads--CDockWidgetTab[activeTab="true"] {
+ background: qlineargradient(spread : pad, x1 : 0, y1 : 0, x2 : 0, y2 : 0.5, stop : 0
+ palette(window), stop:1 palette(dark));
+ /*background: palette(highlight);*/
+}
+
+ads--CDockWidgetTab QLabel {
+ color: palette(light);
+}
+
+ads--CDockWidgetTab[activeTab="true"] QLabel {
+ color: palette(foreground);
+}
+
+
+#tabCloseButton {
+ margin-top: 2px;
+ background: none;
+ border: none;
+ padding: 0px -2px;
+ qproperty-icon: url(:/ads/images/close-button_dark.svg),
+ url(:/ads/images/close-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+#tabCloseButton:hover {
+ /*border: 1px solid rgba(0, 0, 0, 32);*/
+ background: rgba(255, 255, 255, 24);
+}
+
+#tabCloseButton:pressed {
+ background: rgba(255, 255, 255, 48);
+}
+
+
+/* Focus related styling */
+ads--CDockWidgetTab[focused="true"] {
+ background: palette(highlight);
+ border-color: palette(highlight);
+}
+
+ads--CDockWidgetTab[focused="true"] > #tabCloseButton {
+ qproperty-icon: url(:/ads/images/close-button-focused_dark.svg)
+}
+
+ads--CDockWidgetTab[focused="true"] > #tabCloseButton:hover {
+ background: rgba(0, 0, 0, 48);
+}
+
+ads--CDockWidgetTab[focused="true"] > #tabCloseButton:pressed {
+ background: rgba(0, 0, 0, 92);
+}
+
+ads--CDockWidgetTab[focused="true"] QLabel {
+ color: palette(highlighted-text);
+}
+
+
+/*****************************************************************************
+ * CDockWidget
+ *****************************************************************************/
+ads--CDockWidget {
+ background: palette(dark);
+ border-color: palette(dark);
+ border-style: solid;
+ border-width: 1px 0 0 0;
+}
+
+
+QScrollArea#dockWidgetScrollArea {
+ padding: 0px;
+ border: none;
+}
+
+
+
+/*****************************************************************************
+ * Floating widget styling
+ *****************************************************************************/
+ads--CFloatingWidgetTitleBar {
+ qproperty-maximizeIcon: url(:/ads/images/maximize-button_dark.svg);
+ qproperty-normalIcon: url(:/ads/images/restore-button_dark.svg);
+}
+
+
+/* does not properly work on KDE
+ads--CFloatingDockContainer[isActiveWindow="true"] ads--CFloatingWidgetTitleBar {
+ background: palette(highlight);
+ qproperty-maximizeIcon: url(:/ads/images/maximize-button-focused_dark.svg);
+ qproperty-normalIcon: url(:/ads/images/restore-button-focused_dark.svg);
+}
+
+ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleLabel {
+ color: palette(light);
+}
+*/
+
+#floatingTitleCloseButton, #floatingTitleMaximizeButton {
+ qproperty-iconSize: 16px;
+ border: none;
+ margin: 6px 3px 6px 3px;
+}
+
+
+#floatingTitleCloseButton {
+ qproperty-icon: url(:/ads/images/close-button_dark.svg);
+}
+
+
+#floatingTitleCloseButton:hover, #floatingTitleMaximizeButton:hover {
+ background: rgba(255, 255, 255, 24);
+ border: none;
+}
+
+
+#floatingTitleCloseButton:pressed, #floatingTitleMaximizeButton:pressed {
+ background: rgba(255, 255, 255, 48);
+}
+
+
+ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleMaximizeButton {
+ qproperty-iconSize: 16px;
+}
+
+
+/* does not properly work on KDE
+ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleCloseButton {
+ qproperty-icon: url(:/ads/images/close-button-focused_dark.svg);
+ qproperty-iconSize: 16px;
+}
+
+ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleCloseButton:hover,
+ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleMaximizeButton:hover {
+ background: rgba(255, 255, 255, 48);
+}
+
+
+ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleCloseButton:pressed,
+ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleMaximizeButton:pressed {
+ background: rgba(255, 255, 255, 92);
+}
+*/
+
+
+/*****************************************************************************
+ *
+ * Styling of auto hide functionality
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * CAutoHideTab
+ *****************************************************************************/
+ads--CAutoHideTab {
+ qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/
+ background: none;
+ border: none;
+ padding-left: 2px;
+ padding-right: 0px;
+ text-align: center;
+ min-height: 20px;
+ padding-bottom: 2px;
+}
+
+
+ads--CAutoHideTab:hover
+{
+ color: palette(highlight);
+}
+
+
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="0"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="2"] {
+ border-top: 6px solid rgba(255, 255, 255, 48);
+}
+
+
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="1"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="3"] {
+ border-bottom: 6px solid rgba(255, 255, 255, 48);
+}
+
+
+
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="0"],
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="2"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="0"][activeTab="true"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="2"][activeTab="true"] {
+ border-top: 6px solid palette(highlight);
+}
+
+
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="1"],
+ads--CAutoHideTab:hover[iconOnly="false"][sideBarLocation="3"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="1"][activeTab="true"],
+ads--CAutoHideTab[iconOnly="false"][sideBarLocation="3"][activeTab="true"] {
+ border-bottom: 6px solid palette(highlight);
+}
+
+
+/**
+ * Auto hide tabs with icon only
+ */
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="0"] {
+ border-top: 6px solid rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="1"] {
+ border-left: 6px solid rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="2"] {
+ border-right: 6px solid rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="3"] {
+ border-bottom: 6px solid rgba(255, 255, 255, 48);
+}
+
+
+/**
+ * Auto hide tabs with icon only hover
+ */
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="0"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="0"][activeTab="true"] {
+ border-top: 6px solid palette(highlight);
+}
+
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="1"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="1"][activeTab="true"] {
+ border-left: 6px solid palette(highlight);
+}
+
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="2"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="2"][activeTab="true"] {
+ border-right: 6px solid palette(highlight);
+}
+
+ads--CAutoHideTab:hover[iconOnly="true"][sideBarLocation="3"],
+ads--CAutoHideTab[iconOnly="true"][sideBarLocation="3"][activeTab="true"] {
+ border-bottom: 6px solid palette(highlight);
+}
+
+
+
+/*****************************************************************************
+ * CAutoHideSideBar
+ *****************************************************************************/
+ads--CAutoHideSideBar{
+ background: palette(window);
+ border: none;
+ qproperty-spacing: 12;
+}
+
+#sideTabsContainerWidget {
+ background: transparent;
+}
+
+
+ads--CAutoHideSideBar[sideBarLocation="0"] {
+ border-bottom: 1px solid palette(light);
+}
+
+ads--CAutoHideSideBar[sideBarLocation="1"] {
+ border-right: 1px solid palette(light);
+}
+
+ads--CAutoHideSideBar[sideBarLocation="2"] {
+ border-left: 1px solid palette(light);
+}
+
+ads--CAutoHideSideBar[sideBarLocation="3"] {
+ border-top: 1px solid palette(light);
+}
+
+
+/*****************************************************************************
+ * CAutoHideDockContainer
+ *****************************************************************************/
+ads--CAutoHideDockContainer {
+ background: palette(window);
+}
+
+
+ads--CAutoHideDockContainer ads--CDockAreaTitleBar {
+ background: palette(highlight);
+ padding: 0px;
+ border: none;
+}
+
+
+/*
+ * This is required because the ads--CDockAreaWidget[focused="true"] will
+ * overwrite the ads--CAutoHideDockContainer ads--CDockAreaTitleBar rule
+ */
+ads--CAutoHideDockContainer ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar {
+ background: palette(highlight);
+ padding: 0px;
+ border: none;
+}
+
+
+ads--CAutoHideDockContainer #autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(dark);
+}
+
+
+/*****************************************************************************
+ * CAutoHideDockContainer titlebar buttons
+ *****************************************************************************/
+#dockAreaAutoHideButton {
+ qproperty-icon: url(:/ads/images/vs-pin-button_dark.svg),
+ url(:/ads/images/vs-pin-button-disabled_dark.svg) disabled;
+ qproperty-iconSize: 16px;
+}
+
+ads--CAutoHideDockContainer #dockAreaAutoHideButton {
+ qproperty-icon: url(:/ads/images/vs-pin-button-pinned-focused_dark.svg);
+ qproperty-iconSize: 16px;
+}
+
+
+ads--CAutoHideDockContainer #dockAreaMinimizeButton {
+ qproperty-icon: url(:/ads/images/minimize-button-focused_dark.svg);
+ qproperty-iconSize: 16px;
+}
+
+
+ads--CAutoHideDockContainer #dockAreaCloseButton{
+ qproperty-icon: url(:/ads/images/close-button-focused_dark.svg)
+}
+
+
+ads--CAutoHideDockContainer ads--CTitleBarButton:hover {
+ background: rgba(255, 255, 255, 48);
+ border: none;
+}
+
+ads--CAutoHideDockContainer ads--CTitleBarButton:pressed {
+ background: rgba(255, 255, 255, 96);
+ border: none;
+}
+
+/*****************************************************************************
+ * CAutoHideDockContainer Titlebar and Buttons
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * CResizeHandle
+ *****************************************************************************/
+ads--CResizeHandle {
+ background: palette(window);
+}
+
+
+ads--CAutoHideDockContainer[sideBarLocation="0"] ads--CResizeHandle {
+ border-top: 1px solid palette(light);
+}
+
+ads--CAutoHideDockContainer[sideBarLocation="1"] ads--CResizeHandle {
+ border-left: 1px solid palette(light);
+}
+
+ads--CAutoHideDockContainer[sideBarLocation="2"] ads--CResizeHandle {
+ border-right: 1px solid palette(light);
+}
+
+ads--CAutoHideDockContainer[sideBarLocation="3"] ads--CResizeHandle {
+ border-top: 1px solid palette(light);
+}
+
ads5small_2026-07-02_01.diff (4,580 bytes)
diff --git a/scribus/CMakeLists.txt b/scribus/CMakeLists.txt
index 8308fc4af..1dafac139 100644
--- a/scribus/CMakeLists.txt
+++ b/scribus/CMakeLists.txt
@@ -294,7 +294,7 @@ target_link_libraries(${EXE_NAME} PRIVATE
)
#if(WANT_QTADS)
- target_link_libraries(${EXE_NAME} PUBLIC qt6advanceddocking)
+target_link_libraries(${EXE_NAME} PUBLIC qtadvanceddocking-qt${QT_VERSION_MAJOR})
#endif()
if(WITH_TESTS)
diff --git a/scribus/main_nix.cpp b/scribus/main_nix.cpp
index 94566fd86..7ae10366e 100644
--- a/scribus/main_nix.cpp
+++ b/scribus/main_nix.cpp
@@ -67,8 +67,9 @@ int mainApp(int argc, char **argv)
{
emergencyActivated = false;
+// Fallback if the Linux OS doesn't support wayland
#if !defined(Q_OS_MACOS)
- qputenv("QT_QPA_PLATFORM", "xcb");
+ qputenv("QT_QPA_PLATFORM", "wayland;xcb");
#endif
QImageReader::setAllocationLimit(1024);
@@ -78,24 +79,7 @@ int mainApp(int argc, char **argv)
app.parseCommandLine();
FcInit();
-
- if (QApplication::platformName() == "wayland")
- {
- QString errHdr = QObject::tr("Fatal Error");
- QString errMsg = QObject::tr("Scribus does not support the Wayland platform. Use XWayland to run Scribus on Wayland. Scribus will close now.");
- if (app.useGUI)
- {
- QMessageBox::critical(nullptr, errHdr, errMsg);
- }
- else
- {
- std::cout << errHdr.toStdString() << std::endl;
- std::cout << "-------------" << std::endl;
- std::cout << errMsg.toStdString() << std::endl;
- }
- return EXIT_FAILURE;
- }
-
+
int appRetVal = app.init();
if (appRetVal == EXIT_FAILURE)
return(EXIT_FAILURE);
diff --git a/scribus/third_party/Qt-Advanced-Docking-System/CMakeLists.txt b/scribus/third_party/Qt-Advanced-Docking-System/CMakeLists.txt
index 2a807197e..2dbcbdb08 100644
--- a/scribus/third_party/Qt-Advanced-Docking-System/CMakeLists.txt
+++ b/scribus/third_party/Qt-Advanced-Docking-System/CMakeLists.txt
@@ -1,30 +1,39 @@
###<< Scribus
-set(ADS_VERSION "4.3.0")
+set(ADS_VERSION "5.0.0")
###>> Scribus
cmake_minimum_required(VERSION 3.16)
-
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if (POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif (POLICY CMP0091)
+# Add cmake modules path (required for Versioning.cmake and git revision description)
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
+
# By default, the version information is extracted from the git index. However,
# we can override this behavior by explicitly setting ADS_VERSION and
# skipping the git checks. This is useful for cases where this project is being
# used independently of its original git repo (e.g. vendored in another project)
if(NOT ADS_VERSION)
- set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
include(GetGitRevisionDescription)
git_describe(GitTagVersion --tags)
string(REGEX REPLACE "^([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GitTagVersion}")
string(REGEX REPLACE "^[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GitTagVersion}")
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GitTagVersion}")
set(VERSION_SHORT "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
+ set(VERSION_SONAME "${VERSION_MAJOR}")
else()
string(REGEX MATCHALL "[\.]" VERSION_DOT_MATCHES ${ADS_VERSION})
list(LENGTH VERSION_DOT_MATCHES VERSION_DOT_COUNT)
if(VERSION_DOT_COUNT EQUAL 2)
set(VERSION_SHORT ${ADS_VERSION})
+ string(REGEX REPLACE "^([0-9]+)\\..*" "\\1" VERSION_SONAME "${ADS_VERSION}")
+ # Set PROJECT_VERSION_* variables for Versioning.cmake
+ string(REGEX MATCHALL "[0-9]+" VERSION_PARTS "${ADS_VERSION}")
+ list(GET VERSION_PARTS 0 PROJECT_VERSION_MAJOR)
+ list(GET VERSION_PARTS 1 PROJECT_VERSION_MINOR)
+ list(GET VERSION_PARTS 2 PROJECT_VERSION_PATCH)
else()
message(FATAL_ERROR "ADS_VERSION must be in major.minor.patch format, e.g. 3.8.1. Got ${ADS_VERSION}")
endif()
@@ -37,10 +46,15 @@ project(QtADS LANGUAGES CXX VERSION ${VERSION_SHORT})
option(BUILD_STATIC "Build the static library" ON)
option(BUILD_EXAMPLES "Build the examples" OFF)
-if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
- set(ads_PlatformDir "x86")
+# Platform directory: auto-detected based on pointer size, or manually set
+if(NOT ADS_PLATFORM_DIR)
+ if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
+ set(ads_PlatformDir "x86")
+ else()
+ set(ads_PlatformDir "x64")
+ endif()
else()
- set(ads_PlatformDir "x64")
+ set(ads_PlatformDir "${ADS_PLATFORM_DIR}")
endif()
add_subdirectory(src)
|
|
|
Thanks @nitramr .. committed., Looks ok on macOS! |
|
|
Still does not work correctly "for me". I can't dock anything, once it has been made floating. Is there a way to force the floating windows to have a title bar? If I recall correctly, it was much worse in the past, and having a title bar might do it now... Maybe. (but the other system felt better here...) |
|
|
Ok, I've found something: adding CDockManager::setConfigFlag(ads::CDockManager::FloatingContainerForceQWidgetTitleBar, true); to int ScribusMainWindow::initScMW(bool primaryMainWindow) gives me title bars on the floating windows and I can then dock them again. I wonder, how and if we could add this as an option... ADS' usage is still very cumbersome, but I then seem to be able to at least use it. The main reason seems to be that ADS does not support window managers that do not add "compositing" to X11. (I've tried to add a compositing extension, but I still did not have any transparency in ADS) |
|
|
@ale FloatingContainerForceNativeTitleBar might look better on whatever system you are using? Maybe give that a try. Otherwise we can use the FloatingContainerForceQWidgetTitleBar one |
|
|
I've given it a try, and that's exactly the problem: my window manager does not have a native title bar decoration on top of the windows (and that's correct!). And since ADS relies on that title bar to be dropped on the tab, I can't attach the floating windows to the docking areas. The right solution would be for ADS not to rely on the title bar for the docking action, but being able to force them is an OK workaround for me. |
|
|
Force Title Bars on Floating Palettes now an option in preferences |
|
|
Works. Thanks. |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2025-02-28 10:13 | ale | New Issue | |
| 2025-10-31 20:45 | nitramr | Note Added: 0053156 | |
| 2025-10-31 20:45 | nitramr | File Added: kddock_2025-10-31_01.patch | |
| 2025-10-31 20:46 | nitramr | Note Added: 0053157 | |
| 2025-10-31 20:46 | nitramr | File Added: kddock.png | |
| 2025-10-31 20:46 | nitramr | Note Edited: 0053156 | |
| 2025-11-01 08:43 | ale | Note Added: 0053161 | |
| 2025-11-01 12:40 | cbradney | Note Added: 0053162 | |
| 2025-11-01 12:40 | cbradney | File Added: image.png | |
| 2025-11-01 12:40 | cbradney | Note Added: 0053163 | |
| 2025-11-01 12:40 | cbradney | File Added: image-2.png | |
| 2025-11-01 12:42 | cbradney | Note Added: 0053164 | |
| 2025-11-01 12:56 | nitramr | Note Added: 0053165 | |
| 2025-11-01 13:36 | ale | Note Edited: 0053161 | |
| 2025-11-01 14:31 | ale | Note Added: 0053166 | |
| 2025-11-01 14:31 | ale | File Added: dock-laptop.png | |
| 2025-11-01 15:49 | ale | Note Edited: 0053166 | |
| 2025-11-01 16:26 | ale | Note Added: 0053167 | |
| 2025-11-01 16:26 | ale | File Added: custom-shapes.png | |
| 2025-11-01 16:26 | ale | File Added: gray-area.png | |
| 2025-11-13 21:39 | nitramr | Assigned To | => nitramr |
| 2025-11-13 21:39 | nitramr | Status | new => assigned |
| 2025-11-19 16:16 | nitramr | Note Added: 0053279 | |
| 2025-11-19 16:16 | nitramr | File Added: files.zip | |
| 2025-11-19 16:16 | nitramr | File Added: kddock_2025-11-19_01.patch | |
| 2025-11-19 16:29 | nitramr | Note Added: 0053280 | |
| 2025-11-19 16:29 | nitramr | File Added: dock_group.png | |
| 2025-11-19 20:56 | ale | Note Added: 0053281 | |
| 2025-11-19 20:57 | ale | Note Edited: 0053281 | |
| 2025-11-19 21:11 | ale | Note Added: 0053282 | |
| 2025-11-19 21:11 | ale | File Added: properties.png | |
| 2025-11-19 21:36 | nitramr | Note Added: 0053283 | |
| 2025-11-20 07:29 | ale | Note Added: 0053286 | |
| 2026-07-01 22:22 | nitramr | Note Added: 0053921 | |
| 2026-07-01 22:22 | nitramr | File Added: ads5_2026-07-02_01.diff | |
| 2026-07-01 22:22 | nitramr | File Added: ads5small_2026-07-02_01.diff | |
| 2026-07-02 20:53 | cbradney | Note Added: 0053928 | |
| 2026-07-03 19:02 | ale | Note Added: 0053933 | |
| 2026-07-03 19:43 | ale | Note Added: 0053935 | |
| 2026-07-05 13:45 | cbradney | Note Added: 0053975 | |
| 2026-07-05 14:27 | ale | Note Added: 0053977 | |
| 2026-07-05 19:46 | cbradney | Status | assigned => resolved |
| 2026-07-05 19:46 | cbradney | Resolution | open => fixed |
| 2026-07-05 19:46 | cbradney | Fixed in Version | => 1.7.4.svn |
| 2026-07-05 19:46 | cbradney | Note Added: 0053979 | |
| 2026-07-08 17:19 | ale | Note Added: 0053995 |