From 75841415a3e4233b51ff902092a4b37b4ee7be86 Mon Sep 17 00:00:00 2001 From: Nicolas Elie <40382614+n-elie@users.noreply.github.com> Date: Thu, 30 Jul 2020 13:44:05 +0200 Subject: [PATCH 01/34] Update Python bindings (#231) * Update Python bindings to reflect changes in 8443414 * [Python] Fix no such signal error for signals with a reference to an object in ads namespace * [Python] Update examples --- demo/demo.py | 4 ++ examples/deleteonclose/deleteonclose.py | 73 +++++++++++++++++++++++++ examples/simple/simple.py | 36 +++++++++++- sip/DockAreaWidget.sip | 1 + sip/DockManager.sip | 12 ++-- src/DockContainerWidget.h | 2 +- src/DockManager.h | 10 ++-- src/DockWidget.h | 2 +- 8 files changed, 124 insertions(+), 16 deletions(-) create mode 100644 examples/deleteonclose/deleteonclose.py diff --git a/demo/demo.py b/demo/demo.py index c35f687..ff268f6 100644 --- a/demo/demo.py +++ b/demo/demo.py @@ -202,6 +202,9 @@ class MainWindow(MainWindowUI, MainWindowBase): # Test custom factory - we inject a help button into the title bar QtAds.CDockComponentsFactory.setFactory(CCustomComponentsFactory()) top_dock_area = self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea, file_system_widget) + # Uncomment the next line if you would like to test the + # setHideSingleWidgetTitleBar() functionality + # top_dock_area.setHideSingleWidgetTitleBar(True) QtAds.CDockComponentsFactory.resetDefaultFactory() # We create a calendar widget and clear all flags to prevent the dock area @@ -310,6 +313,7 @@ class MainWindow(MainWindowUI, MainWindowBase): def closeEvent(self, event: QCloseEvent): self.save_state() + self.dock_manager.deleteLater() super().closeEvent(event) def on_actionSaveState_triggered(self, state: bool): diff --git a/examples/deleteonclose/deleteonclose.py b/examples/deleteonclose/deleteonclose.py new file mode 100644 index 0000000..514f1a0 --- /dev/null +++ b/examples/deleteonclose/deleteonclose.py @@ -0,0 +1,73 @@ +import sys + +from PyQtAds import QtAds +from PyQt5.QtGui import QCloseEvent +from PyQt5.QtCore import (qDebug, pyqtSlot, QObject, pyqtSignal) +from PyQt5.QtWidgets import (QMainWindow, QAction, QTextEdit, QApplication, + QMenuBar) + + +class MainWindow(QMainWindow): + dock_manager = None + + def closeEvent(self, event: QCloseEvent): + super().closeEvent(event) + if self.dock_manager is not None: + self.dock_manager.deleteLater() + + def setDockManager(self, dock_manager: QtAds.CDockManager): + self.dock_manager = dock_manager + + +if __name__ == '__main__': + app = QApplication(sys.argv) + w = MainWindow() + + QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.FocusHighlighting, True) + QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.AllTabsHaveCloseButton, True) + dock_manager = QtAds.CDockManager(w) + w.setDockManager(dock_manager) + + count = 0 + + def on_focused_dock_widget_changed(old: QtAds.CDockWidget, now: QtAds.CDockWidget): + global count + qDebug( "{:d} CDockManager::focusedDockWidgetChanged old: {} now: {} visible: {}".format( + count, + old.objectName() if old else "-", + now.objectName(), + now.isVisible())) + count += 1 + now.widget().setFocus() + + dock_manager.focusedDockWidgetChanged.connect(on_focused_dock_widget_changed) + + action = QAction("New Delete On Close", w) + w.menuBar().addAction(action) + + i = 0 + def on_action_triggered(): + global i + dw = QtAds.CDockWidget("test doc {:d}".format(i)) + i += 1 + editor = QTextEdit("lorem ipsum...", dw) + dw.setWidget(editor) + dw.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose, True) + area = dock_manager.addDockWidgetTab(QtAds.CenterDockWidgetArea, dw) + qDebug("doc dock widget created! {} {}".format(dw, area)) + action.triggered.connect(on_action_triggered) + + action = QAction("New", w) + w.menuBar().addAction(action) + def on_action2_triggered(): + global i + dw = QtAds.CDockWidget("test {:d}".format(i)) + i += 1 + editor = QTextEdit("lorem ipsum...", dw) + dw.setWidget(editor) + area = dock_manager.addDockWidgetTab(QtAds.CenterDockWidgetArea, dw) + qDebug("dock widget created! {} {}".format(dw, area)) + action.triggered.connect(on_action2_triggered) + + w.show() + app.exec_() \ No newline at end of file diff --git a/examples/simple/simple.py b/examples/simple/simple.py index 20c6fd2..fe24fc6 100644 --- a/examples/simple/simple.py +++ b/examples/simple/simple.py @@ -2,7 +2,8 @@ import os import sys from PyQt5 import uic -from PyQt5.QtCore import Qt +from PyQt5.QtCore import Qt, QTimer +from PyQt5.QtGui import QCloseEvent from PyQt5.QtWidgets import QApplication, QLabel from PyQtAds import QtAds @@ -20,7 +21,7 @@ class MainWindow(MainWindowUI, MainWindowBase): # Create the dock manager. Because the parent parameter is a QMainWindow # the dock manager registers itself as the central widget. - self.dock_manager = QtAds.CDockManager(self) + self.dock_manager1 = QtAds.CDockManager(self) # Create example content label - this can be any application specific # widget @@ -33,13 +34,42 @@ class MainWindow(MainWindowUI, MainWindowBase): # as the dock widget content dock_widget = QtAds.CDockWidget("Label 1") dock_widget.setWidget(l) + + l = QLabel() + l.setWordWrap(True) + l.setAlignment(Qt.AlignTop | Qt.AlignLeft); + l.setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ") + + # Create a dock widget with the title Label 1 and set the created label + # as the dock widget content + dock_widget2 = QtAds.CDockWidget("Label 2") + dock_widget2.setWidget(l) # Add the toggleViewAction of the dock widget to the menu to give # the user the possibility to show the dock widget if it has been closed self.menuView.addAction(dock_widget.toggleViewAction()) # Add the dock widget to the top dock widget area - self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea, dock_widget) + self.dock_manager1.addDockWidget(QtAds.TopDockWidgetArea, dock_widget) + + def remove_first_manager(): + self.dock_manager1.removeDockWidget(dock_widget) + del self.dock_manager1 + QTimer.singleShot(3000, remove_first_manager) + + def add_second_manager(): + self.dock_manager2 = QtAds.CDockManager(self) + self.dock_manager2.addDockWidget(QtAds.TopDockWidgetArea, dock_widget) + QTimer.singleShot(5000, add_second_manager) + + def closeEvent(self, event: QCloseEvent): + super().closeEvent(event) + + if hasattr(self, 'dock_manager1'): + self.dock_manager1.deleteLater() + + if hasattr(self, 'dock_manager2'): + self.dock_manager2.deleteLater() if __name__ == '__main__': diff --git a/sip/DockAreaWidget.sip b/sip/DockAreaWidget.sip index dbe1c7e..f7f1e4a 100644 --- a/sip/DockAreaWidget.sip +++ b/sip/DockAreaWidget.sip @@ -51,6 +51,7 @@ public: void setAllowedAreas(DockWidgetAreas areas); DockWidgetAreas allowedAreas() const; + void setHideSingleWidgetTitleBar(bool hide); CDockAreaTitleBar* titleBar() const; public slots: diff --git a/sip/DockManager.sip b/sip/DockManager.sip index fb5a3fa..d5d2f7a 100644 --- a/sip/DockManager.sip +++ b/sip/DockManager.sip @@ -1,7 +1,7 @@ %Import QtWidgets/QtWidgetsmod.sip %If (Qt_5_0_0 -) - + %MappedType QMap /TypeHint="Dict[QString, CDockWidget*]", TypeHintValue="{}"/ { @@ -224,11 +224,11 @@ signals: void stateRestored(); void openingPerspective(const QString& PerspectiveName); void perspectiveOpened(const QString& PerspectiveName); - void floatingWidgetCreated(CFloatingDockContainer* FloatingWidget); - void dockAreaCreated(ads::CDockAreaWidget* DockArea); - void dockWidgetAboutToBeRemoved(ads::CDockWidget* DockWidget); - void dockWidgetRemoved(ads::CDockWidget* DockWidget); - void focusedDockWidgetChanged(ads::CDockWidget* old, ads::CDockWidget* now); + void floatingWidgetCreated(ads::CFloatingDockContainer*); + void dockAreaCreated(ads::CDockAreaWidget*); + void dockWidgetAboutToBeRemoved(ads::CDockWidget*); + void dockWidgetRemoved(ads::CDockWidget*); + void focusedDockWidgetChanged(ads::CDockWidget*, ads::CDockWidget*); }; }; diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index 8f1b04c..1ce2a9e 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -276,7 +276,7 @@ signals: * This signal is emitted if a dock area is opened or closed via * toggleView() function */ - void dockAreaViewToggled(CDockAreaWidget* DockArea, bool Open); + void dockAreaViewToggled(ads::CDockAreaWidget* DockArea, bool Open); }; // class DockContainerWidget } // namespace ads //----------------------------------------------------------------------------- diff --git a/src/DockManager.h b/src/DockManager.h index 6b5b72c..2f1df43 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -502,20 +502,20 @@ signals: * An application can use this signal to e.g. subscribe to events of * the newly created window. */ - void floatingWidgetCreated(CFloatingDockContainer* FloatingWidget); + void floatingWidgetCreated(ads::CFloatingDockContainer* FloatingWidget); /** * This signal is emitted, if a new DockArea has been created. * An application can use this signal to set custom icons or custom * tooltips for the DockArea buttons. */ - void dockAreaCreated(CDockAreaWidget* DockArea); + void dockAreaCreated(ads::CDockAreaWidget* DockArea); /** * This signal is emitted just before the given dock widget is removed * from the */ - void dockWidgetAboutToBeRemoved(CDockWidget* DockWidget); + void dockWidgetAboutToBeRemoved(ads::CDockWidget* DockWidget); /** * This signal is emitted if a dock widget has been removed with the remove @@ -523,14 +523,14 @@ signals: * If this signal is emitted, the dock widget has been removed from the * docking system but it is not deleted yet. */ - void dockWidgetRemoved(CDockWidget* DockWidget); + void dockWidgetRemoved(ads::CDockWidget* DockWidget); /** * This signal is emitted if the focused dock widget changed. * Both old and now can be nullptr. * The focused dock widget is the one that is highlighted in the GUI */ - void focusedDockWidgetChanged(CDockWidget* old, CDockWidget* now); + void focusedDockWidgetChanged(ads::CDockWidget* old, ads::CDockWidget* now); }; // class DockManager } // namespace ads //----------------------------------------------------------------------------- diff --git a/src/DockWidget.h b/src/DockWidget.h index d55a803..72f2341 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -577,7 +577,7 @@ signals: * This signal is emitted when the features property changes. * The features parameter gives the new value of the property. */ - void featuresChanged(DockWidgetFeatures features); + void featuresChanged(ads::CDockWidget::DockWidgetFeatures features); }; // class DockWidget } // namespace ads From 11aec65967cbe44da5c1c81779fe6767f7a61a7f Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 17 Aug 2020 23:50:37 +0200 Subject: [PATCH 02/34] Properly persist the AllowedAreas state of CDockAreaWidget --- src/DockAreaWidget.cpp | 10 +++++++++- src/DockContainerWidget.cpp | 5 +++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 01acfa6..dad429d 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -235,6 +235,7 @@ public: using DockAreaLayout = CDockAreaLayout; +static constexpr DockWidgetAreas DefaultAllowedAreas = AllDockAreas; /** @@ -248,7 +249,7 @@ struct DockAreaWidgetPrivate CDockAreaTitleBar* TitleBar = nullptr; CDockManager* DockManager = nullptr; bool UpdateTitleBarButtons = false; - DockWidgetAreas AllowedAreas = AllDockAreas; + DockWidgetAreas AllowedAreas = DefaultAllowedAreas; bool HideSingleWidgetTitleBar = false; QSize MinSizeHint; @@ -771,6 +772,13 @@ void CDockAreaWidget::saveState(QXmlStreamWriter& s) const auto CurrentDockWidget = currentDockWidget(); QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : ""; s.writeAttribute("Current", Name); + auto AllowedAreas = allowedAreas(); + // To keep the saved XML data small, we only save the allowed areas if + // the value is different from the default value + if (AllowedAreas != DefaultAllowedAreas) + { + s.writeAttribute("AllowedAreas", QString::number(AllowedAreas, 16)); + } ADS_PRINT("CDockAreaWidget::saveState TabCount: " << d->ContentsLayout->count() << " Current: " << Name); for (int i = 0; i < d->ContentsLayout->count(); ++i) diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index e0bc72c..c3eecf6 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -942,6 +942,11 @@ bool DockContainerWidgetPrivate::restoreDockArea(CDockingStateReader& s, if (!Testing) { DockArea = new CDockAreaWidget(DockManager, _this); + const auto AllowedAreasAttribute = s.attributes().value("AllowedAreas"); + if (!AllowedAreasAttribute.isEmpty()) + { + DockArea->setAllowedAreas((DockWidgetArea)AllowedAreasAttribute.toInt(nullptr, 16)); + } } while (s.readNextStartElement()) From 81a0234b051e166f04db915cc25fffe0c7f87893 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 18 Aug 2020 08:01:45 +0200 Subject: [PATCH 03/34] Added HiveWE editor to showcase applications --- README.md | 23 ++++++++++++++---- doc/{d-tect-x.jpg => showcase_d-tect-x.jpg} | Bin ...ditor.png => showcase_ezEngine_editor.png} | Bin doc/showcase_hivewe.png | Bin 0 -> 213466 bytes ...lements.png => showcase_qmix_elements.png} | Bin ...udio.png => showcase_qt_design_studio.png} | Bin doc/{qtcreator.png => showcase_qtcreator.png} | Bin 7 files changed, 18 insertions(+), 5 deletions(-) rename doc/{d-tect-x.jpg => showcase_d-tect-x.jpg} (100%) rename doc/{ezEngine_editor.png => showcase_ezEngine_editor.png} (100%) create mode 100644 doc/showcase_hivewe.png rename doc/{qmix_elements.png => showcase_qmix_elements.png} (100%) rename doc/{qt_design_studio.png => showcase_qt_design_studio.png} (100%) rename doc/{qtcreator.png => showcase_qtcreator.png} (100%) diff --git a/README.md b/README.md index 73ec16a..9f549f8 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ know it from Visual Studio. - [QmixElements](#qmixelements) - [ezEditor](#ezeditor) - [D-Tect X](#d-tect-x) + - [HiveWE](#hivewe) ### Docking everywhere - no central widget @@ -312,7 +313,7 @@ If this project help you reduce time to develop or if you just like it, you can From version 4.12 on, Qt Creator uses the Advanced Docking Framework for its Qt Quick Designer. This improves the usability when using multiple screens. -![Qt Creator](doc/qtcreator.png) +![Qt Creator](doc/showcase_qtcreator.png) ### [Qt Design Studio](https://www.qt.io/ui-design-tools) @@ -320,7 +321,7 @@ Taken from the [Qt Blog](https://www.qt.io/blog/qt-design-studio-1.5-beta-releas > The most obvious change in [Qt Design Studio 1.5](https://www.qt.io/blog/qt-design-studio-1.5-beta-released) is the integration of dock widgets using the Qt Advanced Docking System. This allows the user to fully customize the workspace and also to undock any view into its own top level window. This especially improves the usability when using multiple screens. -![Qt Design Studio](doc/qt_design_studio.png) +![Qt Design Studio](doc/showcase_qt_design_studio.png) ### [QmixElements](https://www.cetoni.com/products/qmixelements/) @@ -328,7 +329,7 @@ The QmixElements software from [CETONI](https://www.cetoni.com) is a comprehensi plugin-based and modular laboratory automation software for controlling CETONI devices using a joint graphical user interface. The software features a powerful script system to automate processes. This [blog post](https://www.cetoni.com/blog/qmixelements-advanced-docking-system/) gives a nice overview about the use of the Qt Advanced Docking System in the QmixElements sofware. -![QmixElements](doc/qmix_elements.png) +![QmixElements](doc/showcase_qmix_elements.png) ### [ezEditor](https://github.com/ezEngine/ezEngine) @@ -336,7 +337,7 @@ The ezEditor is a full blown graphical editor used for editing scenes and importing and authoring assets for the [ezEngine](https://github.com/ezEngine/ezEngine) - an open source C++ game engine in active development. -![ezEditor](doc/ezEngine_editor.png) +![ezEditor](doc/showcase_ezEngine_editor.png) ### [D-Tect X](https://www.duerr-ndt.com/products/ndt-software/d-tect-xray-inspection-software.html) @@ -344,4 +345,16 @@ D-Tect X is a X-ray inspection software for industrial radiography. It is a stat [learn more...](https://www.duerr-ndt.com/products/ndt-software/d-tect-xray-inspection-software.html) -![D-TectX](doc/d-tect-x.jpg) +![D-TectX](doc/showcase_d-tect-x.jpg) + +### [HiveWE](https://github.com/stijnherfst/HiveWE) + +HiveWE is a Warcraft III world editor. It focusses on speed and ease of use, +especially for large maps where the regular World Editor is often too slow and clunky. +It has a JASS editor with syntax hightlighting, tabs, code completion and more. +The JASS editor uses the Qt Advanced Docking System for the management and layout +of the open editor windows. + +[learn more...](https://github.com/stijnherfst/HiveWE) + +![HiveWE](doc/showcase_hivewe.png) \ No newline at end of file diff --git a/doc/d-tect-x.jpg b/doc/showcase_d-tect-x.jpg similarity index 100% rename from doc/d-tect-x.jpg rename to doc/showcase_d-tect-x.jpg diff --git a/doc/ezEngine_editor.png b/doc/showcase_ezEngine_editor.png similarity index 100% rename from doc/ezEngine_editor.png rename to doc/showcase_ezEngine_editor.png diff --git a/doc/showcase_hivewe.png b/doc/showcase_hivewe.png new file mode 100644 index 0000000000000000000000000000000000000000..f7ba52b1e4ab533de55d8271a64f7f66a331bdd5 GIT binary patch literal 213466 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%0DKrX}5LoRvm0%6+b7@wxGwfyNyd;D> z0(z9xHmSMwE0obLC`~>H;(TUbq;^O^sUKX>x3YZRg#P#hvbC7=tweuT9>z4+NfzGX z?lK$GwHDk<$ZUhZ?8gT^G{@E8ktCsS5&1LKo0Uo&PKPv7y@bg0 z3{4Q91zm0})w_lLuAI2iypX$Os|DXrtcmzL4X9FsincUf7gDVl_^?H1L5lI?WiLxM zZ@dd(4n*~p_msvzA%jvp9}8d*)3Qu(i`N7>smf9){pKKX|4!esn{FDgKo75pRbzr3*0w zWH>mg>u3rjY(Za5qpSpSyGO*)Ens2sgJhh{_Pj4fOu}mB4mxZ*V?bd~R4(P8E=hFmat_rYD(ZIiF^iap9dC0-ypW0>t^~pA({C8vNY=4a21hTNV>H5f?X6I z1Qyd3Ytxv1DDNiVm@O@~Qiu*ejwPMvAH%*y|8tgI4`_vFSP>AsyBjF4f*M@6t={IF zB@gjLhVd^XfL2|Yoh!ZysWF!^wT`pHn|$i-($+mtoYfLE>a>pLWxiCxJA3ugsIx7= zJ!v>7dx>}KVZ&1rAr66nU3A2hrN&e+Eze@)5)uFB;AkP4xz;TP{XCdcqNex^GEsdZ0sPW=05iCE8E(|fsPBDH#Bkt^~Uqw`@M{Y znfN;DI0>qw`5C9Xs?ymW+zDXKS00ceX7ETS)jDyiq>4elB0V^G(zP@b9&UO`zLg+|)Rs8Z7GoZ;I#w^`};- z%31>G3f)GqK2--As(`Qz)uDG+IcBbq5tr50U*Uj8^0fLGEm?Ksr>Eip@_3JduTziB z_P$=!C4BqtL?Lq&w6?-R6S!zav zgEA=L_mG|QY9k#pT-xo_XL+QurYnJCa$V$Fb_Y|RsJ7)RH0!Y0wjotpQ>mdR;^OQH zlHnD3#&Zt}By29{mk~R~0bMZ@vyw~)tAY-wh&DWP{29JbT&bO#@6mBBt3P^Gc7tar zoxJ0*Op9_P5nF-n8`ST@b(9vtmVL5kMdM=&E8C#J8E@u48TSnGa@5JFB~@PJ0jrSn^PA_Eq*!o;vIPJqD{u6c@ciT7Vq>%W6@@FwU$bvolt^J1pZeWHBFrA zl0@3&06}(r0OX|CTAO!xjlKCAo96!Z6>y_-3|xLO-WB>$>)>xcM?dKruw#*6JkdbZ zdQcC!b$js@L%k>od;hsUh5hc2nI}Y6cmDz=7?@a?d)S`0y>4p=e7&vJ&OKM0ZMxl} zenQ!I&rdN|5%M;cL#;rO_z%p?T!s1FhVt{VDbt7V|Og z?RN?~NTrNAp-E9kR6#V1kwMG&7_Z8OYPri1U(8P+@k7%~(zmVT>>eH5r#BAb{vt;h zY=z^b9wI7r7wB!p(wx)7s%ZWZfg4CoOs?MBE9!lE>)eI!`ISz|H$80PER76##G{B& z46QqYx&{5z0t zLie)+IFgP;sl@n$|KLdUEdY+BZKSaEShHk&VRw43NTv>=_Q@>Ii)8-AwzhmVUbNEi zl^J<$ziDE%@|hA>;UKdTv3%Y4BK7YWYvwhJ`--v8Hx;J>M^XZ|TfdJS`A~&_EMig( z*`g81pa=oyA4J0VT#j-TLnZmeE?cEGve*Gks@K%cDzDR{JE(6anA=}NFFh1XSwbUU zIxniIGsHeQH{c66nKIz53TIs~7ias#gLo(fNwk^6li7&&VTmL8UW-1Hw_i0 z_iWnIOhWVBTtqYb8Gi$YzzW}Q6SeG!3JSuDjr90+wUWKYqXj@b0tJJYMoVF!yU3J$ zAD1^ZZwbY~-ZSI*OVb^MCBq9bljC#Di}3%1g{s{$0X5 zddXwUU8T1I=^^5;U3LMWRjTxidtgU>nFwTu_>Lb2iZy05YuM;+D-wk#58ZX(4@e^c zkVVfojRG6@YB2x8n{R-LFmLFq#cLy^F8C8h>E9B>{fm9-{O^FPfX7{IVf(;>#W};H zP$~qaoUNd$xB{+3X#$@^a;R?c+FM=*Ul`%bC$ znqM7+wnDFrkdHPEP~VHw7Re^8-(Zi*0kfZxt4^tHu=vmH-;)5q-c2c}&RsNy)ZdRq zuh}H#3O=?*38a40hIPkhoO{V9O&Tk2cE{jifzO=Z#XS#8A4=i zjl{r8q8{TgXmWBfSX9?!Y{W0h3tTl9N=QsGC(rWI{{B2gc3pQ`>z~W2QDb& z24*%zeuzLW-R{=MyuI@PmrONm+pGg*gOChNldm?usqbwQEUh}2QYHX-_7Xfjo$+8d zU*0?Di()(EK5YzUWLKBSD-NT58xC=ms1>ePl84`osNHbVl+n*?~(wrFi{4nYQUW6m>|fa(iPJ_ znwLcbQU~SksFR$jni8HQe)5<|v>G)wt*09KzywctaQKAp=U+6w0~*?oQ=hg7>>pVI zp|fdS4)fi+QhPNSW!zibI?qUQ@6BsOg6a}4x!a^RDY@80Wl3$IilEe?n>g+938_D8 z?^%;Mc~PMtnkx=)vLwd282_A_6p}1I#pv(Z1Xx^x?b^oqYWo!MEym^CWU3Kf6F_gCQ}tgQ73X@#D8j7I`x z+M;HzMK~5xv>OxmR*ATCC)-WdbCDfRq9@NGgA>VI zJ1OY7-s7S5ESk&vIKkfUyitC1?dKW^RmTNxnoh-DEoWKRvNtd^?3i)-LqD<5zNO&K z65~O#z?(k4!B`jq{GIWsf%x>17etaqkC-(Ovj8{;BtIDy=3iy}Mf?5`CVQw;*5+NH~ zSuN;dW@@U3SmU#_Px#A;)YL+{fD|(c(pZOnpf92*=sXlq5mN}c_)GIZ?J63yZKRJZ zw=C2sE5~Y*fr44=r5^?wm3W%(hXfv{sZonWcTs-uwzE6@8%a<@i-yR;K-R|J3IxRs;_>!Wh`>*ZqOz?eW_ zhJ>uP^=h;z9ZJz&a-_ByIkhU628vx){BSP8(b6A)O&(-AS9J$M5?xE6foad`KNXuN z)|_eG(w&D$Kz$FmFSoG{{KLF~SFHc)aPy`&Y?2QnU+{Z-`QAwk=rvBNEw8@ zj&cbd>a14*+>$RJ$ChsrXIdVU+e2qfGTHA9)PHJF9~L0csqX{v0h?@|Ujh4Isbp)Yko#t6pn#!G;k zGdqd5k@R1Jm38dju9F02X8*Z0BTk^rA*0u<{T}CZVM&$%`$D_tPR1Z!NF6u)mehWT zjE09qI7&Hpk)bQursbvs&4_J#YARbS;!D)q0XUgy^j5+RBw>Xcu`V6%ug4&fhFUYF zG#qrD{t{qfbMqCFcNom7yytz6wWYghM!AgU^XCp4vdJuGXqH-c7wXS+X?iLpmYntX zP25sTPenwCuoSOvZ0Y>RVz+xrXsRJiwaxmy#mud3q zU>rXO5`I^|7D?y6b*?YM6W$#t{L0hUp#k^mw{DwWTT%LAgj?^{2B7%07V}K- zY~lQkljv~R_>geoXwY&CHlTVr7x_T2uHWkI10Iqs3ha#Dd51Rr7v5-Spa;}e;9g-p z@h6Vex2y>qZ@&F~g_qvm0H<>Nxug`Oxc2pII$VRJ3wyp>BH`p@#NZrnYY+?ZrZT_b z{AXb$oH?&~77JHM)OfM~xyvhg`4=?Y8p3Wo3yUB64-ddMxPQ_az3QP&w7)6GNX4CN zF#)QWWR|#S30C~Mx^pDe=zl7`m$%rJEIfgkEG0Mhmp*EVfd+^{e0+SCFK(<{#OG$t zx_khBckScTwCA*jnsVhT@89W=_gl96-y2}G9<=<_9r%1PcG>5h0~ydNZ~_qh-55Hh z6viC>A5f7%1;C#k)uRSc2fV*mwX98|s3ZOr7MTh(H1KeSVZtrm^2j=Ky0V?gV6BIB zxSe$7pj0$7w&`vBm+Z&GE|vmiZv`IGkQJcBe>Ko{e>i9($x}R;KIhc{z6KJPBE*?}nf@3u?b1l!|;A;3812TN#S%PVR z;zk(n_tcCo>T-=aVwV(Y;62{5oJFirP*Hy!^dVmnT1EUY)@=}&>aVy~V7zs;e(6vD z6;&GDVpL1;)FH4v;IYRix5j;*;3h;aj@_!80a)Cl_=Y(saK_$EczHvO(g&lhbBXA= z-8IA=YX0b*Un8o!+(N@Wc|N4x_zO&&K&Hxh*R6!v3aKAnNB?KxsOa&o21|k=~4lW6E z95!Ag{0AwM5>P1i;PsQFmb-(%2h4Y$*``W`+q{+!!HKTN_7BTyL%S)i4 zV~eY=$ILCt)y|M1T%iEMyKvw9(TAM3+}X-))m=$I6Bp~lLt=X!{$T8q8)>)x>IJnW z++3ep_T%lO*dI^dnp+52+N|N7paJ_82Zdr@;*wK%3Wny!Bo-}(t+Jlw%+eEZlWs6g^cV3% z(8ZAcPcKBtK)@u&nrOMDe*A~Uf!C1%1M4u`ZleP{Q~AzwC_l*A7w2j8+Hr{) zTp)U0Abz%_cbzJ_Jp)x2xfS7Lu+ z$wlSljcc*|EIZCNh_2J>{piXen2FEvwS|VtaqilFwNr zwpQ=A;@!LW;tC(9E#?p}WiVMl8(I$FO=eVQoJ{)4OfG=a_I+VG>(xPY_p0hGg{&?n z+6oEDZ-@NI6q~)m2GSOVORynou`;X4%y`ukp9#{SV~BweOe@qswtaw9Us^SU<`1(9 zST3%i)iE08&>4(6N{f`LJ~fv$cL?A zP}`ke7%j4H!a6`+Gk2S<+|L`}6r;y^4ZC-yacde{v{fKQeHrpR`YuPoF64!A!navc zL@#wsA3QPW@XA++S##D|5H`Hq2=B+C=j+E;G zL1&BB-mt9Wq*7HO*>?$CVFxtYXISg`ksRTse#7{xPHJTeRUt~Tu5oZUUYH=4&Z znjx`b>4DXvGUbF$%S=tG3iskB~%oMGlomwftyj0|=SmWvTzWWhY z=zO3Yl8b%!j2@o)}?9P9QK{2hf^rxzMQWLfz3t9006}F^fxX#DBoBz zF0$4&T719(d(FP%CE6~aR<2sZsz{E(boj)$;sgs#$xfBHYj-wfu+ zSEwK(?|u}cxeMVEHp6&5`Xgp3gfds#Ded9Y^bfjv_dh(H$x8xsmEpwSC)XMYp0z|1Qw=v`v?Se-9(r;e12|pf|Y=mO$D0HqbzQ+?3rnZAoM` zHZmvG@W8}iqPiD`*1h4&^efAe|-WuMycWh;Mn^oFEYvrGf(JOqFVMFkO#n{)R^;zL zwU+JWeR%b|&#LpN&}#EIPDdkbG!ueK-G*eukebmih+bk5hq;S?O*wnrB%3P?u-3I) z>$&~5aCjyWXI)t71T)rU~y@!@dzRd3V=#)MjO8e%Zxi4Nu)t^=GfKA}#r8s6eW?d$N>W&W~^{sBF zr0y>%X!`K>(XO7~BOKmcJUE&DS^TNf2QHoQUaZZ2RaIG6vb5be0aZ3hC=N!p)0dz8 z#&Qteuc5jNh)ngEtcPF{BZNNTbhe-62m5bst-L#PS-Q?g6OH2>O; zV|!o6i9{$QbCEix_%AHYa(Gb+=H#IbXf}{qP4d?om+FhZq@kS2 zWMDWy`Wbz&x@%gn4L^fpA2AuEfBJey=ui*g2#T3L@^}#zo5Y*^R5UKlGw7|p!KdLy z<`?yl)IyOx zdsHt%eBKsv-@tP9`NXBwZFsAWrKK0d7M>>hxv$t5%}Bx&z|Y(BjN_hVx{;|ktX&Rk z3+%6bApP)R{TWk-{VXi3yOAJ4V=g|Y|AwDK_o62$t9^EWx|EKFq6zgf`YR5%_yT71 zWWqe#HiEUbrx71Rc+W*q`?bn0I^g3Q|2V;ze@PPq;-`?&Uq=LpSV+eyWsF93No)Oi>WkJEnx*< zNj(q*w2Ho-zR|y)HSjI~B(tj;U|?;Ss<-_@2(YmpDyLczS_yM4l$uD9Q_-cY_Wk

O2ZxRX;$_~(q(2&sV;PC~U6@pNy5Q#3eh8hWSoQ?;rf#WVdow*jV_5bcLr1=A3} zGaJ~m3GCvouu959Z`Pjm#z8F2n-o zTV@s!bEZ?X7!aN>aTPGdLfF47porw*3*s{OGpsoX6#21j{;Ey{MjkT7{bOt;0z7lP z5^K?>`H2){MX6&Z4BN#z%^=(PS^K^oDfk?@(%G2k?X-Rt2c;Vu3=%z`nIWEFp)Vo>#>wIXEHm7e1ytY`7Q zg#W{Z<=a%Qy!rXgMYrPSUw=P;E~M1GCMNL2ASnE95aBt85@a=mUR%u7o4OMYS|NJe z_1jRTFD_d_HsIgP_MK;r^FuwAsYoaeZ=-rpU6b zXJobwY!ieH`CFVy`B9sm?cF=)XamOF088^5!EH21>;ert^fa?Q9!MPk{6&hA!)2R> z!_i5^T5o*4;X*qsSre&uF+w|1d+U zu68LdxuNGtsgMrmDl(}SW*(Vz%M{WMl39|Ba@W<6aXOwSHE(m64DCXF1KljFOz!H? z`}lNgGmyG>3z)%p{lq9b7Aq-56RR=X+SpQ~JrCJvG``UyC!y76$~}GB4nA+r z&#@hDrvN)kq7Fq$hem^5kM*?K3##7J4QSIK@_$q3;w6@$_Ge{`N;v!8z|AQZ{JcH> zO&wUrAk?Le>RqmU_ZUP_En93K7@ zara=!bE@jKN1zs5U1`!CyHja_#s%HL+dByLZaiF#)$xoAn_u~K%XufU^{Hu6qD3Z+ zjQD@(hz$}csKc9^eXr?pZKdOTK)cOM84YqWV3+{M0#wfZAkveQ`0~?A6zARgoP@|AF>ewA}L$5y6VcsT5aMrVbaqxJl-az>_b;^2Z*i4D3s&>1mvpXSegplpyyM9st-#3bS%;qshRw%sZ+ z+_b)fkjXF@JOR;wg(HEhD%;=J`GU(K=dx978hb$oHPq&1!7w;+I`xGIwW(}%khx+<5NGJq-w=f3%FqE}z374&S=8FY6h&?JQyph$ z91gH+C29TxrvT&=ACRu=hzG_$GwQ7!f+wCXg+QIg6C&@V+~MqF$Ke$p-_dmUuE(8_ zrgB?}VlUC>FE+&74nQx?o8`Vy==}!Rb_tJAYN}6J8*L{h#$Pn>xbeUD7sN&>RN5JC zYfu}q2D5t!DS|Jtm#}xEu(nzn>BUKqfBn520Ce#$=DN=%%eUnw__l&8eq-h*=>IDL z!KlxF5#?u(MVS;Z7Ff`1%WQvP;lTnNbAekl@tJr}8lOHa`=*k(jgNbJh18$;qo9xi zx!je#?)O3=LQpvP+7=R>&kB3e={f*#(E{`v=*+I+{&lzG#@8<9wjA)Lq>uhyUd}f- zUXVuJv)I{%v`5-c#e}+{S0s0ZO@d!-1KXdM^$7@Azma^kIii!_p(Nml_ZGWazss}5 zfc@>+`1Q%6xb@jHXZyq*Pw?Z*X#rWFGOC|XpPt>R^?fLJi09Y~yJ2`*4GQ;f|H4@``U@5Sr8OP|n>w z{4t6C6Gx;M8(3LB-{oJLB_Lj!3pwm^6 z`RhwhEXRN;piK$g4IRK7v3n(`Vm-Z|j*w0VxpS`pbgza4R)+z&H zdht)^J>}+e%ex@<5z#lzofW2)U1OBEOI>4R$>|_j@;jAkW7*;tokkLX;?R>SD*P=I zc@LDA)dtX%!bSa!-#&454*ERZfsJ$y^k!Z!GaW8RaEG{NDB}eFFiB78a4Nvfnf6aM z71ilvGWZI73eQdzF0!Ja7Nr%->ln|EjvOFoV)e~usZKUd)>%yMh*we@giAz&Hluzj z`#H9)@RU6s2;!(=r$?d_MBHkIt zR!qdttPKO$$Hw~ygRdAFf3U1i+mJ@Ludi?k_8*}{G)7>I^$*a@5xC;xXJ~1``X+V! z^Ed`iwE^+gm3Op;ZKL(&=pNFZ4GmTQ*M_Hn9+{bpYm)@;43w)AD>aYu#tpNbY70C@ z1SA6aj^_>}@4}J8bdtAOVdCY&FJHrIgCWr^K>`Eg_aaM7JC+Dc;$^A?IWn% z{KKvF)3fMpG*UOTQh#&W3ZhGsK7vpA$s!w-F5Y{e&@oPq3s^R(yilzarC6`LUn$Sq zX%NplZ|3RG+QJ#jZ{-mUxvw?n;sH%7|Ppl2RMSd`BCIH>;UO-w%s4h$SiVM z+*K6=O`5{`st~{B@?sJ1aavJ<>I?KlF+0Ns-6~C}AMIClsQ+fIWkkoCaId(RCrHgS zi<>4iWRh~7!Sox=%jKBNDrkJ+Y`axFQ!3*vs&?N*``l*HIvl+-WQSQImtfZhf8d&| zc%>uz*tn8~`QAqQLLy|rl{uEje3DIhUA`N3o0|#la<vPd&IoM}7JMrXy61a#vNJr<_?vX9P;YREvBYn)78aFXmjMM8noL>KAKU5m9eH1PZ z@(oCya;cAGDO)eTMxL2$w)h0ka&9_b(KVKz_PNj{&YT4JfwjbkhyA;yEzZz~@0YVk z*D}~HO~f+Fm7!LB>&~hDRnN>q=&S|0qlD3LiIDM=m4P%VjE7TcQ{#KmYR|w@UA??B z$2!DQ%*p22o|Cd#s58y9^f4twy;9=zDOWkV*G@x*(s9O( zP>y;5KCL|@Ty~^SU~;{Lbtg@w0`Xu4`=@;wtvIc7Mt%1vzSwQn>ID;F`5));@9zXV z@mcGRtH(U;W{S}qrJH?}$<1|e;Lv0YzDPB2n4ixIrJ}Kt5c+cNk2yPe;%_!&JsM^) zS=I#Rh<7jCUpV$}^JwERprRDiaGmE~u%mGEEfSh#xv&v9uL4YunnkJT%3z_cW>d#d z(W9<;x38O}V2SREa9qmM7PGisQ}>(E4=cBJ1Z0~MkZJX-{<}XYd16)LLT1CK?L;I& zeO(JC=|@Xlyf?eg@8z-(04B82a?b-7q{*AuMu}Fgu15nM?HD;3?izkn_@WBy$4*|< zOmA1F66o!7fveWKZq?7zFAdqS+{2W`E9a|ewH8?uFh1qRDd!(o9nV~&ObV*{cx>i= z%={aAv!$&lDNM-82u5ufa&o*Q^c3fS0E)q za;Z#bZ{A?Gg*`Cq7NLzFF8i7#lantOA|}Z3#lx@{?+0b^DPP2?1zmk{t(cxC4^7JAo(o7))hjPm_V_am`CR|arxioIYqUmL z4^6;S7on$bJpn)Lb__lsz=Hc3cA~T(fn|#G`vd5UNe)$-Wu*HzMSp;!MV&u&eR^l zFj$=2vyd2=zroovNtlYu`S26h&GYV94}fFIozQ6)B(eU;m3tDXNC|)TUBw@r@|Enz zgvzKhQ<%fqT!0qPA>!EX$wj}8_J+5;%I{IV`<0YYMru|+F9kAR3IkMtZl`HqVD2N2FTxhJOw1ny{nz|Wq|zR`nz@jpa2J;+muU=Ao~pinR#l~DihbhkL4y5TAtqZp5)&r}NLM<8 zwN1l3ebD9kXxGNax3qhWil4A?NJjSNydMj><()nwL(}#ZHZO(b;1I~)kyuC_6bSda z)rGM2#CjL#S?NUWYuGQkn1sIAaL(r#-dY~~WI-MTL|9ZzkmRac7;WR<941aj8%sc$#Ny1-!) zn=SlPLhcWK$E}2VgkKl0eAFkad>D@pzWtBAX2%HQc5q=&`7?RXut)1GYa{V6)wyX? zc0IPFlHlc8O1mWdb$UCJ?Zg41rgT)`9@Y2oqIy@RBjl1m9<0+rzuI`y?$U}IE*nkS zN~+YtWz_kVT=2qoC}a1{XLP4UnY{d;(zl`E{dK#DnKdAD<+EqJemRmGS?})%ocT3xYej(ZpOPD}#LB7qNsh zCqjE0QyBHAN);_m(>Dh}3c9k>{T@JXh+5q%FEO=oS7MqPbL9)tcchyKLy%A6 z_Ko1rXpr%XIrdkqp69PS4-?t2!TgV?=?#tEJpEMMZCjGMI`l!SHJ=(;A1;GyfKrWXbK^i`d>FW220-XWJc&^YM z?^6SGxSw;!O{axtE&DRuv^Jr5zk6rwP@oMzhhs9i)`#AkCSofdf#cR_P}Tw{Mh&xUd%0a4)LJAbBi&ZZ zLm>nocaAROLCn|G%Dxfpd+mhljezqW5P*^H~dDaHkh+umkBkH8)7X5zS( zro!~9Mq!XZcoSp%c;VsJG=ZDi(5#fxT;(L0wk3R7;sXeq8X_~pGR>a^; z?ny-b9$@0!0~i~F9SFRt`U0UQer*z$gaUZNET({lh;yhmMj-C0LEx6#ZkMhqcugxayyA9xKcH%Ws!G03Gca4D;3MGjTGW zdH&z(E)K>`V2+M06eMh@?qSAa#Uj3Q>7iQhdB}3U;&!lho+}Q0>KC#@}QTeQpVW1}c!Dn@?mb~2FLfwe2 z-g=ozj-r8$xw~Ht#niM?J+aJF zunEQsez+d;4#lbtKd<*+*aRJdh_)mC;lW$m83{_fUa-^Vb2edZ)_1h9;dU6kO-!-3 z;quN~gm}a;iG465r1J9}xNPMtR##FW1Pu7rhKQONA44sztZ{3?vwR^aB*8D99Wgu$ z3^(YInZiin4W;Q5zCt_Xn-hyNV?Pmzq?5P` zcbL$VP7kOSp+QLPNpMc5lHaG|*vIj=m6j84>+1ZT#Btw{m)x`+-`(10sL$>uR$O&Q zJX?Kjc(aBfc~zI^m9Yii>TMfFBpA>iqUZHQ#6EMPfV z(uok0bQLM}!jeDdBnLe0nRJ4WaRW<7Oi2ynPZoFPLXXFVj*AX?1RUlXX#sW^UkU}mxre$ ze)8VoDItqzC18kE)w{GTDhrQvYJfL)Gpy?)SKZH5X+2G`Jttv z2k~hVKy&`n3v2#fvXnaVMeZ%6BrI1p)fDqR%c2A#?GklwIA)DEWR$3I-k%vxi za7=CvT37+Qtyjpi{s>dFFd$Jyc*PL0cO=|C;c{(q)O5euiGBziKIy-b4abhu876J7 z9zpFA5OH=X*cQ|Mp8D2}2c(;DAk)kx3ODEM3mJGhssIn9|MvM!1U}Czz=nH#%2UG7 z>Q650Pg-vdwj=eS_q(aM)Rkwwz%FEQ5!zhqknyHrQLb*asIdIESw$ z7m*&u-&iM#YgLP1P285~+>OO8BHU!Jz1Ph2xQz`|_Cb_|-7KQ7?7E_RxH*HGMMa@d z?=0K;;`TlVNxaP9bogpMYs&Y%k00?^11b zAZ)%{WUeE0lfmDgy1=5><=d*RUJtdW&VE!Ji!bHcvVq-%1b3bSBiRzVvkqtJ;IiVn z8uD@LrcJ=t9yZ8$WLLCBe%hKa>QS?|39AMR>oqNfC~GM!?i%Gukv!;#cR9a{TMIwd z0kUXi7QL!XN*+i#KdoMM#@u@Otd!r8Eg?kuX2B$;Bm9Lkf9O)*3)`I{z7rF=X zEYn_h6=Pt-N4R;>qYs|-l6jc)f+?dGGpXYDP4ENOxk5XLRod5rk_>2WcSO3Z5b*im z?!-z_n7%vC?fQ6p6#(?a1c-$->61Bg$mx%5UBc>!HInrV9-usG%ltOxeaFwq$s5PU z-FSd;&=B6`%0>cGcBlfaa@DD@Jz53w)u!;KBI(y_=-TmYL7*WLlEm0B@ZJ&2vM}M$ zjZ!rdUxb5I`aoiU^FY*PO8mP(s;)Q{zzxC8EZR=X2xuDC3i z?oCVNVq6z|rvQ3Zdq;9aX81#2a$UO@{Dt%!H*twe zB0WvpPmW3<=Ji&iA@`q^>(`!um;HXyBKU4*KFD=&AGEVej_jGLW)WU>WXDdDu`rl+ zv($x=H0rC7U$l{Fd`yUV^dVQ{Nb+#NfG%@(JwJb%PJG_UdC{23k_@G}t z_8<;2J~o#A3M=8%Fg4g?QI-&x_s6pBsp$>b6aE-W5XLBmFu;8QujF-Es|>IC8a@^? zzqmvAm`4p`kW3@$%@bV%nKg)bcVIltgi8o(cupg-|CgNR=VMce^`~|mI1-XTIqx} zQ3Gyn`5CbNH2-)pBTyLZLU135Zmm1MIi+4g*9QcnhJ|08+r`Jd=LoiwQ|z<=f<$LyJ&#G_XreTC0ykP|HoSX<&^Co+*?Ic~TklA3d(3v+ zlWYuF`~gw6qF7N-Odbis{Dl&}jP)~h=Xk3U_=Zp^$VO3LW7p)|xAwuZpCX~o+ox%I zZ(pdYg3Q_v+QC@oLdS}}u|sqmN|)AetgN=h&jkirAO%4pDbW&9jqS|8Z{_DWdO#ZB@3Uwjc&~$>{D*eQQ zT-bWaykSUfze4$3lTQC2g~Q`J*O^QzQ=3AWz znwf)39pbb{b@DWOv0Sc;Pv}bv@=2W#a-#<_ z>5AX$gwX&lQw^$&#d?S+f&8quX;IF;5*Tv9bCe2&=NayZ;blR7TO64n@#F5j=WOY3|HxfeQf8+ub~&axtF;W z&jKP|S&MdLxlmtMH|CC*@H~~d*|jN(z`}#})-x>bz9%^H5PIO|Wz?~G_g20)q@Qn2 zD3OZS;QT&vAwIri#0~IW02!4qjo3iaYQ&p~deM=EjcHZiWR|KZ$&3d_$g+ zYNeuHrdm=%*brkWTpR-=QrK?WCPMR>p>6*=!f6XD3RDo$MjCKz>Sr?$!o-7&VR$2+ zy|ytra=kYL`&TREjgJyZq&-rov|_D-Lz$tmV(kzqi|~)9v>|Ut8PD6j)RG2jDjV`i zgWT!q%AahG_v!c^k$8R&ZQ_4=1N=o~tI0tjF74ttV!!ND<&CAAU5l}sLp9o|516(x z?SUaewT0>);)}xu93zOZth9=HJC=vQFH#i1gUcl|Z6mAM!iHnGQ3YMgy;g+S zO2(YbT_R(e`=Ao=M+&zlgv2C=jF``DM2YIsD<~etN7fu*Vr$nvet{v2J_}oH?$GJ| zdUyKwh@Yv%3U?V54KlwGOE;M%8D!d(z&ot8pd`%oh zXr;VM0$mKAtFy4hXlbRIM;opNa@v=Vd13VI8DDUjdc067wrrB65q3K6rVth3Huj*P zlBY3`8wdilc*yaL-Xq%ucb`wi2y+Rv)z83RCR{?KA)~U<4|6Ep51dD>o=|fHQp|7> z-FJv`|4y}fziBJM;uay%>o(!b?^L9N!iK@ig60p*RmPbKoZxKk?-0@_+UHpGIYFh7 zOl>Mx@6HMZ$}IT6BLy*#LKfXx8!Nxn1{fCm~aDK*ek`PQr zV6!ZY-RQ54KQ9P=f>S2rXK;)Q{gJkYZNib=`_M6=&?Ec?Gd zWQzZ>J_t{FsvVmb1NRsOmAxM#4k2`8F)lb;6U-E**Ufiqp8_sFVF>99;MzJttYb zxq(&w>T@U6)gNWu0x^1B`vWmQVAYYi3|Wc7!9+yK?`%{PZ{ITmG5NQxpoafe#wt4G zOe9#`J5Y|sIkDul?~c1q+ifGQ7wGn&i^X>0fSBJ#rE2XA@Tc;AU6l! zgb_n?FQ*d`7_EJNH-nHRWcgt8Ef&MDA#-M1&a%b-oOgF*0-=4=UyBJZq>g-+aJ^n9 zYaq4gsLhL3we)zeGD=1d&5~==)}qQfqtKHil`(~{{C-Yj2NJO0Yh`BGrg1^hXD-4KM%~TTmX{;etRs}z zCv(NsiWktO@ds1<8D$*9MeI5(gaVmVsIuwrGOxNn1K`nF7cNv5ob}u0a{Z;Njy}wm zjBRt%S?Yw{Knd!L!I&s_F=C_+#uNsL7cwh}MBw`Sn~@LX&>J6nMEk#wALf7!aa@jTZI-KiqsTh}r6(xPcL2<()b zRw?{yqg*InGK0-X#VR3mOHqB8sswlB7^xJR=k z0~jclb#r*vGrWJaV2pS3YCBG}^U&)9biz&;;PZwp%Ma-L~spy2+jDuDNZ`<5l|?Uio4a0K*RL&ks$o zt!9@GBkqHqFA}@^l@Cv;8yd=mz6!hF;~NMl-v4pf%Fw|Uu3SD9m)Pz z&MoERHnDb6-iCK*z6LA0Ab^#ubno{tHvF5FeAtW{^pcIka0^rJ&y~HASK;Pshi5nL zRrp!gc%gnSZ2ljq)T#3SmP++2eIvmA)T6@6er<$~c*K`YHFd+yB4hXScW$9quloWz zY>>$KwUOoLFQ|UPPJ0GpS7|y74;B0p_p2&Qnbyc%F#sl25fuvdnEEyC3pS#kVf@D{)A zz^SvcXjBx^_md(0Cqq?iM(Sa(ykZP4Ayc?{ap}hopoqSS2k{U^|Hgn0#V@iHx=%(i zPH&Vmm*-({_JxZl{6t~|6&sxTxUXSv9MYXWv1kvp{fmB$yn43cm&bJOr$^=|hxz6w z{Fl>uIY0+C;K{Gr4~#&0<_XA8ilZ0raH2n8FftH^9*6b3n&AXOr^5dC?5B(^xsuYx zE6=nNGRCR1y9$*!c3}`R_T;K9_Miq<$Av%ZU5WlgJW*ONWw?zV%d<| zhYisL9_SiAO777RGt^0Nk+c{wohRd491S?(viUq2(2_8YSJSLoO!R9PcwIf;|5dKM zp9r&;f>a`a18_xLrQ>5yo@;k&u8Qh#=bTmrDVx#gXEl$1FoWa*|F0Yr- zkRveHv=Kft=$k_1_7lOnZ<1$~4m(_r{Qu$6saXDhd2~vb?MdMdjCDlR`2h$%HiSLv zxIjC$U=lC)MH zLps84QukAUALt9B7~Ix1xQ-iCiV<)PYy^<~V#DY}IINj!{*Q*21C9SQ zyqwx~xfw*;wg=btC__IFlk2C_b9MJSeoP=2vQ{OgeL}InHnu5&& zU2FQ3WqgQC1qlu}G8hXhTPA}Bqd`bqQt3c}bNN7tes1Cp615S@hhJxqCQj`*LxoA} z9i#{hHsV0Rv}AlTY(jkhpPY^adsKDrTv)oZidkq7+WFPn-lb$$OM1npycS)1;iItL=2{c3NlF8{^iXt)(SwHILT& z<8Fv2n_sk3`;FI!|5!CPtNv-#*r+mV`bf_R|d{}WrpL|(Zc6pDXZF8S zFMix4dy&d3o}CYT{g=il?C$y{vogG1z2PG!*HeFJVsa-#Q;YBD zujz&S9xsG#hkZkO5I++i?OlH+9u`gnLG-V~4thuswr)^rMEzyvt;9P6wp;u<3rk8| zYDqR5V_crA*zvEz@AFh+>EEFZh#w$dG_(7&^TM*lib zVs7r$>d4z^KHA0ANnVO@OJRg{ia-y2gw9#VK*2j|cx6qyFCLPDYB5-~&h6?WC3Qk* z0aRr{e`29uCc|O(c{Cjhptx8V<6kE4R=+R2dOVi50g2Z8YfiBr#GCyO(n&wPs?`6| zM(3G4Q3}^K@g@Dz?lGnHfqmtUo?^jTrNbjGhP05`GZGt*9S>qKJ|-0bCnqb)6u$N2 zwj22SAHn_qF!t7AQMK*bxQc)Z!h;|oB@KcMB{7tWbO|WkE!{bQk|HpO#DJ7YOScT& zF?2TqLzgq;kiP|w&-=c6@89?B?=Oyn!-KWF*IM^|UFUU1xTN;)c)+f79Hj}DNPItc zeG8g=*Ol9z?Jh)%ujhOHfe9%%=x<*aP2K;+_u-*igQ;P+Tbbo8sn0Bv^bsqs&kE)y zE6F7bJNXvf(9_4dlj>9|LVy-rlyI_YqWasMkG;s~F zsmunN1k8q?)_+inYr%90khp*dIr>TheC=RJU3@KWz7i#iWJgo}!v*NU1@5jdgnE$1 zNcx{U1{4^82$IQwIX6Fb<-f)SY^*NKd3U5E=gkLSb+4?r`MP~7Ghq^zQ@B0UIJr&# zkzA~ZjgY(pydGl zA6t&%zgvz6e_9UTQ&GWMNolE*-36A-{&{<6wOIFmi3UK~Aa~l`<#r_t_cg=kxy52* z4|&oRuj}z*L4b@fp`s%WmkN>I-2VpQRuZj|G@^A*AkZuKT?1_K@%CO)oa8}`HI2y{ z25GL_p*4={|L6Zkz=$6J&YEAvO-4Get}6V32GKT_hgqa$p_Oe%KTh7i6~)|F4p02- z*NkSSH@GV9pYj-`b8jxaJ)+GmX5OOd+Cyrc{8|awFFEm!))%1&#a(rOnR@p`w-xok z6=!Fa;z|VInA#5s<3kc=wX9IV0Mke1!r>^Othv$d9{wL9W-gqok|n`{h1NB3udA6n zf=V-t_CJn0`Den{Q|wJXKddC3ePl#mbV=IOfGyNThar~_lJa3>7Xk* zGAZ{Bbf%=4$zL6h3Gjg`>T9Zv#-N2H+RS+(y-DC@u&K0UE0if(`Xe<_hr-W(32DVw z-SXkIA@h^phILN*McuZpvk;&u-r|G?;G_7VbBVINvqPJ0SUSGH}IQmUsxmacBxfaRFyAq)a>Y7cO`69#F*zh9b*6AD?y z)43WGdC4nQmbq+LuOyn1wW(oT>GEaj1DRX@F>^s`5IdjVd@C#~0C2nCTIbQxw=qbJ z6vo^`hE;h>?yBZKuV);7%c663@*{mCzJ!ZWUQF!xc37jq=il)ukWhs2md5<(XV9OS z;EBtY$^D~&r@(izPkrStXx!7=VHS`o+oEtnp!e_{{W<@|(=Ia9g9t{=GyBTUVqF8r zR1nhokUH^mgT&81?mG$Z<*)bimHSs1$$#z4R_>qW5Q6u!t_(SZ%@8A|(;0Z%&$*2B zYDrnz)9yMxyHcaJCw>L6CGjbQf6%W(b60Gy z0;Vc4{l3(lu!PC>5=q<=EX;uTA78kh8&^;4w~C1w5RP&cg0_AGiT7v?{}C(Is;}_& z^<$B{dMvS|ZE9xa)ar}|IG^~q?L`SX>&8(5w6X_7>$?pfWoxXCJ^-&WZZyye2*_R3 z#nn>HahJV#@jcMJ>SKD#j4wl!9T%pLEE`|aG(K642J`(65rw*xL&oo~_YhobokO=d zQvu@6dZI?YANi$<$kWc8z21J0(R{!yn>?y1)}6Z& z`9gW%3R(di6o3K6#YCR;+P8k#{kdf$YT7E2DEhOeD4z6=rTnPNNzzEqCuJ`#}7s2%-JIdDNW=*l9@dJ-X#0w&p;nz;W;DEWnZv^UpLD#aNa+ zeNkyDto^CRVyY1jbYr0{Afv8W@IAKC^I9CHi!4YrQONs$L3;MZI_4_+(DR%x3lCigVKvz0bO*?D^Fy{9e(JbTn0C}h0 zV5v3$x<1u>uCc`bF3F_*|MhP0kdU{>%+VBhIASpT5$fR!NS{M*!SA*u_aSDcJIAN3 z%ngo<1eU+3ca0;ByU-Mq5}`H}J19>6h$w0em*7in5C5E8SLIpghdH3=h8#&ofkM;Ufsb1lwssMby|!~eJD3Xc zYXGxFZG#7q(i9kD86q4DMaT2qe!zFfGxiG)Pqi}|*FsgJO2`FU&-3bOU=>n1peQ}A z%f2fFo0JfE%4Gd3maD~At?nQ2lpO!>;fE3S%;}jakV^>UDi--=y49T>8G!QgRCHtW zz+i=K`rOdhvJZIityKClkn)utfL0&j-sch4{dOZ#aLtmG8Yn{3?{j!jK0hD)`y>V~ zNDW+Y5Qntx{O90>bF7h?N2+~qc#`15UGlB>B_}ddG)NM+y4zQ-j8lXs_y7G$YuW(K zm#)oe`gzO6zaPcl686Tr|1n|+1R}R3&!gv+R06|1`%)R~fLz3Z$HFfaU{>8GjVzsH zY%F45@n6zCXU&*yGeJ8mat*ke6g3UlEANG_mj)bpB_S^SZ(|J&e87Y3s$+P9V=g{9RKHFZ0ivixA^Q8-u%xBY^dJJDQsyXhfD(%9c@ute1iZi`wM3+pIaFQH z8)VlSgVh99yUn^v%T6>Yy?7`o9=>2Xpb1+QA8*yy-~Bvyk7r$E#tX0K_@vuKyMTa` zIf)M{7LN+Q?Bw-^loFH4pT7P_|Wmf!8khA?KGlsTb+|*R- zqjdDnPaLbW6qLu6;2sn}qrsL6A|mzC0_mp;@_)vG-~8vh0T#WnqU?G@<{ zevUVV33RVt12TSR(p3Pa^>cizZG}pclT~c%IaHh`WMv!J*V{vjz{ zc1NqHqiTEOHv zqHvHK`5yKMi-?Y+La{w;Ol@CE5889mzQ{LNp?jM`aTk$Lsa5W4r82by= zOEH=-`z>52)73&csXRbKL&7fZSDLD*(_}S%7-54g6b2ikTyr7NI|Q(vKt;H9Y;+8 zSgcMi`k&Uu+i`u2foUgoy5%IzO+CKQ0eY}U;xyo+dbmLU!2!^Pz1-aUEeu3xCW&b) zgy?;1(GsFEAF2l8=_EQTIR{jts@Rk((pNc=>k3{hBC3R*<(eKxZ|>-PWu=IyEOX|U zg$OHz+?Q-e*BCFB$XUBvXAW0O+i24dZf$g9tB50sl59-`bx3?tB0*?U&blC#n&VB* z=XsJ!)!%w+Sb$(Tlue4c^hc%}E|caZ$$M2s>V(XGdv3M$pCAv_o5LcX*s2qQlzuvH3#^ImjqpnJjYH6ULF`kkgp$+hVeWdfr9={EPx!TMajH&LbwF)ckZ(` zM<~T`Qu8Q|bqzP<7)xR5jkV80ah)|9w-K*F{*23S*EzV;mvFjy@pPi{=vBVYn}zN|RBj`# znoOVOeiwbmlH-6!8BKoFacObU%TsG@w10WQw4OOvJ8zXXaEc>sR5HTxCa+DZ#xR$Z zFB#iY(Iy_-qArKMo|}PG@0ed74tqwdN8QzOP5$uYUeydVXU^6Xc)4#3(&-#%j>0WOJ|+Ds}tN~p_&

@e+0q4;ofpRn{$86$D#eKBxq|xIfsDYt96hPR=ARJAIvRrgTLs@TaX9TuGJXIDa8>iShc_43Lb zEv>wTSl(^f9Ck3SCxh5J{NxkbF;C`4?zovGv{G#DJzyz!#@BFjbbH4C$@K_6cJQWS z6hrA9g_%<4; ztB3pWkl)@-Siwb4P?TO+GcmMh3X0A*<$aXiX6|L*BvawI91SP$ zkijV4w6>|L8=)Dt&2L@{G7Z>N%9(r6CM(D~@ipO17X9|uDHB{7w!xX9{7{V}UM1LT z{pecTIELdN2d1i9FX(h?cWm4>f~{~}A&TK(^jCKRS?|cxXwB?f`W%kr6*_}W8AYz+ z2UJ^=YnxB>G%rVcaS!6zy*evMm`#dl8kndH{f%@#{2A(8A!qTpST$cEn2?5xwkFZD&`>@RfsWzR<53*=&$@?mMFIB9rLhuw0doa1}zc(;KPY{#4Y`77ZeHs(JTgso!p}#_*F5 zeDZ~H=mXf8ahNOXUrhWQ-DPj|>6DpmKK)ee(zF7}&tT}4oG!$|YCSoXB$vnu2n-#! zJS{AcH=YVv<-uM15V)7lOSZ>Tg9)wgV-m{Ly6M;)iH)}S`o0i<;WWr{&f1uL$icfw zvz(jM9^10lr!8P6yvi{SRbvx(eY@V1c;R}w!lS)!qJxX;<3QeFzlIR7h_R`Fj%6LD z*k zMKByx4a;vWn&lr@HCcR?>{i*9vC*G=*8IVaP|1EWiWuGX<*lmp452!b>d3lFj7`fe zx1jg}e$mPqtE)ntP^_m^e{2GNQQImw?$JJ9eC0Rtr@8Bi{GfO3{RzAHyf(!4UEY8W zer)zV4D^>?(t|n_)gWd613izgYt3r=E0Zmc4NU2R*^2?NqPdZ)i%i(CXCX=7`&^(4 z7Aj=UQGbNm?jslQsk7eq2k(Qf*5W17pEZ8K<<{4j=Wz z{f@%Qgp0(zPdh$BrNrr)ReHmcsEk@Ua{^wa%hy>Yu?Uv2QR;*JnnTvyLl-t1!Nl{O z-nYWPL~g~sV%87{z7tb?@~G>bsfz2kAUMMDG2_>!SLtGUVr&ZW=yDED<++1Jcdgm# zt`3d2!u+}-nMKi(6+(`+_S)ZH|L)RYh(z!rjU1^fB+X#21@gm`X&19LGb??PBcqt6 z+Kl#oAAR_&@-BkFQO78GIZ<_rVANSsRVX>bu8c?BcIicK`sFJYj}TSKxZ-nqr-Z!) zFRNdJ2-^K9IHupl|88`6zj~je6|pz=z=u+tL?b!5q1V`qOO)pka&CpYfD8&uhr!q106j6z)Z4EAas zvf-Y*Mri}A5+Wm~@`*s^L6p&9Ja;1hUmPh8s1E41kgtDXvRu64($aByj~qW*SO>Xu z2obexxLmxGz>8c8v@b<=!OTtx+1}q*=nvy@g3oku#UJk zy~l4J)ffZjp=_}l-Oit|=9Ee=DgqjXej{xUe+@hgG1`vF zU#vT;30Z3mps-*P#?uptRbGaWhL{ZvY6&X_J(uZf;g=U;Y>NvmmZ|Db(Bq;q=)S9= z$RDJ~AXZx`nHe28-ft!l)vXcYiID(;MU_3Z(pI@4`yud{Qz!!~5Py1XQ} zn_vqEHgRMd%`w@w>ak2-vdJTrVGcQ_xu$llRd7vo+sHPe0U>Slj-~b&ovv2g)r$cO zNDZBF%FvHU=u}coozg$!FeB6JprS$MaQB1Fx4-nf8;+_UEKRkz}V zwHAzK>MJW$)06J1q&M@JO$R&iBPKG4+EE#{q&94}MWqM1_o15&&#KNa->6y6?<51p zOPYLQ!76n^8YEi_+D8eG{EoeQK|gQ68kzpy7#fSYi}S9Xc5SabKV2>y;kVJ)(N7fe zKYXCzEle_|GpXrnii3Zqyld+{5al<51GM z3=b`u8k`GOR!ViL$1>S73Qt~m`MAfb1^>l>ddMBxwV6R;h6RsiEz|&=uOtDFIydc> zA*ej|L*>JfS;*4;Eu5M^y5ZaS;c<}a)14Y`<=4lQpv?4kAhc-D;G6us*hrd)VDiAv zmrMRn4e>aDB(#bntov80c1E{Fj-K@ojt<+d^~La4r`vk4`{=fYXQ>e91{M3VR!KeA z!aS>xSG9P#0q2igC+QT^m7=noMW4>PJvIndBeNvS`J+9!Isqpp$;qE$oK|`$Hsl*? z&jS+6<~;^m@sj;wIDM_v(LvO&H-+YIN4QxCXpiiAY>)vteH&J*m3b?UX1Vsg97=wl zL1AS~Q~k%b6tu7yksbC0Q@4(hOel_gD|JHzPWay11fLMtx)FVgmRdh1`UDH(UoTPo z{%XhlvtQr9LbNsJbiwLxhXWyFuk1yn_uI=}k)<%hf0Jk}2I>3VM&gmW@N%rhO{P5ON|`%Yaj;z4gk>{4h|RX?ZUVZ?8v*if7bQ})>32RS{F?0cF**DLp3q# zWs&$RG6ReZ?rKdf3ZZdeZ#|qHA!fyDv8W+z%HM(;fME!s9Nq>8Y_ChbbvuhPf#5q* zMc^kd>=dwYRJz;Grq8DD`~#cbGqjI-dzX1i8r{3 z*P(hN2VBR?Z%THOK{cYDP=0BjvA2t2d3!8GWUKrx0FYF9O=U6b&iF`<{GNY_G-Q#( z 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�n3eFas9WN06x4N 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 DY8Mna literal 0 HcmV?d00001 diff --git a/doc/qmix_elements.png b/doc/showcase_qmix_elements.png similarity index 100% rename from doc/qmix_elements.png rename to doc/showcase_qmix_elements.png diff --git a/doc/qt_design_studio.png b/doc/showcase_qt_design_studio.png similarity index 100% rename from doc/qt_design_studio.png rename to doc/showcase_qt_design_studio.png diff --git a/doc/qtcreator.png b/doc/showcase_qtcreator.png similarity index 100% rename from doc/qtcreator.png rename to doc/showcase_qtcreator.png From c78cc17730844ea044b11546c13330d8707bb0cf Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 18 Aug 2020 10:48:35 +0200 Subject: [PATCH 04/34] Properly persist dock area HideSingleWidgetTitleBar flag (and all other dock area flags) --- demo/MainWindow.cpp | 4 ++-- src/DockAreaWidget.cpp | 45 ++++++++++++++++++++++++++++--------- src/DockAreaWidget.h | 35 ++++++++++++++++++++++++----- src/DockContainerWidget.cpp | 6 +++++ src/DockManager.h | 2 +- 5 files changed, 73 insertions(+), 19 deletions(-) diff --git a/demo/MainWindow.cpp b/demo/MainWindow.cpp index a4cb640..5127242 100644 --- a/demo/MainWindow.cpp +++ b/demo/MainWindow.cpp @@ -400,8 +400,8 @@ void MainWindowPrivate::createContent() ads::CDockComponentsFactory::setFactory(new CCustomComponentsFactory()); auto TopDockArea = DockManager->addDockWidget(ads::TopDockWidgetArea, FileSystemWidget); // Uncomment the next line if you would like to test the - // setHideSingleWidgetTitleBar() functionality - // TopDockArea->setHideSingleWidgetTitleBar(true); + // HideSingleWidgetTitleBar functionality + // TopDockArea->setDockAreaFlag(ads::CDockAreaWidget::HideSingleWidgetTitleBar, true); ads::CDockComponentsFactory::resetDefaultFactory(); // We create a calendar widget and clear all flags to prevent the dock area diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index dad429d..092f997 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -250,8 +250,8 @@ struct DockAreaWidgetPrivate CDockManager* DockManager = nullptr; bool UpdateTitleBarButtons = false; DockWidgetAreas AllowedAreas = DefaultAllowedAreas; - bool HideSingleWidgetTitleBar = false; QSize MinSizeHint; + CDockAreaWidget::DockAreaFlags Flags{CDockAreaWidget::DefaultFlags}; /** * Private data constructor @@ -747,7 +747,7 @@ void CDockAreaWidget::updateTitleBarVisibility() { bool Hidden = Container->hasTopLevelDockWidget() && (Container->isFloating() || CDockManager::testConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar)); - Hidden |= (d->HideSingleWidgetTitleBar && openDockWidgetsCount() == 1); + Hidden |= (d->Flags.testFlag(HideSingleWidgetTitleBar) && openDockWidgetsCount() == 1); d->TitleBar->setVisible(!Hidden); } } @@ -772,12 +772,16 @@ void CDockAreaWidget::saveState(QXmlStreamWriter& s) const auto CurrentDockWidget = currentDockWidget(); QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : ""; s.writeAttribute("Current", Name); - auto AllowedAreas = allowedAreas(); - // To keep the saved XML data small, we only save the allowed areas if - // the value is different from the default value - if (AllowedAreas != DefaultAllowedAreas) + // To keep the saved XML data small, we only save the allowed areas and the + // dock area flags if the values are different from the default values + if (d->AllowedAreas != DefaultAllowedAreas) { - s.writeAttribute("AllowedAreas", QString::number(AllowedAreas, 16)); + 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); @@ -872,11 +876,32 @@ DockWidgetAreas CDockAreaWidget::allowedAreas() const return d->AllowedAreas; } + //============================================================================ -void CDockAreaWidget::setHideSingleWidgetTitleBar(bool hide) +CDockAreaWidget::DockAreaFlags CDockAreaWidget::dockAreaFlags() const { - d->HideSingleWidgetTitleBar = hide; - updateTitleBarVisibility(); + 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); } diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index 3deada4..337eac2 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -143,6 +143,16 @@ protected slots: public: using Super = QFrame; + /** + * Dock area related flags + */ + enum eDockAreaFlag + { + HideSingleWidgetTitleBar = 0x0001, + DefaultFlags = 0x0000 + }; + Q_DECLARE_FLAGS(DockAreaFlags, eDockAreaFlag) + /** * Default Constructor */ @@ -272,17 +282,30 @@ public: */ DockWidgetAreas allowedAreas() const; - /** - * Will hide the title bar when set to true and there is only one - * dock widget in this area - */ - void setHideSingleWidgetTitleBar(bool hide); - /** * 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); + public slots: /** * This activates the tab for the given tab index. diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index c3eecf6..4d716c6 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -947,6 +947,12 @@ bool DockContainerWidgetPrivate::restoreDockArea(CDockingStateReader& s, { 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()) diff --git a/src/DockManager.h b/src/DockManager.h index 2f1df43..b682c43 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -513,7 +513,7 @@ signals: /** * This signal is emitted just before the given dock widget is removed - * from the + * from the dock manager */ void dockWidgetAboutToBeRemoved(ads::CDockWidget* DockWidget); From c6cf9487ba264fe0647c2e988ed3995d400e7e34 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 18 Aug 2020 20:36:02 +0200 Subject: [PATCH 05/34] Added maximize button svg icon --- src/images/maximize-button-focused.svg | 145 ++++++++++++++++++++++++ src/images/maximize-button.svg | 145 ++++++++++++++++++++++++ src/images/restore-button-focused.svg | 150 +++++++++++++++++++++++++ src/images/restore-button.svg | 150 +++++++++++++++++++++++++ 4 files changed, 590 insertions(+) create mode 100644 src/images/maximize-button-focused.svg create mode 100644 src/images/maximize-button.svg create mode 100644 src/images/restore-button-focused.svg create mode 100644 src/images/restore-button.svg diff --git a/src/images/maximize-button-focused.svg b/src/images/maximize-button-focused.svg new file mode 100644 index 0000000..cdbb56d --- /dev/null +++ b/src/images/maximize-button-focused.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Jemis Mali + + + + + image/svg+xml + + + + + + diff --git a/src/images/maximize-button.svg b/src/images/maximize-button.svg new file mode 100644 index 0000000..4084eb8 --- /dev/null +++ b/src/images/maximize-button.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Jemis Mali + + + + + image/svg+xml + + + + + + diff --git a/src/images/restore-button-focused.svg b/src/images/restore-button-focused.svg new file mode 100644 index 0000000..45b32e9 --- /dev/null +++ b/src/images/restore-button-focused.svg @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Jemis Mali + + + + + image/svg+xml + + + + + + diff --git a/src/images/restore-button.svg b/src/images/restore-button.svg new file mode 100644 index 0000000..46175d4 --- /dev/null +++ b/src/images/restore-button.svg @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Jemis Mali + + + + + image/svg+xml + + + + + + From c44d0c87e3f2f2f49bf89c70cbae15f816682549 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 19 Aug 2020 13:38:53 +0200 Subject: [PATCH 06/34] Fixed broken SimpleExample application --- examples/simple/MainWindow.cpp | 78 +--------------------------------- examples/simple/MainWindow.h | 6 +-- 2 files changed, 3 insertions(+), 81 deletions(-) diff --git a/examples/simple/MainWindow.cpp b/examples/simple/MainWindow.cpp index 6779b3a..46e24b3 100644 --- a/examples/simple/MainWindow.cpp +++ b/examples/simple/MainWindow.cpp @@ -9,7 +9,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { - /*ui->setupUi(this); + ui->setupUi(this); // Create the dock manager. Because the parent parameter is a QMainWindow // the dock manager registers itself as the central widget. @@ -32,67 +32,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);*/ - - ui->setupUi(this); - - // Create the dock manager. Because the parent parameter is a QMainWindow - // the dock manager registers itself as the central widget. - m_DockManager1 = new ads::CDockManager(this); - - // Create example content label - this can be any application specific - // widget - ads::CDockWidget* DockWidget; - { - QLabel* l = new QLabel(); - l->setWordWrap(true); - l->setAlignment(Qt::AlignTop | Qt::AlignLeft); - l->setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. "); - - // Create a dock widget with the title Label 1 and set the created label - // as the dock widget content - DockWidget = new ads::CDockWidget("Label 1"); - DockWidget->setWidget(l); - } - - ads::CDockWidget* DockWidget2; - { - QLabel* l = new QLabel(); - l->setWordWrap(true); - l->setAlignment(Qt::AlignTop | Qt::AlignLeft); - l->setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. "); - - // Create a dock widget with the title Label 1 and set the created label - // as the dock widget content - DockWidget2 = new ads::CDockWidget("Label 2"); - DockWidget2->setWidget(l); - } - - - // Add the toggleViewAction of the dock widget to the menu to give - // the user the possibility to show the dock widget if it has been closed - ui->menuView->addAction(DockWidget->toggleViewAction()); - - // Add the dock widget to the top dock widget area - m_DockManager1->addDockWidget(ads::TopDockWidgetArea, DockWidget); - - - auto funcRemoveFirstManager = [=]() - { - m_DockManager1->removeDockWidget(DockWidget); - - delete m_DockManager1; - m_DockManager1 = nullptr; - }; - QTimer::singleShot(3000, funcRemoveFirstManager); - - auto funcAddSecondManager = [=]() - { - m_DockManager2 = new ads::CDockManager(this); - - m_DockManager2->addDockWidget(ads::TopDockWidgetArea, DockWidget); - }; - QTimer::singleShot(5000, funcAddSecondManager); + m_DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget); } MainWindow::~MainWindow() @@ -100,17 +40,3 @@ MainWindow::~MainWindow() delete ui; } - -void MainWindow::closeEvent(QCloseEvent *event) -{ - QMainWindow::closeEvent(event); - if (m_DockManager1) - { - m_DockManager1->deleteLater(); - } - - if (m_DockManager2) - { - m_DockManager2->deleteLater(); - } -} diff --git a/examples/simple/MainWindow.h b/examples/simple/MainWindow.h index e1c6176..8d90885 100644 --- a/examples/simple/MainWindow.h +++ b/examples/simple/MainWindow.h @@ -18,13 +18,9 @@ public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); -protected: - virtual void closeEvent(QCloseEvent *event) override; - private: Ui::MainWindow *ui; - ads::CDockManager* m_DockManager1; - ads::CDockManager* m_DockManager2; + ads::CDockManager* m_DockManager; }; #endif // MAINWINDOW_H From 121248c3c596ce13109b033d23d184d2eaf9428b Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 19 Aug 2020 13:49:20 +0200 Subject: [PATCH 07/34] Improved documentation --- src/DockWidget.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DockWidget.h b/src/DockWidget.h index 72f2341..b9572b0 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -149,10 +149,10 @@ public: { DockWidgetClosable = 0x01,///< dock widget has a close button DockWidgetMovable = 0x02,///< dock widget is movable and can be moved to a new position in the current dock container - DockWidgetFloatable = 0x04, + DockWidgetFloatable = 0x04,///< dock widget can be dragged into a floating window DockWidgetDeleteOnClose = 0x08, ///< deletes the dock widget when it is closed - CustomCloseHandling = 0x10, - DockWidgetFocusable = 0x20, + CustomCloseHandling = 0x10, ///< clicking the close button will not close the dock widget but emits the closeRequested() signal instead + DockWidgetFocusable = 0x20, ///< if this is enabled, a dock widget can get focus highlighting DefaultDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable | DockWidgetFocusable, AllDockWidgetFeatures = DefaultDockWidgetFeatures | DockWidgetDeleteOnClose | CustomCloseHandling, NoDockWidgetFeatures = 0x00 From 04b4ff8b4b3da29c35576c75278212568913a35c Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 19 Aug 2020 15:16:13 +0200 Subject: [PATCH 08/34] Fixed typo in DockWidget documentation --- src/DockWidget.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DockWidget.h b/src/DockWidget.h index b9572b0..ccae27e 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -197,7 +197,7 @@ public: * 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, the set the minimumSizeHintMode() to + * content widget, then set the minimumSizeHintMode() to * MinimumSizeHintFromContent. */ enum eMinimumSizeHintMode From 8361f90dcecbb2eb0c754dbfc68e48d10e6ca0bf Mon Sep 17 00:00:00 2001 From: shelomentsev Date: Thu, 20 Aug 2020 15:56:37 +0500 Subject: [PATCH 09/34] Delete widgets without parents in CDockAreaLayout. (#241) --- src/DockAreaWidget.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 092f997..1696e1f 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -86,6 +86,18 @@ public: } + /** + * Delete widgets without parents in this layout + */ + ~CDockAreaLayout() + { + for(auto Widget : m_Widgets) + { + if(!Widget->parent()) + delete Widget; + } + } + /** * Returns the number of widgets in this layout */ From a4d281dbb6d5daee746d36a7ccfa971308c2374f Mon Sep 17 00:00:00 2001 From: shelomentsev Date: Thu, 20 Aug 2020 15:58:15 +0500 Subject: [PATCH 10/34] Floating window fixes. (#239) * Don't show a CFloatingDockContainer if all its CDockWidget were hidden before its first shown. * Destroy empty CFloatingDockContainer when removing CDockWidget via removeDockWidget function. --- src/DockAreaWidget.cpp | 8 ++++++++ src/DockManager.cpp | 9 ++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 1696e1f..a12bcb0 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -478,6 +478,14 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget) 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) { diff --git a/src/DockManager.cpp b/src/DockManager.cpp index 95e4fac..cd109c6 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -653,7 +653,14 @@ void CDockManager::showEvent(QShowEvent *event) for (auto FloatingWidget : d->UninitializedFloatingWidgets) { - FloatingWidget->show(); + for(CDockWidget* DockWidget : FloatingWidget->dockWidgets()) + { + if(!DockWidget->isClosed()) + { + FloatingWidget->show(); + break; + } + } } d->UninitializedFloatingWidgets.clear(); } From 1a11e5ddcdf82f62eab98b40fc7a2cf2a27ef3a8 Mon Sep 17 00:00:00 2001 From: hulswit Date: Thu, 20 Aug 2020 16:36:02 +0200 Subject: [PATCH 11/34] Central Widget concept added Adde option to set a dock widget as central widget. It influences resizing behavior of the splitters. The central widget will be stretched with the main window and remaing dock widgets and threir respective areas will be resized only vertically if docked left or right and horizontaly if docked top or bottom --- examples/CMakeLists.txt | 3 +- examples/centralWidget/CMakeLists.txt | 26 +++ examples/centralWidget/centralWidget.pro | 56 ++++++ examples/centralWidget/digitalclock.cpp | 27 +++ examples/centralWidget/digitalclock.h | 17 ++ examples/centralWidget/main.cpp | 11 ++ examples/centralWidget/mainwindow.cpp | 237 +++++++++++++++++++++++ examples/centralWidget/mainwindow.h | 32 +++ examples/centralWidget/mainwindow.ui | 30 +++ examples/examples.pro | 1 + src/DockAreaWidget.cpp | 11 ++ src/DockAreaWidget.h | 7 +- src/DockContainerWidget.cpp | 132 ++++++++++--- src/DockContainerWidget.h | 6 + src/DockManager.cpp | 18 ++ src/DockManager.h | 14 +- src/DockSplitter.cpp | 14 ++ src/DockSplitter.h | 5 + src/DockWidget.cpp | 6 + src/DockWidget.h | 5 + 20 files changed, 629 insertions(+), 29 deletions(-) create mode 100644 examples/centralWidget/CMakeLists.txt create mode 100644 examples/centralWidget/centralWidget.pro create mode 100644 examples/centralWidget/digitalclock.cpp create mode 100644 examples/centralWidget/digitalclock.h create mode 100644 examples/centralWidget/main.cpp create mode 100644 examples/centralWidget/mainwindow.cpp create mode 100644 examples/centralWidget/mainwindow.h create mode 100644 examples/centralWidget/mainwindow.ui diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d1a4516..3b24252 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -2,4 +2,5 @@ cmake_minimum_required(VERSION 3.5) project(QtADSExamples LANGUAGES CXX VERSION ${VERSION_SHORT}) add_subdirectory(simple) add_subdirectory(sidebar) -add_subdirectory(deleteonclose) \ No newline at end of file +add_subdirectory(deleteonclose) +add_subdirectory(centralWidget) \ No newline at end of file diff --git a/examples/centralWidget/CMakeLists.txt b/examples/centralWidget/CMakeLists.txt new file mode 100644 index 0000000..4cc7de9 --- /dev/null +++ b/examples/centralWidget/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.5) +project(ads_example_centralwidget VERSION ${VERSION_SHORT}) +find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +add_executable(CentralWidgetExample WIN32 + main.cpp + mainwindow.cpp + mainwindow.ui + digitalclock.cpp +) +target_include_directories(CentralWidgetExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src") +target_link_libraries(CentralWidgetExample PRIVATE qtadvanceddocking) +target_link_libraries(CentralWidgetExample PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets) +set_target_properties(CentralWidgetExample PROPERTIES + AUTOMOC ON + AUTORCC ON + AUTOUIC ON + CXX_STANDARD 14 + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS OFF + VERSION ${VERSION_SHORT} + EXPORT_NAME "Qt Advanced Docking System Central Widget Example" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/bin" +) diff --git a/examples/centralWidget/centralWidget.pro b/examples/centralWidget/centralWidget.pro new file mode 100644 index 0000000..f39896d --- /dev/null +++ b/examples/centralWidget/centralWidget.pro @@ -0,0 +1,56 @@ +ADS_OUT_ROOT = $${OUT_PWD}/../.. + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = CentralWidgetExample +DESTDIR = $${ADS_OUT_ROOT}/lib +TEMPLATE = app +CONFIG += c++14 +CONFIG += debug_and_release + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + digitalclock.cpp \ + main.cpp \ + mainwindow.cpp + +HEADERS += \ + digitalclock.h \ + mainwindow.h + +FORMS += \ + mainwindow.ui + +LIBS += -L$${ADS_OUT_ROOT}/lib + +# Dependency: AdvancedDockingSystem (shared) +CONFIG(debug, debug|release){ + win32 { + LIBS += -lqtadvanceddockingd + } + else:mac { + LIBS += -lqtadvanceddocking_debug + } + else { + LIBS += -lqtadvanceddocking + } +} +else{ + LIBS += -lqtadvanceddocking +} + +INCLUDEPATH += ../../src +DEPENDPATH += ../../src + diff --git a/examples/centralWidget/digitalclock.cpp b/examples/centralWidget/digitalclock.cpp new file mode 100644 index 0000000..2752d6b --- /dev/null +++ b/examples/centralWidget/digitalclock.cpp @@ -0,0 +1,27 @@ +#include "digitalclock.h" + +#include +#include + +CDigitalClock::CDigitalClock(QWidget *parent) + : QLCDNumber(parent) +{ + setDigitCount(8); + setSegmentStyle(Filled); + + QTimer *timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, &CDigitalClock::showTime); + timer->start(1000); + + showTime(); + + setWindowTitle(tr("Digital Clock")); + resize(150, 60); +} + +void CDigitalClock::showTime() +{ + QTime time = QTime::currentTime(); + QString text = time.toString("hh:mm:ss"); + display(text); +} diff --git a/examples/centralWidget/digitalclock.h b/examples/centralWidget/digitalclock.h new file mode 100644 index 0000000..4c155d3 --- /dev/null +++ b/examples/centralWidget/digitalclock.h @@ -0,0 +1,17 @@ +#ifndef DIGITALCLOCK_H +#define DIGITALCLOCK_H + +#include + +class CDigitalClock : public QLCDNumber +{ + Q_OBJECT + +public: + CDigitalClock(QWidget *parent = nullptr); + +private slots: + void showTime(); +}; + +#endif // DIGITALCLOCK_H diff --git a/examples/centralWidget/main.cpp b/examples/centralWidget/main.cpp new file mode 100644 index 0000000..3f073f3 --- /dev/null +++ b/examples/centralWidget/main.cpp @@ -0,0 +1,11 @@ +#include "mainwindow.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + CMainWindow w; + w.show(); + return a.exec(); +} diff --git a/examples/centralWidget/mainwindow.cpp b/examples/centralWidget/mainwindow.cpp new file mode 100644 index 0000000..cc4a8d9 --- /dev/null +++ b/examples/centralWidget/mainwindow.cpp @@ -0,0 +1,237 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "digitalclock.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DockAreaWidget.h" +#include "DockAreaTitleBar.h" +#include "DockAreaTabBar.h" +#include "FloatingDockContainer.h" +#include "DockComponentsFactory.h" + +using namespace ads; + +const QString CMainWindow::kTableTopLayout = "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "344 272 " + "" + "" + "" + "" + "" + "" + "" + "258 758 258 " + "" + "" + "" + "" + "52 621 52 " + "" + "" + ""; + +const QString CMainWindow::kTableBottomLayout = "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "258 758 258 " + "" + "" + "" + "" + "" + "" + "" + "621 52 52 " + "" + "" + ""; + +CMainWindow::CMainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CMainWindow) +{ + ui->setupUi(this); + CDockManager::setConfigFlag(CDockManager::OpaqueSplitterResize, true); + CDockManager::setConfigFlag(CDockManager::XmlCompressionEnabled, false); + DockManager = new CDockManager(this); + QCalendarWidget* calendar = new QCalendarWidget(); + CDockWidget* CentralDockWidget = new CDockWidget("CentralWidget"); + CentralDockWidget->setWidget(calendar); + CentralDockWidget->setFeature(CDockWidget::DockWidgetClosable, false); + CentralDockWidget->setFeature(CDockWidget::DockWidgetMovable, false); + CentralDockWidget->setFeature(CDockWidget::DockWidgetFloatable, false); + auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget); + CentralDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); + CentralDockArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); + + QTreeView* fileTree = new QTreeView(); + fileTree->setFrameShape(QFrame::NoFrame); + QFileSystemModel* fileModel = new QFileSystemModel(fileTree); + fileModel->setRootPath(QDir::currentPath()); + fileTree->setModel(fileModel); + CDockWidget* DataDockWidget = new CDockWidget("File system"); + DataDockWidget->setWidget(fileTree); + DataDockWidget->resize(150, 250); + DataDockWidget->setMinimumSize(100, 250); + auto* fileArea = DockManager->addDockWidget(DockWidgetArea::LeftDockWidgetArea, DataDockWidget, CentralDockArea); + + QTableWidget* table = new QTableWidget(); + table->setColumnCount(3); + table->setRowCount(10); + CDockWidget* TableDockWidget = new CDockWidget("Table"); + TableDockWidget->setWidget(table); + TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); + TableDockWidget->resize(250, 150); + TableDockWidget->setMinimumSize(200,150); + DockManager->addDockWidget(DockWidgetArea::BottomDockWidgetArea, TableDockWidget, fileArea); + + QTableWidget* propertiesTable = new QTableWidget(); + table->setColumnCount(3); + table->setRowCount(10); + CDockWidget* PropertiesDockWidget = new CDockWidget("Properties"); + PropertiesDockWidget->setWidget(propertiesTable); + PropertiesDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); + PropertiesDockWidget->resize(250, 150); + PropertiesDockWidget->setMinimumSize(200,150); + DockManager->addDockWidget(DockWidgetArea::RightDockWidgetArea, PropertiesDockWidget, CentralDockArea); + + QWidget* timeLineWidget = new QWidget(); + QHBoxLayout* timelineLayout = new QHBoxLayout(timeLineWidget); + QRadioButton* radioDockTop = new QRadioButton("Top", timeLineWidget); + QRadioButton* radioDockBottom = new QRadioButton("Bottom", timeLineWidget); + radioDockTop->setChecked(true); + timelineLayout->addWidget(new QLabel("Fixed height Dock widget.")); + timelineLayout->addStretch(1); + timelineLayout->addWidget(new QLabel("Apply predefined perspective: ", this)); + timelineLayout->addWidget(radioDockTop); + timelineLayout->addWidget(radioDockBottom); + TimelineDockWidget = new CDockWidget("Timeline"); + TimelineDockWidget->setWidget(timeLineWidget); +// TimelineDockWidget->setResizeMode(CDockWidget::eResizeMode::ResizeHorizontal); + TimelineDockWidget->setFeature(CDockWidget::DockWidgetClosable, false); + TimelineDockWidget->setFeature(CDockWidget::DockWidgetMovable, false); + TimelineDockWidget->setFeature(CDockWidget::DockWidgetFloatable, false); + TimelineDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); + TimelineDockWidget->setMinimumSize(QSize(50, 50)); + TimelineDockWidget->setFixedHeight(50); + auto *TimelineDockArea = DockManager->addDockWidget(DockWidgetArea::TopDockWidgetArea, TimelineDockWidget); + TimelineDockArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); + TimelineDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); + connect(radioDockTop, &QRadioButton::toggled, [this](bool checked){ + bool ok = true; + if(!checked) + { + ok = DockManager->restoreState(kTableBottomLayout.toUtf8()); + } + else + { + ok = DockManager->restoreState(kTableTopLayout.toUtf8()); + } + if(!ok) + { + QMessageBox msgBox; + msgBox.setText("Failed to apply perspective!"); + msgBox.exec(); + } + }); + + QWidget* statusWidget = new QWidget(); + QHBoxLayout* statusLayout = new QHBoxLayout(statusWidget); + statusLayout->setSpacing(10); + CDigitalClock* clock = new CDigitalClock(statusWidget); + statusLayout->addWidget(new QLabel("Status Bar")); + QPushButton* OpenPerspectiveButton = new QPushButton("Open Perspective", statusWidget); + connect(OpenPerspectiveButton, &QPushButton::clicked, [this](){ + QString PerspectiveName = QFileDialog::getOpenFileName(this, "Open Perspective", "", "Perspective files (*.xml)"); + if (PerspectiveName.isEmpty()) + { + return; + } + + QFile stateFile(PerspectiveName); + stateFile.open(QIODevice::ReadOnly); + QByteArray state = stateFile.readAll(); + stateFile.close(); + if(!DockManager->restoreState(state)) + { + QMessageBox msgBox; + msgBox.setText("Failed to apply perspective " + stateFile.fileName()); + msgBox.exec(); + } + }); + QPushButton* SavePerspectiveButton = new QPushButton("Create Perspective", statusWidget); + connect(SavePerspectiveButton, &QPushButton::clicked, [this](){ + QString PerspectiveName = QInputDialog::getText(this, "Save Perspective", "Enter unique name:"); + if (PerspectiveName.isEmpty()) + { + return; + } + + QByteArray state = DockManager->saveState(); + QFile stateFile(PerspectiveName + ".xml"); + stateFile.open(QIODevice::WriteOnly); + stateFile.write(state); + stateFile.close(); + }); + statusLayout->addWidget(OpenPerspectiveButton); + statusLayout->addWidget(SavePerspectiveButton); + statusLayout->addStretch(1); + statusLayout->addWidget(clock); + CDockWidget* StatusDockWidget = new CDockWidget("Status"); + StatusDockWidget->setWidget(statusWidget); +// StatusDockWidget->setResizeMode(CDockWidget::eResizeMode::ResizeHorizontal); + StatusDockWidget->setFeature(CDockWidget::DockWidgetClosable, false); + StatusDockWidget->setFeature(CDockWidget::DockWidgetMovable, false); + StatusDockWidget->setFeature(CDockWidget::DockWidgetFloatable, false); + StatusDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); + StatusDockWidget->setMinimumSize(QSize(50, 50)); + StatusDockWidget->setFixedHeight(50); + StatusDockArea = DockManager->addDockWidget(DockWidgetArea::BottomDockWidgetArea, StatusDockWidget); + StatusDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); + StatusDockArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); +} + +CMainWindow::~CMainWindow() +{ + delete ui; +} + diff --git a/examples/centralWidget/mainwindow.h b/examples/centralWidget/mainwindow.h new file mode 100644 index 0000000..cbd05b0 --- /dev/null +++ b/examples/centralWidget/mainwindow.h @@ -0,0 +1,32 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +#include "DockManager.h" +#include "DockAreaWidget.h" +#include "DockWidget.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class CMainWindow; } +QT_END_NAMESPACE + +class CMainWindow : public QMainWindow +{ + Q_OBJECT + +public: + CMainWindow(QWidget *parent = nullptr); + ~CMainWindow(); + +private: + static const QString kTableTopLayout; + static const QString kTableBottomLayout; + + Ui::CMainWindow *ui; + + ads::CDockManager* DockManager; + ads::CDockAreaWidget* StatusDockArea; + ads::CDockWidget* TimelineDockWidget; +}; +#endif // MAINWINDOW_H diff --git a/examples/centralWidget/mainwindow.ui b/examples/centralWidget/mainwindow.ui new file mode 100644 index 0000000..73ae7b1 --- /dev/null +++ b/examples/centralWidget/mainwindow.ui @@ -0,0 +1,30 @@ + + + CMainWindow + + + + 0 + 0 + 1284 + 757 + + + + MainWindow + + + + + + 0 + 0 + 1284 + 21 + + + + + + + diff --git a/examples/examples.pro b/examples/examples.pro index 68419c9..de8cf7f 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -1,6 +1,7 @@ TEMPLATE = subdirs SUBDIRS = \ + centralwidget \ simple \ sidebar \ deleteonclose diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 092f997..6d3b8c9 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -440,6 +440,7 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget, DockWidget->toggleViewInternal(true); } d->updateTitleBarButtonStates(); + updateTitleBarVisibility(); } @@ -946,6 +947,16 @@ CDockAreaTitleBar* CDockAreaWidget::titleBar() const } +//============================================================================ +bool CDockAreaWidget::isCentralWidgetArea() +{ + if(dockWidgetsCount()!=1) + return false; + + return dockManager()->centralWidget()==dockWidgets()[0]; +} + + //============================================================================ QSize CDockAreaWidget::minimumSizeHint() const { diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index 337eac2..0c4653a 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -153,7 +153,7 @@ public: }; Q_DECLARE_FLAGS(DockAreaFlags, eDockAreaFlag) - /** + /** * Default Constructor */ CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent); @@ -306,6 +306,11 @@ public: */ void setDockAreaFlag(eDockAreaFlag Flag, bool On); + /** + * Returns true if the area contains the central widget of it's manager. + */ + bool isCentralWidgetArea(); + public slots: /** * This activates the tab for the given tab index. diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 4d716c6..56aef07 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -322,6 +322,17 @@ public: Splitter->setSizes(SplitterSizes); } + /** + * This finction forces the dock container widget to update handles of splitters + * based on resize modes of dock widgets aontained in the container. + */ + void updateSplitterHandles(QSplitter* splitter); + + /** + * This function returns true if the area is not allowed to resize in the direstion + * of the splitter. Otherwise returns true. + */ + bool widgetResizesWithContainer(QWidget* widget); // private slots: ------------------------------------------------------------ void onDockAreaViewToggled(bool Visible) @@ -421,7 +432,8 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter); NewSplitter->addWidget(Splitter); - Splitter = NewSplitter; + updateSplitterHandles(NewSplitter); + Splitter = NewSplitter; delete li; } @@ -430,19 +442,21 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float 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); @@ -453,7 +467,7 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float if (!Splitter->isVisible()) { Splitter->show(); - } + } _this->dumpLayout(); } @@ -515,7 +529,8 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin QSplitter* Splitter = newSplitter(InsertParam.orientation()); Layout->replaceWidget(TargetArea, Splitter); Splitter->addWidget(TargetArea); - TargetAreaSplitter = Splitter; + updateSplitterHandles(Splitter); + TargetAreaSplitter = Splitter; } int AreaIndex = TargetAreaSplitter->indexOf(TargetArea); auto Widget = FloatingWidget->dockContainer()->findChild(QString(), Qt::FindDirectChildrenOnly); @@ -529,7 +544,8 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1) { TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), Widget); - } + updateSplitterHandles(TargetAreaSplitter); + } else { AdjustSplitterSizes = (FloatingSplitter->count() == 1); @@ -537,8 +553,9 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin while (FloatingSplitter->count()) { TargetAreaSplitter->insertWidget(InsertIndex++, FloatingSplitter->widget(0)); - } - } + updateSplitterHandles(TargetAreaSplitter); + } + } if (AdjustSplitterSizes) { @@ -557,28 +574,32 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1) { NewSplitter->addWidget(Widget); - } + 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()); - if (AdjustSplitterSizes) + 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(); @@ -663,7 +684,8 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg { int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height(); TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), NewDockArea); - int Size = (TargetAreaSize - TargetAreaSplitter->handleWidth()) / 2; + updateSplitterHandles(TargetAreaSplitter); + int Size = (TargetAreaSize - TargetAreaSplitter->handleWidth()) / 2; Sizes[AreaIndex] = Size; Sizes.insert(AreaIndex, Size); } @@ -674,16 +696,54 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); NewSplitter->addWidget(TargetArea); insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append()); - int Size = TargetAreaSize / 2; + updateSplitterHandles(NewSplitter); + int Size = TargetAreaSize / 2; NewSplitter->setSizes({Size, Size}); TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter); - } + updateSplitterHandles(TargetAreaSplitter); + } TargetAreaSplitter->setSizes(Sizes); addDockAreasToList({NewDockArea}); } +//============================================================================ +void DockContainerWidgetPrivate::updateSplitterHandles( QSplitter* splitter ) +{ + if( splitter ) + { + for( int index = 0; index < splitter->count(); index++ ) + { + splitter->setStretchFactor(index, widgetResizesWithContainer(splitter->widget(index)) ? 1 : 0); + } + } +} + + +//============================================================================ +bool DockContainerWidgetPrivate::widgetResizesWithContainer(QWidget* widget) +{ + if(!DockManager->centralWidget()) + return true; + + CDockAreaWidget* Area = dynamic_cast< CDockAreaWidget* >( widget ); + if(Area) + { + return Area->isCentralWidgetArea(); + } + + CDockSplitter* innerSplitter = dynamic_cast< CDockSplitter* >( widget ); + if(innerSplitter) + { + return innerSplitter->resizeWithContainer(); + } + + return false; +} + + + //============================================================================ void DockContainerWidgetPrivate::moveToContainer(QWidget* Widget, DockWidgetArea area) { @@ -892,6 +952,10 @@ bool DockContainerWidgetPrivate::restoreSplitter(CDockingStateReader& s, Splitter->addWidget(ChildNode); Visible |= ChildNode->isVisibleTo(Splitter); } + if(!Testing) + { + updateSplitterHandles(Splitter); + } if (Sizes.count() != WidgetCount) { @@ -1069,7 +1133,8 @@ void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockW if (Splitter->orientation() == InsertParam.orientation()) { insertWidgetIntoSplitter(Splitter, NewDockArea, InsertParam.append()); - if (Splitter->isHidden()) + updateSplitterHandles(Splitter); + if (Splitter->isHidden()) { Splitter->show(); } @@ -1082,14 +1147,16 @@ void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockW QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter); NewSplitter->addWidget(Splitter); NewSplitter->addWidget(NewDockArea); - delete li; + updateSplitterHandles(NewSplitter); + delete li; } else { NewSplitter->addWidget(NewDockArea); QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter); NewSplitter->addWidget(Splitter); - delete li; + updateSplitterHandles(NewSplitter); + delete li; } RootSplitter = NewSplitter; } @@ -1175,7 +1242,8 @@ CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetA { ADS_PRINT("TargetAreaSplitter->orientation() == InsertParam.orientation()"); TargetAreaSplitter->insertWidget(index + InsertParam.insertOffset(), NewDockArea); - // do nothing, if flag is not enabled + updateSplitterHandles(TargetAreaSplitter); + // do nothing, if flag is not enabled if (CDockManager::testConfigFlag(CDockManager::EqualSplitOnInsertion)) { adjustSplitterSizesOnInsertion(TargetAreaSplitter); @@ -1188,11 +1256,14 @@ CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetA auto TargetAreaSizes = TargetAreaSplitter->sizes(); QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); NewSplitter->addWidget(TargetDockArea); +// updateSplitterHandles(NewSplitter); insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append()); - TargetAreaSplitter->insertWidget(index, NewSplitter); - if (CDockManager::testConfigFlag(CDockManager::EqualSplitOnInsertion)) - { + updateSplitterHandles(NewSplitter); + TargetAreaSplitter->insertWidget(index, NewSplitter); + updateSplitterHandles(TargetAreaSplitter); + if (CDockManager::testConfigFlag(CDockManager::EqualSplitOnInsertion)) + { TargetAreaSplitter->setSizes(TargetAreaSizes); adjustSplitterSizesOnInsertion(NewSplitter); } @@ -1381,9 +1452,11 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area) } delete Splitter; + Splitter = nullptr; emitAndExit: - CDockWidget* TopLevelWidget = topLevelDockWidget(); + updateSplitterHandles(Splitter); + CDockWidget* TopLevelWidget = topLevelDockWidget(); // Updated the title bar visibility of the dock widget if there is only // one single visible dock widget @@ -1732,6 +1805,13 @@ QList CDockContainerWidget::dockWidgets() const } +//============================================================================ +void CDockContainerWidget::updateSplitterHandles(QSplitter* splitter) +{ + d->updateSplitterHandles(splitter); +} + + //============================================================================ CDockWidget::DockWidgetFeatures CDockContainerWidget::features() const { diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index 1ce2a9e..5e8b8cb 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -155,6 +155,12 @@ protected: */ QList dockWidgets() const; + /** + * This finction forces the dock container widget to update handles of splitters + * based on resize modes of dock widgets aontained in the container. + */ + void updateSplitterHandles(QSplitter* splitter); + public: /** * Default Constructor diff --git a/src/DockManager.cpp b/src/DockManager.cpp index 95e4fac..717ffde 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -108,6 +108,7 @@ struct DockManagerPrivate bool RestoringState = false; QVector UninitializedFloatingWidgets; CDockFocusController* FocusController = nullptr; + CDockWidget* CentralWidget = nullptr; /** * Private data constructor @@ -816,6 +817,23 @@ void CDockManager::loadPerspectives(QSettings& Settings) Settings.endArray(); } +CDockWidget* CDockManager::centralWidget() +{ + return d->CentralWidget; +} + +//============================================================================ +CDockAreaWidget* CDockManager::setCentralWidget(CDockWidget* widget) +{ + if(d->CentralWidget) + { + addDockWidget(RightDockWidgetArea, d->CentralWidget); + } + + d->CentralWidget = widget; + return addDockWidget(CenterDockWidgetArea, widget); +} + //============================================================================ QAction* CDockManager::addToggleViewActionToMenu(QAction* ToggleViewAction, const QString& Group, const QIcon& GroupIcon) diff --git a/src/DockManager.h b/src/DockManager.h index b682c43..7808a43 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -378,7 +378,19 @@ public: */ void loadPerspectives(QSettings& Settings); - /** + /** + * This function returns managers central widget or nullptr if no central widget is set. + */ + CDockWidget* centralWidget(); + + /** + * Adds dockwidget into the central area and marks it as central widget. + * If central widget is set, it will be the only dock widget + * that will resize with the dock container. + */ + CDockAreaWidget* setCentralWidget(CDockWidget* widget); + + /** * Adds a toggle view action to the the internal view menu. * You can either manage the insertion of the toggle view actions in your * application or you can add the actions to the internal view menu and diff --git a/src/DockSplitter.cpp b/src/DockSplitter.cpp index 92f988d..2be1f07 100644 --- a/src/DockSplitter.cpp +++ b/src/DockSplitter.cpp @@ -102,6 +102,20 @@ QWidget* CDockSplitter::lastWidget() const return (count() > 0) ? widget(count() - 1) : nullptr; } +//============================================================================ +bool CDockSplitter::resizeWithContainer() +{ + QList areas = findChildren(); + + for(int i=0; iisCentralWidgetArea()) + return true; + } + return false; +} + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockSplitter.h b/src/DockSplitter.h index 24abc40..9dacdf8 100644 --- a/src/DockSplitter.h +++ b/src/DockSplitter.h @@ -71,6 +71,11 @@ public: * Returns last widget of nullptr is splitter is empty */ QWidget* lastWidget() const; + + /** + * Returns true if the splitter contains central widget of dock manager. + */ + bool resizeWithContainer(); }; // class CDockSplitter } // namespace ads diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index 56c697e..1c3d521 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -461,6 +461,12 @@ void CDockWidget::setMinimumSizeHintMode(eMinimumSizeHintMode Mode) } +bool CDockWidget::isCentralWidget() +{ + return dockManager()->centralWidget() == this; +} + + //============================================================================ void CDockWidget::toggleView(bool Open) { diff --git a/src/DockWidget.h b/src/DockWidget.h index 72f2341..ef8be51 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -360,6 +360,11 @@ public: */ void setMinimumSizeHintMode(eMinimumSizeHintMode Mode); + /** + * Returns true if the dock wisget is set as central widget of it's dock manager + */ + bool isCentralWidget(); + /** * Sets the dock widget icon that is shown in tabs and in toggle view * actions From 0eca1b0433e0b39fc41b4a7265a3e3478d985ffb Mon Sep 17 00:00:00 2001 From: shelomentsev Date: Fri, 21 Aug 2020 11:08:33 +0500 Subject: [PATCH 12/34] Memory leak (#242) * Delete widgets without parents in CDockAreaLayout. * Fixed the place where dock widgets witout parents are destroyed. --- src/DockManager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/DockManager.cpp b/src/DockManager.cpp index cd109c6..f75ff71 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -484,6 +484,12 @@ CDockManager::~CDockManager() { delete FloatingWidget; } + auto DockWidgetsMap = d->DockWidgetsMap; + for(auto DockWidget : d->DockWidgetsMap) + { + if(!DockWidget->parent()) + delete DockWidget; + } delete d; } From 703a9b3e1293b5ff89d810cb00fd00f987f38aeb Mon Sep 17 00:00:00 2001 From: shelomentsev Date: Fri, 21 Aug 2020 11:09:13 +0500 Subject: [PATCH 13/34] Update the state of close button on titlebar and tabbar when CDockWidget::DockWidgetClosable changed. (#240) --- src/DockAreaWidget.cpp | 10 ++++++++++ src/DockAreaWidget.h | 1 + src/DockWidget.cpp | 2 ++ src/DockWidgetTab.cpp | 19 ++++++++++++++----- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index a12bcb0..78c4e5e 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -971,6 +971,16 @@ QSize CDockAreaWidget::minimumSizeHint() const { return d->MinSizeHint.isValid() ? d->MinSizeHint : Super::minimumSizeHint(); } + + +//============================================================================ +void CDockAreaWidget::onDockWidgetFeaturesChanged() +{ + if (d->TitleBar) + d->updateTitleBarButtonStates(); +} + + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index 337eac2..55b1a39 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -65,6 +65,7 @@ private: friend class CDockWidget; friend struct DockManagerPrivate; friend class CDockManager; + void onDockWidgetFeaturesChanged(); private slots: void onTabCloseRequested(int Index); diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index 56c697e..83cb613 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -340,6 +340,8 @@ void CDockWidget::setFeatures(DockWidgetFeatures features) d->Features = features; emit featuresChanged(d->Features); d->TabWidget->onDockWidgetFeaturesChanged(); + if(CDockAreaWidget* DockArea = dockAreaWidget()) + DockArea->onDockWidgetFeaturesChanged(); } diff --git a/src/DockWidgetTab.cpp b/src/DockWidgetTab.cpp index d8b9a84..6d80b1f 100644 --- a/src/DockWidgetTab.cpp +++ b/src/DockWidgetTab.cpp @@ -134,6 +134,18 @@ struct DockWidgetTabPrivate } } + /** + * Update the close button visibility from current feature/config + */ + void updateCloseButtonVisibility(bool active) + { + bool DockWidgetClosable = DockWidget->features().testFlag(CDockWidget::DockWidgetClosable); + bool ActiveTabHasCloseButton = testConfigFlag(CDockManager::ActiveTabHasCloseButton); + bool AllTabsHaveCloseButton = testConfigFlag(CDockManager::AllTabsHaveCloseButton); + bool TabHasCloseButton = (ActiveTabHasCloseButton && active) | AllTabsHaveCloseButton; + CloseButton->setVisible(DockWidgetClosable && TabHasCloseButton); + } + template IFloatingWidget* createFloatingWidget(T* Widget, bool OpaqueUndocking) { @@ -461,11 +473,7 @@ bool CDockWidgetTab::isActiveTab() const //============================================================================ void CDockWidgetTab::setActiveTab(bool active) { - bool DockWidgetClosable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetClosable); - bool ActiveTabHasCloseButton = d->testConfigFlag(CDockManager::ActiveTabHasCloseButton); - bool AllTabsHaveCloseButton = d->testConfigFlag(CDockManager::AllTabsHaveCloseButton); - bool TabHasCloseButton = (ActiveTabHasCloseButton && active) | AllTabsHaveCloseButton; - d->CloseButton->setVisible(DockWidgetClosable && TabHasCloseButton); + d->updateCloseButtonVisibility(active); // Focus related stuff if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting) && !d->DockWidget->dockManager()->isRestoringState()) @@ -653,6 +661,7 @@ void CDockWidgetTab::onDockWidgetFeaturesChanged() SizePolicy.setRetainSizeWhenHidden(Features.testFlag(CDockWidget::DockWidgetClosable) && d->testConfigFlag(CDockManager::RetainTabSizeWhenCloseButtonHidden)); d->CloseButton->setSizePolicy(SizePolicy); + d->updateCloseButtonVisibility(isActiveTab()); } From 14c29f695c205868745bf2e0a107fa86e34a7847 Mon Sep 17 00:00:00 2001 From: hulswit Date: Fri, 21 Aug 2020 13:30:59 +0200 Subject: [PATCH 14/34] Central widget update Updated the setting of central widget with option to set where the possible old central widget will be placed. Fixed option of "unsetting" central widget by setting it to nullptr. --- .gitignore | 1 + examples/centralWidget/centralWidget.pro | 2 -- examples/centralWidget/digitalclock.cpp | 27 ------------------------ examples/centralWidget/digitalclock.h | 17 --------------- examples/centralWidget/mainwindow.cpp | 15 ++----------- src/DockContainerWidget.cpp | 10 +++++---- src/DockManager.cpp | 21 +++++++++++++----- src/DockManager.h | 4 +++- 8 files changed, 28 insertions(+), 69 deletions(-) delete mode 100644 examples/centralWidget/digitalclock.cpp delete mode 100644 examples/centralWidget/digitalclock.h diff --git a/.gitignore b/.gitignore index f9e79be..05aa783 100644 --- a/.gitignore +++ b/.gitignore @@ -382,3 +382,4 @@ MigrationBackup/ FodyWeavers.xsd / build /Settings.ini +.vscode/settings.json diff --git a/examples/centralWidget/centralWidget.pro b/examples/centralWidget/centralWidget.pro index f39896d..9c00fd6 100644 --- a/examples/centralWidget/centralWidget.pro +++ b/examples/centralWidget/centralWidget.pro @@ -22,12 +22,10 @@ DEFINES += QT_DEPRECATED_WARNINGS #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ - digitalclock.cpp \ main.cpp \ mainwindow.cpp HEADERS += \ - digitalclock.h \ mainwindow.h FORMS += \ diff --git a/examples/centralWidget/digitalclock.cpp b/examples/centralWidget/digitalclock.cpp deleted file mode 100644 index 2752d6b..0000000 --- a/examples/centralWidget/digitalclock.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "digitalclock.h" - -#include -#include - -CDigitalClock::CDigitalClock(QWidget *parent) - : QLCDNumber(parent) -{ - setDigitCount(8); - setSegmentStyle(Filled); - - QTimer *timer = new QTimer(this); - connect(timer, &QTimer::timeout, this, &CDigitalClock::showTime); - timer->start(1000); - - showTime(); - - setWindowTitle(tr("Digital Clock")); - resize(150, 60); -} - -void CDigitalClock::showTime() -{ - QTime time = QTime::currentTime(); - QString text = time.toString("hh:mm:ss"); - display(text); -} diff --git a/examples/centralWidget/digitalclock.h b/examples/centralWidget/digitalclock.h deleted file mode 100644 index 4c155d3..0000000 --- a/examples/centralWidget/digitalclock.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef DIGITALCLOCK_H -#define DIGITALCLOCK_H - -#include - -class CDigitalClock : public QLCDNumber -{ - Q_OBJECT - -public: - CDigitalClock(QWidget *parent = nullptr); - -private slots: - void showTime(); -}; - -#endif // DIGITALCLOCK_H diff --git a/examples/centralWidget/mainwindow.cpp b/examples/centralWidget/mainwindow.cpp index cc4a8d9..285de5b 100644 --- a/examples/centralWidget/mainwindow.cpp +++ b/examples/centralWidget/mainwindow.cpp @@ -1,6 +1,5 @@ #include "mainwindow.h" #include "ui_mainwindow.h" -#include "digitalclock.h" #include #include @@ -96,12 +95,8 @@ CMainWindow::CMainWindow(QWidget *parent) QCalendarWidget* calendar = new QCalendarWidget(); CDockWidget* CentralDockWidget = new CDockWidget("CentralWidget"); CentralDockWidget->setWidget(calendar); - CentralDockWidget->setFeature(CDockWidget::DockWidgetClosable, false); - CentralDockWidget->setFeature(CDockWidget::DockWidgetMovable, false); - CentralDockWidget->setFeature(CDockWidget::DockWidgetFloatable, false); auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget); CentralDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); - CentralDockArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); QTreeView* fileTree = new QTreeView(); fileTree->setFrameShape(QFrame::NoFrame); @@ -139,20 +134,18 @@ CMainWindow::CMainWindow(QWidget *parent) QRadioButton* radioDockTop = new QRadioButton("Top", timeLineWidget); QRadioButton* radioDockBottom = new QRadioButton("Bottom", timeLineWidget); radioDockTop->setChecked(true); - timelineLayout->addWidget(new QLabel("Fixed height Dock widget.")); + timelineLayout->addWidget(new QLabel("Test Widget.")); timelineLayout->addStretch(1); timelineLayout->addWidget(new QLabel("Apply predefined perspective: ", this)); timelineLayout->addWidget(radioDockTop); timelineLayout->addWidget(radioDockBottom); TimelineDockWidget = new CDockWidget("Timeline"); TimelineDockWidget->setWidget(timeLineWidget); -// TimelineDockWidget->setResizeMode(CDockWidget::eResizeMode::ResizeHorizontal); TimelineDockWidget->setFeature(CDockWidget::DockWidgetClosable, false); TimelineDockWidget->setFeature(CDockWidget::DockWidgetMovable, false); TimelineDockWidget->setFeature(CDockWidget::DockWidgetFloatable, false); TimelineDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); TimelineDockWidget->setMinimumSize(QSize(50, 50)); - TimelineDockWidget->setFixedHeight(50); auto *TimelineDockArea = DockManager->addDockWidget(DockWidgetArea::TopDockWidgetArea, TimelineDockWidget); TimelineDockArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); TimelineDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); @@ -177,7 +170,6 @@ CMainWindow::CMainWindow(QWidget *parent) QWidget* statusWidget = new QWidget(); QHBoxLayout* statusLayout = new QHBoxLayout(statusWidget); statusLayout->setSpacing(10); - CDigitalClock* clock = new CDigitalClock(statusWidget); statusLayout->addWidget(new QLabel("Status Bar")); QPushButton* OpenPerspectiveButton = new QPushButton("Open Perspective", statusWidget); connect(OpenPerspectiveButton, &QPushButton::clicked, [this](){ @@ -215,19 +207,16 @@ CMainWindow::CMainWindow(QWidget *parent) statusLayout->addWidget(OpenPerspectiveButton); statusLayout->addWidget(SavePerspectiveButton); statusLayout->addStretch(1); - statusLayout->addWidget(clock); CDockWidget* StatusDockWidget = new CDockWidget("Status"); StatusDockWidget->setWidget(statusWidget); -// StatusDockWidget->setResizeMode(CDockWidget::eResizeMode::ResizeHorizontal); StatusDockWidget->setFeature(CDockWidget::DockWidgetClosable, false); StatusDockWidget->setFeature(CDockWidget::DockWidgetMovable, false); StatusDockWidget->setFeature(CDockWidget::DockWidgetFloatable, false); StatusDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); StatusDockWidget->setMinimumSize(QSize(50, 50)); - StatusDockWidget->setFixedHeight(50); StatusDockArea = DockManager->addDockWidget(DockWidgetArea::BottomDockWidgetArea, StatusDockWidget); StatusDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); - StatusDockArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); + StatusDockArea->setDockAreaFlag(ads::CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); } CMainWindow::~CMainWindow() diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 56aef07..171a8e0 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -711,11 +711,14 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg //============================================================================ void DockContainerWidgetPrivate::updateSplitterHandles( QSplitter* splitter ) { - if( splitter ) + if(DockManager->centralWidget()) { - for( int index = 0; index < splitter->count(); index++ ) + if( splitter ) { - splitter->setStretchFactor(index, widgetResizesWithContainer(splitter->widget(index)) ? 1 : 0); + for( int index = 0; index < splitter->count(); index++ ) + { + splitter->setStretchFactor(index, widgetResizesWithContainer(splitter->widget(index)) ? 1 : 0); + } } } } @@ -1256,7 +1259,6 @@ CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetA auto TargetAreaSizes = TargetAreaSplitter->sizes(); QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); NewSplitter->addWidget(TargetDockArea); -// updateSplitterHandles(NewSplitter); insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append()); updateSplitterHandles(NewSplitter); diff --git a/src/DockManager.cpp b/src/DockManager.cpp index d04cc50..145501f 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -407,6 +407,7 @@ bool DockManagerPrivate::restoreState(const QByteArray& State, int version) return false; } + CentralWidget = nullptr; // Hide updates of floating widgets from use hideFloatingWidgets(); markDockWidgetsDirty(); @@ -830,15 +831,25 @@ CDockWidget* CDockManager::centralWidget() } //============================================================================ -CDockAreaWidget* CDockManager::setCentralWidget(CDockWidget* widget) +CDockAreaWidget* CDockManager::setCentralWidget(CDockWidget* widget, CDockWidget* oldCentralWidget, DockWidgetArea oldCentralWidgetArea) { - if(d->CentralWidget) + oldCentralWidget = d->CentralWidget; + if(oldCentralWidget) { - addDockWidget(RightDockWidgetArea, d->CentralWidget); + addDockWidget(oldCentralWidgetArea, oldCentralWidget); } - d->CentralWidget = widget; - return addDockWidget(CenterDockWidgetArea, widget); + if(widget) + { + widget->setFeature(CDockWidget::DockWidgetClosable, false); + widget->setFeature(CDockWidget::DockWidgetMovable, false); + widget->setFeature(CDockWidget::DockWidgetFloatable, false); + d->CentralWidget = widget; + CDockAreaWidget* CentralArea = addDockWidget(CenterDockWidgetArea, widget); + CentralArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); + return CentralArea; + } + return nullptr; } //============================================================================ diff --git a/src/DockManager.h b/src/DockManager.h index 7808a43..07f735c 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -387,8 +387,10 @@ public: * Adds dockwidget into the central area and marks it as central widget. * If central widget is set, it will be the only dock widget * that will resize with the dock container. + * If a central widget does exist, it will be docked to oldCentralWidgetArea + * and returned in oldCentralWidget. */ - CDockAreaWidget* setCentralWidget(CDockWidget* widget); + CDockAreaWidget* setCentralWidget(CDockWidget* widget, CDockWidget* oldCentralWidget = nullptr, DockWidgetArea oldCentralWidgetArea = DockWidgetArea::RightDockWidgetArea); /** * Adds a toggle view action to the the internal view menu. From ba69f3e6b9b15d60657dd5287ec881dabc2c75a9 Mon Sep 17 00:00:00 2001 From: hulswit Date: Fri, 21 Aug 2020 13:42:52 +0200 Subject: [PATCH 15/34] CMake Fix --- examples/centralWidget/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/centralWidget/CMakeLists.txt b/examples/centralWidget/CMakeLists.txt index 4cc7de9..aa69603 100644 --- a/examples/centralWidget/CMakeLists.txt +++ b/examples/centralWidget/CMakeLists.txt @@ -6,7 +6,6 @@ add_executable(CentralWidgetExample WIN32 main.cpp mainwindow.cpp mainwindow.ui - digitalclock.cpp ) target_include_directories(CentralWidgetExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src") target_link_libraries(CentralWidgetExample PRIVATE qtadvanceddocking) From a565239c4a1bded30d9d84ac923208ab1b1eec1f Mon Sep 17 00:00:00 2001 From: Yurii Miroshnyk Date: Fri, 21 Aug 2020 19:20:54 +0300 Subject: [PATCH 16/34] Fixes pack. Parenting, memory leaks, floating widgets deleting. * DockWidget always has DockAreaWidget as parent. It's not necessary to make it nullptr. This fixes many bugs related to restoring inactive tabbed DockWidgets. * Fixed memory leaks related to QBoxLayout::takeAt(). * Fixed algorithm of deleting remaining floating widgets after restore. --- src/DockAreaWidget.cpp | 23 ++++------------------- src/DockManager.cpp | 8 ++++---- src/DockWidget.cpp | 1 + 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 78c4e5e..eaf99ad 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -86,18 +86,6 @@ public: } - /** - * Delete widgets without parents in this layout - */ - ~CDockAreaLayout() - { - for(auto Widget : m_Widgets) - { - if(!Widget->parent()) - delete Widget; - } - } - /** * Returns the number of widgets in this layout */ @@ -112,7 +100,6 @@ public: */ void insertWidget(int index, QWidget* Widget) { - Widget->setParent(nullptr); if (index < 0) { index = m_Widgets.count(); @@ -143,6 +130,8 @@ public: { LayoutItem->widget()->setParent(nullptr); } + delete LayoutItem; + m_CurrentWidget = nullptr; m_CurrentIndex = -1; } @@ -182,11 +171,7 @@ public: parent->setUpdatesEnabled(false); } - auto LayoutItem = m_ParentLayout->takeAt(1); - if (LayoutItem) - { - LayoutItem->widget()->setParent(nullptr); - } + delete m_ParentLayout->takeAt(1); m_ParentLayout->addWidget(next); if (prev) @@ -247,7 +232,7 @@ public: using DockAreaLayout = CDockAreaLayout; -static constexpr DockWidgetAreas DefaultAllowedAreas = AllDockAreas; +static const DockWidgetAreas DefaultAllowedAreas = AllDockAreas; /** diff --git a/src/DockManager.cpp b/src/DockManager.cpp index f75ff71..09bc9a5 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -296,11 +296,11 @@ bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int versi { // Delete remaining empty floating widgets int FloatingWidgetIndex = DockContainerCount - 1; - int DeleteCount = FloatingWidgets.count() - FloatingWidgetIndex; - for (int i = 0; i < DeleteCount; ++i) + for (int i = FloatingWidgetIndex; i < FloatingWidgets.count(); ++i) { - FloatingWidgets[FloatingWidgetIndex + i]->deleteLater(); - _this->removeDockContainer(FloatingWidgets[FloatingWidgetIndex + i]->dockContainer()); + auto* floatingWidget = FloatingWidgets[i]; + _this->removeDockContainer(floatingWidget->dockContainer()); + floatingWidget->deleteLater(); } } diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index 83cb613..dceca83 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -542,6 +542,7 @@ void CDockWidget::setDockArea(CDockAreaWidget* DockArea) { d->DockArea = DockArea; d->ToggleViewAction->setChecked(DockArea != nullptr && !this->isClosed()); + setParent(DockArea); } From 835a532e755a90177993e4f1a9fbedba1c2c4447 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 24 Aug 2020 10:22:12 +0200 Subject: [PATCH 17/34] Corrected constness of some functions, changed signatur of setCentralWidget function --- src/DockAreaWidget.cpp | 8 ++++--- src/DockAreaWidget.h | 2 +- src/DockContainerWidget.cpp | 36 ++++++++++++++-------------- src/DockContainerWidget.h | 4 ++-- src/DockManager.cpp | 47 +++++++++++++++++++++---------------- src/DockManager.h | 19 ++++++++++----- src/DockSplitter.cpp | 10 ++++---- src/DockSplitter.h | 2 +- src/DockWidget.cpp | 3 ++- src/DockWidget.h | 4 ++-- 10 files changed, 77 insertions(+), 58 deletions(-) diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 2fb345c..fe9097f 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -968,12 +968,14 @@ CDockAreaTitleBar* CDockAreaWidget::titleBar() const //============================================================================ -bool CDockAreaWidget::isCentralWidgetArea() +bool CDockAreaWidget::isCentralWidgetArea() const { - if(dockWidgetsCount()!=1) + if (dockWidgetsCount()!= 1) + { return false; + } - return dockManager()->centralWidget()==dockWidgets()[0]; + return dockManager()->centralWidget() == dockWidgets()[0]; } diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index 231af91..ac7dcb5 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -310,7 +310,7 @@ public: /** * Returns true if the area contains the central widget of it's manager. */ - bool isCentralWidgetArea(); + bool isCentralWidgetArea() const; public slots: /** diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 171a8e0..a10495e 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -323,14 +323,15 @@ public: } /** - * This finction forces the dock container widget to update handles of splitters - * based on resize modes of dock widgets aontained in the container. + * This function forces the dock container widget to update handles of splitters + * based if a central widget exists. */ void updateSplitterHandles(QSplitter* splitter); /** - * This function returns true if the area is not allowed to resize in the direstion - * of the splitter. Otherwise returns true. + * 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); @@ -711,15 +712,14 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg //============================================================================ void DockContainerWidgetPrivate::updateSplitterHandles( QSplitter* splitter ) { - if(DockManager->centralWidget()) + if (!DockManager->centralWidget() || !splitter) + { + return; + } + + for (int i = 0; i < splitter->count(); ++i) { - if( splitter ) - { - for( int index = 0; index < splitter->count(); index++ ) - { - splitter->setStretchFactor(index, widgetResizesWithContainer(splitter->widget(index)) ? 1 : 0); - } - } + splitter->setStretchFactor(i, widgetResizesWithContainer(splitter->widget(i)) ? 1 : 0); } } @@ -727,19 +727,21 @@ void DockContainerWidgetPrivate::updateSplitterHandles( QSplitter* splitter ) //============================================================================ bool DockContainerWidgetPrivate::widgetResizesWithContainer(QWidget* widget) { - if(!DockManager->centralWidget()) + if (!DockManager->centralWidget()) + { return true; + } - CDockAreaWidget* Area = dynamic_cast< CDockAreaWidget* >( widget ); + auto Area = qobject_cast(widget); if(Area) { return Area->isCentralWidgetArea(); } - CDockSplitter* innerSplitter = dynamic_cast< CDockSplitter* >( widget ); - if(innerSplitter) + auto innerSplitter = qobject_cast(widget); + if (innerSplitter) { - return innerSplitter->resizeWithContainer(); + return innerSplitter->isResizingWithContainer(); } return false; diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index 5e8b8cb..0bc674b 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -156,8 +156,8 @@ protected: QList dockWidgets() const; /** - * This finction forces the dock container widget to update handles of splitters - * based on resize modes of dock widgets aontained in the container. + * 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); diff --git a/src/DockManager.cpp b/src/DockManager.cpp index 503a122..55ef20f 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -831,31 +831,38 @@ void CDockManager::loadPerspectives(QSettings& Settings) Settings.endArray(); } -CDockWidget* CDockManager::centralWidget() + +//============================================================================ +CDockWidget* CDockManager::centralWidget() const { return d->CentralWidget; } -//============================================================================ -CDockAreaWidget* CDockManager::setCentralWidget(CDockWidget* widget, CDockWidget* oldCentralWidget, DockWidgetArea oldCentralWidgetArea) -{ - oldCentralWidget = d->CentralWidget; - if(oldCentralWidget) - { - addDockWidget(oldCentralWidgetArea, oldCentralWidget); - } - if(widget) - { - widget->setFeature(CDockWidget::DockWidgetClosable, false); - widget->setFeature(CDockWidget::DockWidgetMovable, false); - widget->setFeature(CDockWidget::DockWidgetFloatable, false); - d->CentralWidget = widget; - CDockAreaWidget* CentralArea = addDockWidget(CenterDockWidgetArea, widget); - CentralArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); - return CentralArea; - } - return nullptr; +//============================================================================ +CDockAreaWidget* CDockManager::setCentralWidget(CDockWidget* widget) +{ + if (!widget) + { + d->CentralWidget = nullptr; + return nullptr; + } + + // Setting a new central widget is now allowed if there is alread a central + // widget + if (d->CentralWidget) + { + return nullptr; + } + + + widget->setFeature(CDockWidget::DockWidgetClosable, false); + widget->setFeature(CDockWidget::DockWidgetMovable, false); + widget->setFeature(CDockWidget::DockWidgetFloatable, false); + d->CentralWidget = widget; + CDockAreaWidget* CentralArea = addDockWidget(CenterDockWidgetArea, widget); + CentralArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); + return CentralArea; } //============================================================================ diff --git a/src/DockManager.h b/src/DockManager.h index 07f735c..f56fc13 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -381,16 +381,23 @@ public: /** * This function returns managers central widget or nullptr if no central widget is set. */ - CDockWidget* centralWidget(); + CDockWidget* centralWidget() const; /** - * Adds dockwidget into the central area and marks it as central widget. + * Adds dockwidget widget into the central area and marks it as central widget. * If central widget is set, it will be the only dock widget - * that will resize with the dock container. - * If a central widget does exist, it will be docked to oldCentralWidgetArea - * and returned in oldCentralWidget. + * that will resize with the dock container. A central widget if not + * movable, floatable or closable and the titlebar of the central + * dock area is not visible. + * If the given widget could be set as central widget, the function returns + * the created cok area. If the widget could not be set, because there + * is already a central widget, this function returns a nullptr. + * To clear the central widget, pass a nullptr to the function. + * \retval != 0 The dock area that contains the central widget + * \retval nullptr Indicates that the given widget can not be set as central + * widget because there is already a central widget. */ - CDockAreaWidget* setCentralWidget(CDockWidget* widget, CDockWidget* oldCentralWidget = nullptr, DockWidgetArea oldCentralWidgetArea = DockWidgetArea::RightDockWidgetArea); + CDockAreaWidget* setCentralWidget(CDockWidget* widget); /** * Adds a toggle view action to the the internal view menu. diff --git a/src/DockSplitter.cpp b/src/DockSplitter.cpp index 2be1f07..047f0f4 100644 --- a/src/DockSplitter.cpp +++ b/src/DockSplitter.cpp @@ -103,16 +103,16 @@ QWidget* CDockSplitter::lastWidget() const } //============================================================================ -bool CDockSplitter::resizeWithContainer() +bool CDockSplitter::isResizingWithContainer() const { - QList areas = findChildren(); - - for(int i=0; i()) { - CDockAreaWidget* area = areas.at(i); if(area->isCentralWidgetArea()) + { return true; + } } + return false; } diff --git a/src/DockSplitter.h b/src/DockSplitter.h index 9dacdf8..1cc766c 100644 --- a/src/DockSplitter.h +++ b/src/DockSplitter.h @@ -75,7 +75,7 @@ public: /** * Returns true if the splitter contains central widget of dock manager. */ - bool resizeWithContainer(); + bool isResizingWithContainer() const; }; // class CDockSplitter } // namespace ads diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index 22b282b..0893e2d 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -463,7 +463,8 @@ void CDockWidget::setMinimumSizeHintMode(eMinimumSizeHintMode Mode) } -bool CDockWidget::isCentralWidget() +//============================================================================ +bool CDockWidget::isCentralWidget() const { return dockManager()->centralWidget() == this; } diff --git a/src/DockWidget.h b/src/DockWidget.h index b574fa4..b5fb5a1 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -361,9 +361,9 @@ public: void setMinimumSizeHintMode(eMinimumSizeHintMode Mode); /** - * Returns true if the dock wisget is set as central widget of it's dock manager + * Returns true if the dock widget is set as central widget of it's dock manager */ - bool isCentralWidget(); + bool isCentralWidget() const; /** * Sets the dock widget icon that is shown in tabs and in toggle view From 08a8cee1c6f7770bfec9970061535167262cb31a Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 24 Aug 2020 11:14:58 +0200 Subject: [PATCH 18/34] Updated centralwidget test --- examples/CMakeLists.txt | 2 +- examples/centralWidget/mainwindow.cpp | 226 ------------------ .../CMakeLists.txt | 0 .../centralwidget.pro} | 0 .../{centralWidget => centralwidget}/main.cpp | 3 +- examples/centralwidget/mainwindow.cpp | 83 +++++++ .../mainwindow.h | 0 .../mainwindow.ui | 6 + 8 files changed, 91 insertions(+), 229 deletions(-) delete mode 100644 examples/centralWidget/mainwindow.cpp rename examples/{centralWidget => centralwidget}/CMakeLists.txt (100%) rename examples/{centralWidget/centralWidget.pro => centralwidget/centralwidget.pro} (100%) rename examples/{centralWidget => centralwidget}/main.cpp (85%) create mode 100644 examples/centralwidget/mainwindow.cpp rename examples/{centralWidget => centralwidget}/mainwindow.h (100%) rename examples/{centralWidget => centralwidget}/mainwindow.ui (80%) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3b24252..32ca8c4 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -3,4 +3,4 @@ project(QtADSExamples LANGUAGES CXX VERSION ${VERSION_SHORT}) add_subdirectory(simple) add_subdirectory(sidebar) add_subdirectory(deleteonclose) -add_subdirectory(centralWidget) \ No newline at end of file +add_subdirectory(centralwidget) \ No newline at end of file diff --git a/examples/centralWidget/mainwindow.cpp b/examples/centralWidget/mainwindow.cpp deleted file mode 100644 index 285de5b..0000000 --- a/examples/centralWidget/mainwindow.cpp +++ /dev/null @@ -1,226 +0,0 @@ -#include "mainwindow.h" -#include "ui_mainwindow.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "DockAreaWidget.h" -#include "DockAreaTitleBar.h" -#include "DockAreaTabBar.h" -#include "FloatingDockContainer.h" -#include "DockComponentsFactory.h" - -using namespace ads; - -const QString CMainWindow::kTableTopLayout = "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "344 272 " - "" - "" - "" - "" - "" - "" - "" - "258 758 258 " - "" - "" - "" - "" - "52 621 52 " - "" - "" - ""; - -const QString CMainWindow::kTableBottomLayout = "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "258 758 258 " - "" - "" - "" - "" - "" - "" - "" - "621 52 52 " - "" - "" - ""; - -CMainWindow::CMainWindow(QWidget *parent) - : QMainWindow(parent) - , ui(new Ui::CMainWindow) -{ - ui->setupUi(this); - CDockManager::setConfigFlag(CDockManager::OpaqueSplitterResize, true); - CDockManager::setConfigFlag(CDockManager::XmlCompressionEnabled, false); - DockManager = new CDockManager(this); - QCalendarWidget* calendar = new QCalendarWidget(); - CDockWidget* CentralDockWidget = new CDockWidget("CentralWidget"); - CentralDockWidget->setWidget(calendar); - auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget); - CentralDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); - - QTreeView* fileTree = new QTreeView(); - fileTree->setFrameShape(QFrame::NoFrame); - QFileSystemModel* fileModel = new QFileSystemModel(fileTree); - fileModel->setRootPath(QDir::currentPath()); - fileTree->setModel(fileModel); - CDockWidget* DataDockWidget = new CDockWidget("File system"); - DataDockWidget->setWidget(fileTree); - DataDockWidget->resize(150, 250); - DataDockWidget->setMinimumSize(100, 250); - auto* fileArea = DockManager->addDockWidget(DockWidgetArea::LeftDockWidgetArea, DataDockWidget, CentralDockArea); - - QTableWidget* table = new QTableWidget(); - table->setColumnCount(3); - table->setRowCount(10); - CDockWidget* TableDockWidget = new CDockWidget("Table"); - TableDockWidget->setWidget(table); - TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); - TableDockWidget->resize(250, 150); - TableDockWidget->setMinimumSize(200,150); - DockManager->addDockWidget(DockWidgetArea::BottomDockWidgetArea, TableDockWidget, fileArea); - - QTableWidget* propertiesTable = new QTableWidget(); - table->setColumnCount(3); - table->setRowCount(10); - CDockWidget* PropertiesDockWidget = new CDockWidget("Properties"); - PropertiesDockWidget->setWidget(propertiesTable); - PropertiesDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); - PropertiesDockWidget->resize(250, 150); - PropertiesDockWidget->setMinimumSize(200,150); - DockManager->addDockWidget(DockWidgetArea::RightDockWidgetArea, PropertiesDockWidget, CentralDockArea); - - QWidget* timeLineWidget = new QWidget(); - QHBoxLayout* timelineLayout = new QHBoxLayout(timeLineWidget); - QRadioButton* radioDockTop = new QRadioButton("Top", timeLineWidget); - QRadioButton* radioDockBottom = new QRadioButton("Bottom", timeLineWidget); - radioDockTop->setChecked(true); - timelineLayout->addWidget(new QLabel("Test Widget.")); - timelineLayout->addStretch(1); - timelineLayout->addWidget(new QLabel("Apply predefined perspective: ", this)); - timelineLayout->addWidget(radioDockTop); - timelineLayout->addWidget(radioDockBottom); - TimelineDockWidget = new CDockWidget("Timeline"); - TimelineDockWidget->setWidget(timeLineWidget); - TimelineDockWidget->setFeature(CDockWidget::DockWidgetClosable, false); - TimelineDockWidget->setFeature(CDockWidget::DockWidgetMovable, false); - TimelineDockWidget->setFeature(CDockWidget::DockWidgetFloatable, false); - TimelineDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); - TimelineDockWidget->setMinimumSize(QSize(50, 50)); - auto *TimelineDockArea = DockManager->addDockWidget(DockWidgetArea::TopDockWidgetArea, TimelineDockWidget); - TimelineDockArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); - TimelineDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); - connect(radioDockTop, &QRadioButton::toggled, [this](bool checked){ - bool ok = true; - if(!checked) - { - ok = DockManager->restoreState(kTableBottomLayout.toUtf8()); - } - else - { - ok = DockManager->restoreState(kTableTopLayout.toUtf8()); - } - if(!ok) - { - QMessageBox msgBox; - msgBox.setText("Failed to apply perspective!"); - msgBox.exec(); - } - }); - - QWidget* statusWidget = new QWidget(); - QHBoxLayout* statusLayout = new QHBoxLayout(statusWidget); - statusLayout->setSpacing(10); - statusLayout->addWidget(new QLabel("Status Bar")); - QPushButton* OpenPerspectiveButton = new QPushButton("Open Perspective", statusWidget); - connect(OpenPerspectiveButton, &QPushButton::clicked, [this](){ - QString PerspectiveName = QFileDialog::getOpenFileName(this, "Open Perspective", "", "Perspective files (*.xml)"); - if (PerspectiveName.isEmpty()) - { - return; - } - - QFile stateFile(PerspectiveName); - stateFile.open(QIODevice::ReadOnly); - QByteArray state = stateFile.readAll(); - stateFile.close(); - if(!DockManager->restoreState(state)) - { - QMessageBox msgBox; - msgBox.setText("Failed to apply perspective " + stateFile.fileName()); - msgBox.exec(); - } - }); - QPushButton* SavePerspectiveButton = new QPushButton("Create Perspective", statusWidget); - connect(SavePerspectiveButton, &QPushButton::clicked, [this](){ - QString PerspectiveName = QInputDialog::getText(this, "Save Perspective", "Enter unique name:"); - if (PerspectiveName.isEmpty()) - { - return; - } - - QByteArray state = DockManager->saveState(); - QFile stateFile(PerspectiveName + ".xml"); - stateFile.open(QIODevice::WriteOnly); - stateFile.write(state); - stateFile.close(); - }); - statusLayout->addWidget(OpenPerspectiveButton); - statusLayout->addWidget(SavePerspectiveButton); - statusLayout->addStretch(1); - CDockWidget* StatusDockWidget = new CDockWidget("Status"); - StatusDockWidget->setWidget(statusWidget); - StatusDockWidget->setFeature(CDockWidget::DockWidgetClosable, false); - StatusDockWidget->setFeature(CDockWidget::DockWidgetMovable, false); - StatusDockWidget->setFeature(CDockWidget::DockWidgetFloatable, false); - StatusDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); - StatusDockWidget->setMinimumSize(QSize(50, 50)); - StatusDockArea = DockManager->addDockWidget(DockWidgetArea::BottomDockWidgetArea, StatusDockWidget); - StatusDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); - StatusDockArea->setDockAreaFlag(ads::CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true); -} - -CMainWindow::~CMainWindow() -{ - delete ui; -} - diff --git a/examples/centralWidget/CMakeLists.txt b/examples/centralwidget/CMakeLists.txt similarity index 100% rename from examples/centralWidget/CMakeLists.txt rename to examples/centralwidget/CMakeLists.txt diff --git a/examples/centralWidget/centralWidget.pro b/examples/centralwidget/centralwidget.pro similarity index 100% rename from examples/centralWidget/centralWidget.pro rename to examples/centralwidget/centralwidget.pro diff --git a/examples/centralWidget/main.cpp b/examples/centralwidget/main.cpp similarity index 85% rename from examples/centralWidget/main.cpp rename to examples/centralwidget/main.cpp index 3f073f3..fa4c4fd 100644 --- a/examples/centralWidget/main.cpp +++ b/examples/centralwidget/main.cpp @@ -1,5 +1,4 @@ -#include "mainwindow.h" - +#include #include int main(int argc, char *argv[]) diff --git a/examples/centralwidget/mainwindow.cpp b/examples/centralwidget/mainwindow.cpp new file mode 100644 index 0000000..f4c7858 --- /dev/null +++ b/examples/centralwidget/mainwindow.cpp @@ -0,0 +1,83 @@ +#include "mainwindow.h" + +#include "ui_mainwindow.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DockAreaWidget.h" +#include "DockAreaTitleBar.h" +#include "DockAreaTabBar.h" +#include "FloatingDockContainer.h" +#include "DockComponentsFactory.h" + +using namespace ads; + +CMainWindow::CMainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::CMainWindow) +{ + ui->setupUi(this); + CDockManager::setConfigFlag(CDockManager::OpaqueSplitterResize, true); + CDockManager::setConfigFlag(CDockManager::XmlCompressionEnabled, false); + DockManager = new CDockManager(this); + + // Set central widget + QCalendarWidget* calendar = new QCalendarWidget(); + CDockWidget* CentralDockWidget = new CDockWidget("CentralWidget"); + CentralDockWidget->setWidget(calendar); + auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget); + CentralDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas); + + // create other dock widgets + QTreeView* fileTree = new QTreeView(); + fileTree->setFrameShape(QFrame::NoFrame); + QFileSystemModel* fileModel = new QFileSystemModel(fileTree); + fileModel->setRootPath(QDir::currentPath()); + fileTree->setModel(fileModel); + CDockWidget* DataDockWidget = new CDockWidget("File system"); + DataDockWidget->setWidget(fileTree); + DataDockWidget->resize(150, 250); + DataDockWidget->setMinimumSize(100, 250); + auto* fileArea = DockManager->addDockWidget(DockWidgetArea::LeftDockWidgetArea, DataDockWidget, CentralDockArea); + ui->menuView->addAction(DataDockWidget->toggleViewAction()); + + QTableWidget* table = new QTableWidget(); + table->setColumnCount(3); + table->setRowCount(10); + CDockWidget* TableDockWidget = new CDockWidget("Table"); + TableDockWidget->setWidget(table); + TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); + TableDockWidget->resize(250, 150); + TableDockWidget->setMinimumSize(200,150); + DockManager->addDockWidget(DockWidgetArea::BottomDockWidgetArea, TableDockWidget, fileArea); + ui->menuView->addAction(TableDockWidget->toggleViewAction()); + + QTableWidget* propertiesTable = new QTableWidget(); + table->setColumnCount(3); + table->setRowCount(10); + CDockWidget* PropertiesDockWidget = new CDockWidget("Properties"); + PropertiesDockWidget->setWidget(propertiesTable); + PropertiesDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); + PropertiesDockWidget->resize(250, 150); + PropertiesDockWidget->setMinimumSize(200,150); + DockManager->addDockWidget(DockWidgetArea::RightDockWidgetArea, PropertiesDockWidget, CentralDockArea); + ui->menuView->addAction(PropertiesDockWidget->toggleViewAction()); +} + +CMainWindow::~CMainWindow() +{ + delete ui; +} + diff --git a/examples/centralWidget/mainwindow.h b/examples/centralwidget/mainwindow.h similarity index 100% rename from examples/centralWidget/mainwindow.h rename to examples/centralwidget/mainwindow.h diff --git a/examples/centralWidget/mainwindow.ui b/examples/centralwidget/mainwindow.ui similarity index 80% rename from examples/centralWidget/mainwindow.ui rename to examples/centralwidget/mainwindow.ui index 73ae7b1..135fdd1 100644 --- a/examples/centralWidget/mainwindow.ui +++ b/examples/centralwidget/mainwindow.ui @@ -23,6 +23,12 @@ 21 + + + View + + + From 1b4204813524d997f4b3b75873a5fc4723d2e2ba Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 24 Aug 2020 11:33:40 +0200 Subject: [PATCH 19/34] Fixed pure virtual function call --- src/DockManager.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/DockManager.cpp b/src/DockManager.cpp index 09bc9a5..bf20907 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -484,12 +484,6 @@ CDockManager::~CDockManager() { delete FloatingWidget; } - auto DockWidgetsMap = d->DockWidgetsMap; - for(auto DockWidget : d->DockWidgetsMap) - { - if(!DockWidget->parent()) - delete DockWidget; - } delete d; } From c28a27c81ca8b2d01a2c9ba76568e51d9025cb6c Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 24 Aug 2020 13:22:34 +0200 Subject: [PATCH 20/34] Reverted changes that cause application crash --- src/DockAreaWidget.cpp | 14 ++------------ src/DockManager.cpp | 15 +-------------- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 78c4e5e..98055e8 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -86,18 +86,6 @@ public: } - /** - * Delete widgets without parents in this layout - */ - ~CDockAreaLayout() - { - for(auto Widget : m_Widgets) - { - if(!Widget->parent()) - delete Widget; - } - } - /** * Returns the number of widgets in this layout */ @@ -977,7 +965,9 @@ QSize CDockAreaWidget::minimumSizeHint() const void CDockAreaWidget::onDockWidgetFeaturesChanged() { if (d->TitleBar) + { d->updateTitleBarButtonStates(); + } } diff --git a/src/DockManager.cpp b/src/DockManager.cpp index f75ff71..95e4fac 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -484,12 +484,6 @@ CDockManager::~CDockManager() { delete FloatingWidget; } - auto DockWidgetsMap = d->DockWidgetsMap; - for(auto DockWidget : d->DockWidgetsMap) - { - if(!DockWidget->parent()) - delete DockWidget; - } delete d; } @@ -659,14 +653,7 @@ void CDockManager::showEvent(QShowEvent *event) for (auto FloatingWidget : d->UninitializedFloatingWidgets) { - for(CDockWidget* DockWidget : FloatingWidget->dockWidgets()) - { - if(!DockWidget->isClosed()) - { - FloatingWidget->show(); - break; - } - } + FloatingWidget->show(); } d->UninitializedFloatingWidgets.clear(); } From 03b1848b43e7fc1c05da6a33bea0abddbc2829c6 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 24 Aug 2020 13:25:20 +0200 Subject: [PATCH 21/34] Reverted changed --- src/DockAreaWidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index de18b69..3ee3797 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -100,6 +100,7 @@ public: */ void insertWidget(int index, QWidget* Widget) { + Widget->setParent(nullptr); if (index < 0) { index = m_Widgets.count(); From 543d226ba3b039a0f58b906c2abcf2217b4dc292 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 24 Aug 2020 13:32:50 +0200 Subject: [PATCH 22/34] Fixed memory leak --- src/DockAreaWidget.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 3ee3797..5d37f63 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -131,8 +131,6 @@ public: { LayoutItem->widget()->setParent(nullptr); } - delete LayoutItem; - m_CurrentWidget = nullptr; m_CurrentIndex = -1; } @@ -172,7 +170,12 @@ public: parent->setUpdatesEnabled(false); } - delete m_ParentLayout->takeAt(1); + auto LayoutItem = m_ParentLayout->takeAt(1); + if (LayoutItem) + { + LayoutItem->widget()->setParent(nullptr); + } + delete LayoutItem; m_ParentLayout->addWidget(next); if (prev) From 48fb999bd0f7cce27be1336c253d04c3cded148f Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 24 Aug 2020 15:46:51 +0200 Subject: [PATCH 23/34] Fix static build of centralwidget example --- examples/centralwidget/centralwidget.pro | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/examples/centralwidget/centralwidget.pro b/examples/centralwidget/centralwidget.pro index 9c00fd6..3c0932d 100644 --- a/examples/centralwidget/centralwidget.pro +++ b/examples/centralwidget/centralwidget.pro @@ -1,14 +1,15 @@ ADS_OUT_ROOT = $${OUT_PWD}/../.. -QT += core gui - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets +QT += core gui widgets TARGET = CentralWidgetExample DESTDIR = $${ADS_OUT_ROOT}/lib TEMPLATE = app CONFIG += c++14 CONFIG += debug_and_release +adsBuildStatic { + DEFINES += ADS_STATIC +} # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings @@ -16,11 +17,6 @@ CONFIG += debug_and_release # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - SOURCES += \ main.cpp \ mainwindow.cpp From 533d174abceb62faa74850040792a9ef601240b2 Mon Sep 17 00:00:00 2001 From: helywin Date: Thu, 12 Sep 2019 10:44:12 +0800 Subject: [PATCH 24/34] Finished implementing maximize for linux. Added FloatingContainerForc*TitleBar to switch between native and custom titlebar. Co-authored-by: SleepProgger --- src/DockFocusController.cpp | 3 + src/DockManager.cpp | 53 +++++++- src/DockManager.h | 12 ++ src/FloatingDockContainer.cpp | 169 ++++++++++++++++++----- src/FloatingDockContainer.h | 41 +++++- src/ads_globals.cpp | 193 +++++++++++++++++++++++++++ src/ads_globals.h | 32 +++++ src/linux/FloatingWidgetTitleBar.cpp | 55 +++++++- src/linux/FloatingWidgetTitleBar.h | 11 ++ src/src.pro | 1 + 10 files changed, 533 insertions(+), 37 deletions(-) diff --git a/src/DockFocusController.cpp b/src/DockFocusController.cpp index c4a9332..702a00a 100644 --- a/src/DockFocusController.cpp +++ b/src/DockFocusController.cpp @@ -83,6 +83,9 @@ static void updateDockAreaFocusStyle(CDockAreaWidget* DockArea, bool Focused) #ifdef Q_OS_LINUX static void updateFloatingWidgetFocusStyle(CFloatingDockContainer* FloatingWidget, bool Focused) { + if(FloatingWidget->hasNativeTitleBar()){ + return; + } auto TitleBar = qobject_cast(FloatingWidget->titleBarWidget()); if (!TitleBar) { diff --git a/src/DockManager.cpp b/src/DockManager.cpp index e21dbdf..3fcac69 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -368,8 +368,6 @@ void DockManagerPrivate::restoreDockAreasIndices() } } - - //============================================================================ void DockManagerPrivate::emitTopLevelEvents() { @@ -476,6 +474,10 @@ CDockManager::CDockManager(QWidget *parent) : { d->FocusController = new CDockFocusController(this); } + +#ifdef Q_OS_LINUX + window()->installEventFilter(this); +#endif } //============================================================================ @@ -489,6 +491,53 @@ CDockManager::~CDockManager() delete d; } +//============================================================================ +#ifdef Q_OS_LINUX +bool CDockManager::eventFilter(QObject *obj, QEvent *e){ + // Emulate Qt:Tool behaviour. + // Required because on some WMs Tool windows can't be maximized. + + // Window always on top of the MainWindow. + if(e->type() == QEvent::WindowActivate){ + for(auto _window : floatingWidgets()){ + if(!_window->isVisible() || window()->isMinimized()){ + continue; + } + // setWindowFlags(Qt::WindowStaysOnTopHint) will hide the window and thus requires a show call. + // This then leads to flickering and a nasty endless loop (also buggy behaviour on Ubuntu). + // So we just do it ourself. + internal::xcb_update_prop(true, _window->window()->winId(), "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP"); + } + } + else if(e->type() == QEvent::WindowDeactivate){ + for(auto _window : floatingWidgets()){ + if(!_window->isVisible() || window()->isMinimized()){ + continue; + } + internal::xcb_update_prop(false, _window->window()->winId(), "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP"); + _window->raise(); + } + } + + // Sync minimize with MainWindow + if(e->type() == QEvent::WindowStateChange){ + for(auto _window : floatingWidgets()){ + if(! _window->isVisible()){ + continue; + } + if(window()->isMinimized()){ + _window->showMinimized(); + } else { + _window->setWindowState(_window->windowState() & (~Qt::WindowMinimized)); + } + } + if(!window()->isMinimized()){ + QApplication::setActiveWindow(window()); + } + } + return Super::eventFilter(obj, e); +} +#endif //============================================================================ void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget) diff --git a/src/DockManager.h b/src/DockManager.h index f56fc13..addbc25 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -178,9 +178,17 @@ public: FloatingContainerHasWidgetIcon = 0x80000, //!< If set, the Floating Widget icon reflects the icon of the current dock widget otherwise it displays application icon HideSingleCentralWidgetTitleBar = 0x100000, //!< If there is only one single visible dock widget in the main dock container (the dock manager) and if this flag is set, then the titlebar of this dock widget will be hidden //!< this only makes sense for non draggable and non floatable widgets and enables the creation of some kind of "central" widget + FocusHighlighting = 0x200000, //!< enables styling of focused dock widget tabs or floating widget titlebar EqualSplitOnInsertion = 0x400000, ///!< if enabled, the space is equally distributed to all widgets in a splitter + FloatingContainerForceNativeTitleBar = 0x800000, //!< Linux only ! Forces all FloatingContainer to use the native title bar. This might break docking for FloatinContainer on some Window Managers (like Kwin/KDE). + //!< If neither this nor FloatingContainerForceCustomTitleBar is set (the default) native titlebars are used except on known bad systems. + //! Users can overwrite this by setting the environment variable ADS_UseNativeTitle to "1" or "0". + FloatingContainerForceCustomTitleBar = 0x1000000,//!< Linux only ! Forces all FloatingContainer to use a custom title bar. + //!< If neither this nor FloatingContainerForceNativeTitleBar is set (the default) native titlebars are used except on known bad systems. + //! Users can overwrite this by setting the environment variable ADS_UseNativeTitle to "1" or "0". + DefaultDockAreaButtons = DockAreaHasCloseButton | DockAreaHasUndockButton | DockAreaHasTabsMenuButton,///< default configuration of dock area title bar buttons @@ -464,6 +472,10 @@ public: widget->setFocus(Qt::OtherFocusReason); } +#ifdef Q_OS_LINUX + bool eventFilter(QObject *obj, QEvent *e) override; +#endif + public slots: /** * Opens the perspective with the given name. diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index 13c175a..cfe66fd 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -376,6 +376,7 @@ struct FloatingDockContainerPrivate #ifdef Q_OS_LINUX QWidget* MouseEventHandler = nullptr; CFloatingWidgetTitleBar* TitleBar = nullptr; + bool IsResizing = false; #endif /** @@ -410,10 +411,11 @@ struct FloatingDockContainerPrivate void setWindowTitle(const QString &Text) { #ifdef Q_OS_LINUX - TitleBar->setTitle(Text); -#else - _this->setWindowTitle(Text); + if(TitleBar){ + TitleBar->setTitle(Text); + } #endif + _this->setWindowTitle(Text); } /** @@ -604,13 +606,36 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) : SLOT(onDockAreasAddedOrRemoved())); #ifdef Q_OS_LINUX - d->TitleBar = new CFloatingWidgetTitleBar(this); - setWindowFlags(windowFlags() | Qt::Tool); - QDockWidget::setWidget(d->DockContainer); - QDockWidget::setFloating(true); - QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures); - setTitleBarWidget(d->TitleBar); - connect(d->TitleBar, SIGNAL(closeRequested()), SLOT(close())); + QDockWidget::setWidget(d->DockContainer); + QDockWidget::setFloating(true); + QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures); + + // 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]; + bool native_window = window_manager != "KWIN"; + // 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::FloatingContainerForceCustomTitleBar )){ + 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); @@ -629,9 +654,7 @@ CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget *DockArea) : CFloatingDockContainer(DockArea->dockManager()) { d->DockContainer->addDockArea(DockArea); -#ifdef Q_OS_LINUX - d->TitleBar->enableCloseButton(isClosable()); -#endif + auto TopLevelDockWidget = topLevelDockWidget(); if (TopLevelDockWidget) { @@ -646,9 +669,6 @@ CFloatingDockContainer::CFloatingDockContainer(CDockWidget *DockWidget) : CFloatingDockContainer(DockWidget->dockManager()) { d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget); -#ifdef Q_OS_LINUX - d->TitleBar->enableCloseButton(isClosable()); -#endif auto TopLevelDockWidget = topLevelDockWidget(); if (TopLevelDockWidget) { @@ -678,12 +698,18 @@ CDockContainerWidget* CFloatingDockContainer::dockContainer() const //============================================================================ void CFloatingDockContainer::changeEvent(QEvent *event) { - QWidget::changeEvent(event); + Super::changeEvent(event); if ((event->type() == QEvent::ActivationChange) && isActiveWindow()) { ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange "); d->zOrderIndex = ++zOrderCounter; - return; + +#ifdef Q_OS_LINUX + if(d->DraggingState == DraggingFloatingWidget){ + d->titleMouseReleaseEvent(); + d->DraggingState = DraggingInactive; + } +#endif } } @@ -825,13 +851,19 @@ void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos, #ifndef Q_OS_LINUX Q_UNUSED(MouseEventHandler) #endif +#ifdef Q_OS_LINUX + if (!isMaximized()) { + resize(Size); + d->DragStartMousePosition = DragStartMousePos; + } +#else resize(Size); - d->setState(DragState); d->DragStartMousePosition = DragStartMousePos; +#endif + d->setState(DragState); #ifdef Q_OS_LINUX if (DraggingFloatingWidget == DragState) { - setAttribute(Qt::WA_X11NetWmWindowTypeDock, true); d->MouseEventHandler = MouseEventHandler; if (d->MouseEventHandler) { @@ -839,7 +871,13 @@ void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos, } } #endif +#ifdef Q_OS_LINUX + if (!isMaximized()) { + moveFloating(); + } +#else moveFloating(); +#endif show(); } @@ -850,7 +888,6 @@ void CFloatingDockContainer::moveFloating() const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition - QPoint(BorderSize, 0); move(moveToPos); - switch (d->DraggingState) { case DraggingMousePressed: @@ -949,11 +986,16 @@ bool CFloatingDockContainer::restoreState(CDockingStateReader &Stream, { return false; } - onDockAreasAddedOrRemoved(); +#ifdef Q_OS_LINUX + if(d->TitleBar){ + d->TitleBar->setMaximizedIcon(windowState() == Qt::WindowMaximized); + } +#endif return true; } + //============================================================================ bool CFloatingDockContainer::hasTopLevelDockWidget() const { @@ -977,19 +1019,17 @@ void CFloatingDockContainer::finishDragging() { ADS_PRINT("CFloatingDockContainer::finishDragging"); #ifdef Q_OS_LINUX - setAttribute(Qt::WA_X11NetWmWindowTypeDock, false); - setWindowOpacity(1); - activateWindow(); - if (d->MouseEventHandler) - { - d->MouseEventHandler->releaseMouse(); - d->MouseEventHandler = nullptr; - } + setWindowOpacity(1); + activateWindow(); + if (d->MouseEventHandler) + { + d->MouseEventHandler->releaseMouse(); + d->MouseEventHandler = nullptr; + } #endif - d->titleMouseReleaseEvent(); + d->titleMouseReleaseEvent(); } - #ifdef Q_OS_MACOS //============================================================================ bool CFloatingDockContainer::event(QEvent *e) @@ -1092,6 +1132,71 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event) } #endif + +#ifdef Q_OS_LINUX +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->DraggingState = DraggingFloatingWidget; + d->updateDropOverlays(QCursor::pos()); + } + d->IsResizing = false; +} + +bool CFloatingDockContainer::hasNativeTitleBar(){ + return d->TitleBar == nullptr; +} +#endif + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/FloatingDockContainer.h b/src/FloatingDockContainer.h index 0099e2a..6062315 100644 --- a/src/FloatingDockContainer.h +++ b/src/FloatingDockContainer.h @@ -185,6 +185,11 @@ protected: // reimplements QWidget virtual void moveEvent(QMoveEvent *event) override; #endif +#ifdef Q_OS_LINUX + virtual void moveEvent(QMoveEvent *event) override; + virtual void resizeEvent(QResizeEvent *event) override; +#endif + #ifdef Q_OS_WIN /** * Native event filter for handling WM_MOVING messages on Windows @@ -194,7 +199,7 @@ protected: // reimplements QWidget public: - using Super = QWidget; + using Super = tFloatingWidgetBase; /** * Create empty floating widget - required for restore state @@ -248,6 +253,40 @@ public: * function of the internal container widget. */ QList dockWidgets() const; + +#ifdef Q_OS_LINUX + /** + * 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(); + + bool hasNativeTitleBar(); +#endif + }; // class FloatingDockContainer } // namespace ads diff --git a/src/ads_globals.cpp b/src/ads_globals.cpp index b185e5e..ee72d4e 100644 --- a/src/ads_globals.cpp +++ b/src/ads_globals.cpp @@ -38,12 +38,205 @@ #include "IconProvider.h" #include "ads_globals.h" +#ifdef Q_OS_LINUX +#include +#include +#include +#endif + + +#include namespace ads { namespace internal { +#ifdef Q_OS_LINUX + static QString _window_manager; + static QHash _xcb_atom_cache; + +xcb_atom_t xcb_get_atom(const char *name){ + if (!QX11Info::isPlatformX11()){ + return XCB_ATOM_NONE; + } + auto key = QString(name); + if(_xcb_atom_cache.contains(key)){ + return _xcb_atom_cache[key]; + } + xcb_connection_t *connection = QX11Info::connection(); + xcb_intern_atom_cookie_t request = xcb_intern_atom(connection, 1, strlen(name), name); + xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, request, NULL); + if(!reply){ + return XCB_ATOM_NONE; + } + xcb_atom_t atom = reply->atom; + if(atom == XCB_ATOM_NONE){ + ADS_PRINT("Unknown Atom response from XServer: " << name); + } else { + _xcb_atom_cache.insert(key, atom); + } + free(reply); + return atom; +} + +void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2) +{ + auto connection = QX11Info::connection(); + xcb_atom_t type_atom = xcb_get_atom(type); + xcb_atom_t prop_atom = xcb_get_atom(prop); + xcb_client_message_event_t event; + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.sequence = 0; + event.window = window; + event.type = type_atom; + event.data.data32[0] = set ? 1 : 0; + event.data.data32[1] = prop_atom; + event.data.data32[2] = prop2 ? xcb_get_atom(prop2) : 0; + event.data.data32[3] = 0; + event.data.data32[4] = 0; + + xcb_send_event(connection, 0, window, + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_PROPERTY_CHANGE, + (const char *)&event); + xcb_flush(connection); +} + +xcb_get_property_reply_t* _xcb_get_props(WId window, const char *type, unsigned int atom_type){ + if (!QX11Info::isPlatformX11()){ + return nullptr; + } + xcb_connection_t *connection = QX11Info::connection(); + xcb_atom_t type_atom = xcb_get_atom(type); + if (type_atom == XCB_ATOM_NONE){ + return nullptr; + } + xcb_get_property_cookie_t request = xcb_get_property_unchecked(connection, 0, window, type_atom, atom_type, 0, 1024); + xcb_get_property_reply_t *reply = xcb_get_property_reply(connection, request, nullptr); + if(reply && reply->type != atom_type){ + ADS_PRINT("ATOM TYPE MISMATCH (" << type <<"). Expected: " << atom_type << " but got " << reply->type); + free(reply); + return nullptr; + } + return reply; +} + +template +void xcb_get_prop_list(WId window, const char *type, QVector &ret, unsigned int atom_type){ + xcb_get_property_reply_t *reply = _xcb_get_props(window, type, atom_type); + if (reply && reply->format == 32 && reply->type == atom_type && reply->value_len > 0) { + const xcb_atom_t *data = static_cast(xcb_get_property_value(reply)); + ret.resize(reply->value_len); + memcpy((void *)&ret.first(), (void *)data, reply->value_len * sizeof(T)); + } + free(reply); +} + +QString xcb_get_prop_string(WId window, const char *type){ + QString ret; + // try utf8 first + xcb_atom_t utf_atom = xcb_get_atom("UTF8_STRING"); + if(utf_atom != XCB_ATOM_NONE){ + xcb_get_property_reply_t *reply = _xcb_get_props(window, type, utf_atom); + if (reply && reply->format == 8 && reply->type == utf_atom) { + const char *value = reinterpret_cast(xcb_get_property_value(reply)); + ret = QString::fromUtf8(value, xcb_get_property_value_length(reply)); + free(reply); + return ret; + } + free(reply); + } + // Fall back to XCB_ATOM_STRING + xcb_get_property_reply_t *reply = _xcb_get_props(window, type, XCB_ATOM_STRING); + if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) { + const char *value = reinterpret_cast(xcb_get_property_value(reply)); + ret = QString::fromLatin1(value, xcb_get_property_value_length(reply)); + } + free(reply); + return ret; +} + +bool xcb_dump_props(WId window, const char *type){ + QVector atoms; + xcb_get_prop_list(window, type, atoms, XCB_ATOM_ATOM); + qDebug() << "\n\n!!!" << type << " - " << atoms.length(); + xcb_connection_t *connection = QX11Info::connection(); + for(auto atom : atoms){ + auto foo = xcb_get_atom_name(connection, atom); + auto bar = xcb_get_atom_name_reply(connection, foo, nullptr); + qDebug() << "\t" << xcb_get_atom_name_name(bar); + free(bar); + } + return true; +} + +void xcb_add_prop(bool state, WId window, const char *type, const char *prop){ + if (!QX11Info::isPlatformX11()){ + return; + } + xcb_atom_t prop_atom = xcb_get_atom(prop); + xcb_atom_t type_atom = xcb_get_atom(type); + if(prop_atom == XCB_ATOM_NONE || type_atom == XCB_ATOM_NONE){ + return; + } + QVector atoms; + xcb_get_prop_list(window, type, atoms, XCB_ATOM_ATOM); + int index = atoms.indexOf(prop_atom); + if(state && index == -1){ + atoms.push_back(prop_atom); + } else if(!state && index >= 0){ + atoms.remove(index); + } + xcb_connection_t *connection = QX11Info::connection(); + xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, type_atom, XCB_ATOM_ATOM, 32, atoms.count(), atoms.constData()); + xcb_flush(connection); +} + +QString detectWindowManagerX11(){ + // Tries to detect the windowmanager via X11. + // See: https://specifications.freedesktop.org/wm-spec/1.3/ar01s03.html#idm46018259946000 + if (!QX11Info::isPlatformX11()){ + return "UNKNOWN"; + } + xcb_connection_t *connection = QX11Info::connection(); + xcb_screen_t *first_screen = xcb_setup_roots_iterator (xcb_get_setup (connection)).data; + if(!first_screen){ + ADS_PRINT("No screen found via XCB."); + return "UNKNOWN"; + } + // Get supporting window () + xcb_window_t root = first_screen->root; + xcb_window_t support_win = 0; + QVector sup_windows; + xcb_get_prop_list(root, "_NET_SUPPORTING_WM_CHECK", sup_windows, XCB_ATOM_WINDOW); + if(sup_windows.length() == 0){ + // This doesn't seem to be in use anymore, but wmctrl does the same so lets play safe. + // Both XCB_ATOM_CARDINAL and XCB_ATOM_WINDOW break down to a uint32_t, so reusing sup_windows should be fine. + xcb_get_prop_list(root, "_WIN_SUPPORTING_WM_CHECK", sup_windows, XCB_ATOM_CARDINAL); + } + if(sup_windows.length() == 0){ + ADS_PRINT("Failed to get the supporting window on non EWMH comform WM."); + return "UNKNOWN"; + } + support_win = sup_windows[0]; + QString ret = xcb_get_prop_string(support_win, "_NET_WM_NAME"); + if(ret.length() == 0){ + ADS_PRINT("Empty WM name occured."); + return "UNKNOWN"; + } + return ret; +} + +QString windowManager(){ + if(_window_manager.length() == 0){ + _window_manager = detectWindowManagerX11(); + } + return _window_manager; +} +#endif + + //============================================================================ void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To) { diff --git a/src/ads_globals.h b/src/ads_globals.h index 3523be5..dc278bf 100644 --- a/src/ads_globals.h +++ b/src/ads_globals.h @@ -37,6 +37,10 @@ #include #include +#ifdef Q_OS_LINUX +#include +#endif + QT_FORWARD_DECLARE_CLASS(QAbstractButton) #ifndef ADS_STATIC @@ -122,6 +126,7 @@ enum eBitwiseOperator BitwiseOr }; + namespace internal { static const bool RestoreTesting = true; @@ -129,6 +134,33 @@ static const bool Restore = false; static const char* const ClosedProperty = "close"; static const char* const DirtyProperty = "dirty"; +#ifdef Q_OS_LINUX + // Utils to directly communicate with the X server + /** + * Get atom from cache or request it from the XServer. + */ + xcb_atom_t xcb_get_atom(const char *name); + + /** + * Add a property to a window. Only works on "hidden" windows. + */ + void xcb_add_prop(bool state, WId window, const char *type, const char *prop); + /** + * Updates up to two window properties. Can be set on a visible window. + */ + void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2 = nullptr); + /** + * Only for debugging purposes. + */ + bool xcb_dump_props(WId window, const char *type); + /** + * Gets the active window manager from the X11 Server. + * Requires a EWMH conform window manager (Allmost all common used ones are). + * Returns "UNKNOWN" otherwise. + */ + QString windowManager(); +#endif + /** * Replace the from widget in the given splitter with the To widget */ diff --git a/src/linux/FloatingWidgetTitleBar.cpp b/src/linux/FloatingWidgetTitleBar.cpp index e8e077b..63f88ef 100644 --- a/src/linux/FloatingWidgetTitleBar.cpp +++ b/src/linux/FloatingWidgetTitleBar.cpp @@ -46,6 +46,7 @@ namespace ads using tTabLabel = CElidingLabel; using tCloseButton = QToolButton; +using tMaximizeButton = QToolButton; /** * @brief Private data class of public interface CFloatingWidgetTitleBar @@ -56,6 +57,7 @@ struct FloatingWidgetTitleBarPrivate QLabel *IconLabel = nullptr; tTabLabel *TitleLabel; tCloseButton *CloseButton = nullptr; + tMaximizeButton* MaximizeButton = nullptr; CFloatingDockContainer *FloatingWidget = nullptr; eDragState DragState = DraggingInactive; @@ -83,6 +85,10 @@ void FloatingWidgetTitleBarPrivate::createLayout() CloseButton->setObjectName("floatingTitleCloseButton"); CloseButton->setAutoRaise(true); + MaximizeButton = new tMaximizeButton(); + MaximizeButton->setObjectName("floatingTitleMaximizeButton"); + MaximizeButton->setAutoRaise(true); + // The standard icons do does not look good on high DPI screens QIcon CloseIcon; QPixmap normalPixmap = _this->style()->standardPixmap( @@ -97,6 +103,12 @@ void FloatingWidgetTitleBarPrivate::createLayout() CloseButton->setFocusPolicy(Qt::NoFocus); _this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested())); + _this->setMaximizedIcon(false); + MaximizeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + MaximizeButton->setVisible(true); + MaximizeButton->setFocusPolicy(Qt::NoFocus); + _this->connect(MaximizeButton, &QPushButton::clicked, _this, &CFloatingWidgetTitleBar::maximizeRequested); + QFontMetrics fm(TitleLabel->font()); int Spacing = qRound(fm.height() / 4.0); @@ -107,6 +119,7 @@ void FloatingWidgetTitleBarPrivate::createLayout() _this->setLayout(Layout); Layout->addWidget(TitleLabel, 1); Layout->addSpacing(Spacing); + Layout->addWidget(MaximizeButton); Layout->addWidget(CloseButton); Layout->setAlignment(Qt::AlignCenter); @@ -147,7 +160,7 @@ void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent *ev) d->DragState = DraggingInactive; if (d->FloatingWidget) { - d->FloatingWidget->finishDragging(); + d->FloatingWidget->finishDragging(); } Super::mouseReleaseEvent(ev); } @@ -165,6 +178,12 @@ void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent *ev) // move floating window if (DraggingFloatingWidget == d->DragState) { +#ifdef Q_OS_LINUX + if(d->FloatingWidget->isMaximized()) + { + d->FloatingWidget->showNormal(true); + } +#endif d->FloatingWidget->moveFloating(); Super::mouseMoveEvent(ev); return; @@ -186,11 +205,43 @@ void CFloatingWidgetTitleBar::setTitle(const QString &Text) d->TitleLabel->setText(Text); } - //============================================================================ void CFloatingWidgetTitleBar::updateStyle() { internal::repolishStyle(this, internal::RepolishDirectChildren); } +void CFloatingWidgetTitleBar::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (event->buttons() & Qt::LeftButton) + { + emit maximizeRequested(); + event->accept(); + } + else + { + QWidget::mouseDoubleClickEvent(event); + } +} + +void CFloatingWidgetTitleBar::setMaximizedIcon(bool maximized) +{ + if (maximized) + { + QIcon normalIcon; + auto normalPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarNormalButton, 0, d->MaximizeButton); + normalIcon.addPixmap(normalPixmap, QIcon::Normal); + normalIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled); + d->MaximizeButton->setIcon(normalIcon); + } + else + { + QIcon MaxIcon; + auto maxPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarMaxButton, 0, d->MaximizeButton); + MaxIcon.addPixmap(maxPixmap, QIcon::Normal); + MaxIcon.addPixmap(internal::createTransparentPixmap(maxPixmap, 0.25), QIcon::Disabled); + d->MaximizeButton->setIcon(MaxIcon); + } +} + } // namespace ads diff --git a/src/linux/FloatingWidgetTitleBar.h b/src/linux/FloatingWidgetTitleBar.h index 13914db..ec44cb3 100644 --- a/src/linux/FloatingWidgetTitleBar.h +++ b/src/linux/FloatingWidgetTitleBar.h @@ -55,6 +55,7 @@ protected: virtual void mousePressEvent(QMouseEvent *ev) override; virtual void mouseReleaseEvent(QMouseEvent *ev) override; virtual void mouseMoveEvent(QMouseEvent *ev) override; + virtual void mouseDoubleClickEvent(QMouseEvent *event) override; public: using Super = QWidget; @@ -80,11 +81,21 @@ public: */ void updateStyle(); + /** + * Change the maximize button icon according to current windows state + */ + void setMaximizedIcon(bool maximized); + signals: /** * This signal is emitted, if the close button is clicked. */ void closeRequested(); + + /** + * This signal is emitted, if the maximize button is clicked. + */ + void maximizeRequested(); }; } // namespace ads #endif // FLOATINGWIDGETTITLEBAR_H diff --git a/src/src.pro b/src/src.pro index fba3562..9cd81f4 100644 --- a/src/src.pro +++ b/src/src.pro @@ -72,6 +72,7 @@ SOURCES += \ unix { HEADERS += linux/FloatingWidgetTitleBar.h SOURCES += linux/FloatingWidgetTitleBar.cpp +QT += x11extras } isEmpty(PREFIX){ From 04aecb369304afa7b9a5dc2e0bb3d0b106472670 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 31 Aug 2020 08:32:56 +0200 Subject: [PATCH 25/34] Some code cleanup, adjustments to match ADS coding style --- src/DockFocusController.cpp | 3 +- src/DockManager.cpp | 47 +++++++---- src/FloatingDockContainer.cpp | 119 ++++++++++++++++++--------- src/FloatingDockContainer.h | 4 + src/ads_globals.cpp | 116 ++++++++++++++++++-------- src/ads_globals.h | 46 +++++------ src/linux/FloatingWidgetTitleBar.cpp | 8 +- 7 files changed, 231 insertions(+), 112 deletions(-) diff --git a/src/DockFocusController.cpp b/src/DockFocusController.cpp index 702a00a..c488288 100644 --- a/src/DockFocusController.cpp +++ b/src/DockFocusController.cpp @@ -83,7 +83,8 @@ static void updateDockAreaFocusStyle(CDockAreaWidget* DockArea, bool Focused) #ifdef Q_OS_LINUX static void updateFloatingWidgetFocusStyle(CFloatingDockContainer* FloatingWidget, bool Focused) { - if(FloatingWidget->hasNativeTitleBar()){ + if (FloatingWidget->hasNativeTitleBar()) + { return; } auto TitleBar = qobject_cast(FloatingWidget->titleBarWidget()); diff --git a/src/DockManager.cpp b/src/DockManager.cpp index 3fcac69..d322dfe 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -493,45 +493,62 @@ CDockManager::~CDockManager() //============================================================================ #ifdef Q_OS_LINUX -bool CDockManager::eventFilter(QObject *obj, QEvent *e){ +bool CDockManager::eventFilter(QObject *obj, QEvent *e) +{ // Emulate Qt:Tool behaviour. // Required because on some WMs Tool windows can't be maximized. // Window always on top of the MainWindow. - if(e->type() == QEvent::WindowActivate){ - for(auto _window : floatingWidgets()){ - if(!_window->isVisible() || window()->isMinimized()){ + if (e->type() == QEvent::WindowActivate) + { + for (auto _window : floatingWidgets()) + { + if (!_window->isVisible() || window()->isMinimized()) + { continue; } // setWindowFlags(Qt::WindowStaysOnTopHint) will hide the window and thus requires a show call. // This then leads to flickering and a nasty endless loop (also buggy behaviour on Ubuntu). // So we just do it ourself. - internal::xcb_update_prop(true, _window->window()->winId(), "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP"); + internal::xcb_update_prop(true, _window->window()->winId(), + "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP"); } } - else if(e->type() == QEvent::WindowDeactivate){ - for(auto _window : floatingWidgets()){ - if(!_window->isVisible() || window()->isMinimized()){ + else if (e->type() == QEvent::WindowDeactivate) + { + for (auto _window : floatingWidgets()) + { + if (!_window->isVisible() || window()->isMinimized()) + { continue; } - internal::xcb_update_prop(false, _window->window()->winId(), "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP"); + internal::xcb_update_prop(false, _window->window()->winId(), + "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP"); _window->raise(); } } // Sync minimize with MainWindow - if(e->type() == QEvent::WindowStateChange){ - for(auto _window : floatingWidgets()){ - if(! _window->isVisible()){ + if (e->type() == QEvent::WindowStateChange) + { + for (auto _window : floatingWidgets()) + { + if (! _window->isVisible()) + { continue; } - if(window()->isMinimized()){ + + if (window()->isMinimized()) + { _window->showMinimized(); - } else { + } + else + { _window->setWindowState(_window->windowState() & (~Qt::WindowMinimized)); } } - if(!window()->isMinimized()){ + if (!window()->isMinimized()) + { QApplication::setActiveWindow(window()); } } diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index cfe66fd..8da5626 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -411,7 +411,8 @@ struct FloatingDockContainerPrivate void setWindowTitle(const QString &Text) { #ifdef Q_OS_LINUX - if(TitleBar){ + if (TitleBar) + { TitleBar->setTitle(Text); } #endif @@ -610,24 +611,40 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) : QDockWidget::setFloating(true); QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures); - // 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]; - bool native_window = window_manager != "KWIN"; + 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"){ + 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::FloatingContainerForceCustomTitleBar )){ + } + else if (env == "0") + { native_window = false; } - if(native_window){ + else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceNativeTitleBar)) + { + native_window = true; + } + else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceCustomTitleBar)) + { + 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]; + bool native_window = window_manager != "KWIN"; + } + + if (native_window) + { setTitleBarWidget(new QWidget()); setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint); - } else { + } + else + { d->TitleBar = new CFloatingWidgetTitleBar(this); setTitleBarWidget(d->TitleBar); setWindowFlags(Qt::Window | Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint); @@ -705,7 +722,8 @@ void CFloatingDockContainer::changeEvent(QEvent *event) d->zOrderIndex = ++zOrderCounter; #ifdef Q_OS_LINUX - if(d->DraggingState == DraggingFloatingWidget){ + if (d->DraggingState == DraggingFloatingWidget) + { d->titleMouseReleaseEvent(); d->DraggingState = DraggingInactive; } @@ -848,20 +866,13 @@ void CFloatingDockContainer::showEvent(QShowEvent *event) void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos, const QSize &Size, eDragState DragState, QWidget *MouseEventHandler) { -#ifndef Q_OS_LINUX - Q_UNUSED(MouseEventHandler) -#endif #ifdef Q_OS_LINUX - if (!isMaximized()) { + if (!isMaximized()) + { resize(Size); d->DragStartMousePosition = DragStartMousePos; } -#else - resize(Size); - d->DragStartMousePosition = DragStartMousePos; -#endif d->setState(DragState); -#ifdef Q_OS_LINUX if (DraggingFloatingWidget == DragState) { d->MouseEventHandler = MouseEventHandler; @@ -870,15 +881,20 @@ void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos, d->MouseEventHandler->grabMouse(); } } -#endif -#ifdef Q_OS_LINUX - if (!isMaximized()) { + + if (!isMaximized()) + { moveFloating(); } -#else - moveFloating(); -#endif show(); +#else + Q_UNUSED(MouseEventHandler) + resize(Size); + d->DragStartMousePosition = DragStartMousePos; + d->setState(DragState); + moveFloating(); + show(); +#endif } //============================================================================ @@ -988,7 +1004,8 @@ bool CFloatingDockContainer::restoreState(CDockingStateReader &Stream, } onDockAreasAddedOrRemoved(); #ifdef Q_OS_LINUX - if(d->TitleBar){ + if(d->TitleBar) + { d->TitleBar->setMaximizedIcon(windowState() == Qt::WindowMaximized); } #endif @@ -1134,15 +1151,21 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event) #ifdef Q_OS_LINUX +//============================================================================ void CFloatingDockContainer::onMaximizeRequest() { - if(windowState() == Qt::WindowMaximized){ + if (windowState() == Qt::WindowMaximized) + { showNormal(); - }else{ + } + else + { showMaximized(); } } + +//============================================================================ void CFloatingDockContainer::showNormal(bool fixGeometry) { if (windowState() == Qt::WindowMaximized) @@ -1154,45 +1177,65 @@ void CFloatingDockContainer::showNormal(bool fixGeometry) setGeometry(oldNormal); } } - if(d->TitleBar){ + if(d->TitleBar) + { d->TitleBar->setMaximizedIcon(false); } } + +//============================================================================ void CFloatingDockContainer::showMaximized() { Super::showMaximized(); - if(d->TitleBar){ + if (d->TitleBar) + { d->TitleBar->setMaximizedIcon(true); } } + +//============================================================================ bool CFloatingDockContainer::isMaximized() const { return windowState() == Qt::WindowMaximized; } -void CFloatingDockContainer::show(){ + +//============================================================================ +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){ + + +//============================================================================ +void CFloatingDockContainer::resizeEvent(QResizeEvent *event) +{ d->IsResizing = true; Super::resizeEvent(event); } -void CFloatingDockContainer::moveEvent(QMoveEvent *event){ + +//============================================================================ +void CFloatingDockContainer::moveEvent(QMoveEvent *event) +{ Super::moveEvent(event); - if(!d->IsResizing && event->spontaneous()){ + if (!d->IsResizing && event->spontaneous()) + { d->DraggingState = DraggingFloatingWidget; d->updateDropOverlays(QCursor::pos()); } d->IsResizing = false; } -bool CFloatingDockContainer::hasNativeTitleBar(){ + +//============================================================================ +bool CFloatingDockContainer::hasNativeTitleBar() +{ return d->TitleBar == nullptr; } #endif diff --git a/src/FloatingDockContainer.h b/src/FloatingDockContainer.h index 6062315..a22d394 100644 --- a/src/FloatingDockContainer.h +++ b/src/FloatingDockContainer.h @@ -284,6 +284,10 @@ public: */ 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 diff --git a/src/ads_globals.cpp b/src/ads_globals.cpp index ee72d4e..322046e 100644 --- a/src/ads_globals.cpp +++ b/src/ads_globals.cpp @@ -53,33 +53,44 @@ namespace ads namespace internal { #ifdef Q_OS_LINUX - static QString _window_manager; - static QHash _xcb_atom_cache; +static QString _window_manager; +static QHash _xcb_atom_cache; -xcb_atom_t xcb_get_atom(const char *name){ - if (!QX11Info::isPlatformX11()){ + +//============================================================================ +xcb_atom_t xcb_get_atom(const char *name) +{ + if (!QX11Info::isPlatformX11()) + { return XCB_ATOM_NONE; } auto key = QString(name); - if(_xcb_atom_cache.contains(key)){ + if(_xcb_atom_cache.contains(key)) + { return _xcb_atom_cache[key]; } xcb_connection_t *connection = QX11Info::connection(); xcb_intern_atom_cookie_t request = xcb_intern_atom(connection, 1, strlen(name), name); xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, request, NULL); - if(!reply){ + if (!reply) + { return XCB_ATOM_NONE; } xcb_atom_t atom = reply->atom; - if(atom == XCB_ATOM_NONE){ + if(atom == XCB_ATOM_NONE) + { ADS_PRINT("Unknown Atom response from XServer: " << name); - } else { + } + else + { _xcb_atom_cache.insert(key, atom); } free(reply); return atom; } + +//============================================================================ void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2) { auto connection = QX11Info::connection(); @@ -103,18 +114,24 @@ void xcb_update_prop(bool set, WId window, const char *type, const char *prop, c xcb_flush(connection); } -xcb_get_property_reply_t* _xcb_get_props(WId window, const char *type, unsigned int atom_type){ - if (!QX11Info::isPlatformX11()){ + +//============================================================================ +xcb_get_property_reply_t* _xcb_get_props(WId window, const char *type, unsigned int atom_type) +{ + if (!QX11Info::isPlatformX11()) + { return nullptr; } xcb_connection_t *connection = QX11Info::connection(); xcb_atom_t type_atom = xcb_get_atom(type); - if (type_atom == XCB_ATOM_NONE){ + if (type_atom == XCB_ATOM_NONE) + { return nullptr; } xcb_get_property_cookie_t request = xcb_get_property_unchecked(connection, 0, window, type_atom, atom_type, 0, 1024); xcb_get_property_reply_t *reply = xcb_get_property_reply(connection, request, nullptr); - if(reply && reply->type != atom_type){ + if(reply && reply->type != atom_type) + { ADS_PRINT("ATOM TYPE MISMATCH (" << type <<"). Expected: " << atom_type << " but got " << reply->type); free(reply); return nullptr; @@ -122,10 +139,14 @@ xcb_get_property_reply_t* _xcb_get_props(WId window, const char *type, unsigned return reply; } + +//============================================================================ template -void xcb_get_prop_list(WId window, const char *type, QVector &ret, unsigned int atom_type){ +void xcb_get_prop_list(WId window, const char *type, QVector &ret, unsigned int atom_type) +{ xcb_get_property_reply_t *reply = _xcb_get_props(window, type, atom_type); - if (reply && reply->format == 32 && reply->type == atom_type && reply->value_len > 0) { + if (reply && reply->format == 32 && reply->type == atom_type && reply->value_len > 0) + { const xcb_atom_t *data = static_cast(xcb_get_property_value(reply)); ret.resize(reply->value_len); memcpy((void *)&ret.first(), (void *)data, reply->value_len * sizeof(T)); @@ -133,13 +154,18 @@ void xcb_get_prop_list(WId window, const char *type, QVector &ret, unsigned i free(reply); } -QString xcb_get_prop_string(WId window, const char *type){ + +//============================================================================ +QString xcb_get_prop_string(WId window, const char *type) +{ QString ret; // try utf8 first xcb_atom_t utf_atom = xcb_get_atom("UTF8_STRING"); - if(utf_atom != XCB_ATOM_NONE){ + if(utf_atom != XCB_ATOM_NONE) + { xcb_get_property_reply_t *reply = _xcb_get_props(window, type, utf_atom); - if (reply && reply->format == 8 && reply->type == utf_atom) { + if (reply && reply->format == 8 && reply->type == utf_atom) + { const char *value = reinterpret_cast(xcb_get_property_value(reply)); ret = QString::fromUtf8(value, xcb_get_property_value_length(reply)); free(reply); @@ -149,7 +175,8 @@ QString xcb_get_prop_string(WId window, const char *type){ } // Fall back to XCB_ATOM_STRING xcb_get_property_reply_t *reply = _xcb_get_props(window, type, XCB_ATOM_STRING); - if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) { + if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) + { const char *value = reinterpret_cast(xcb_get_property_value(reply)); ret = QString::fromLatin1(value, xcb_get_property_value_length(reply)); } @@ -157,12 +184,16 @@ QString xcb_get_prop_string(WId window, const char *type){ return ret; } -bool xcb_dump_props(WId window, const char *type){ + +//============================================================================ +bool xcb_dump_props(WId window, const char *type) +{ QVector atoms; xcb_get_prop_list(window, type, atoms, XCB_ATOM_ATOM); qDebug() << "\n\n!!!" << type << " - " << atoms.length(); xcb_connection_t *connection = QX11Info::connection(); - for(auto atom : atoms){ + for (auto atom : atoms) + { auto foo = xcb_get_atom_name(connection, atom); auto bar = xcb_get_atom_name_reply(connection, foo, nullptr); qDebug() << "\t" << xcb_get_atom_name_name(bar); @@ -171,21 +202,29 @@ bool xcb_dump_props(WId window, const char *type){ return true; } -void xcb_add_prop(bool state, WId window, const char *type, const char *prop){ - if (!QX11Info::isPlatformX11()){ + +//============================================================================ +void xcb_add_prop(bool state, WId window, const char *type, const char *prop) +{ + if (!QX11Info::isPlatformX11()) + { return; } xcb_atom_t prop_atom = xcb_get_atom(prop); xcb_atom_t type_atom = xcb_get_atom(type); - if(prop_atom == XCB_ATOM_NONE || type_atom == XCB_ATOM_NONE){ + if (prop_atom == XCB_ATOM_NONE || type_atom == XCB_ATOM_NONE) + { return; } QVector atoms; xcb_get_prop_list(window, type, atoms, XCB_ATOM_ATOM); int index = atoms.indexOf(prop_atom); - if(state && index == -1){ + if (state && index == -1) + { atoms.push_back(prop_atom); - } else if(!state && index >= 0){ + } + else if (!state && index >= 0) + { atoms.remove(index); } xcb_connection_t *connection = QX11Info::connection(); @@ -193,15 +232,20 @@ void xcb_add_prop(bool state, WId window, const char *type, const char *prop){ xcb_flush(connection); } -QString detectWindowManagerX11(){ + +//============================================================================ +QString detectWindowManagerX11() +{ // Tries to detect the windowmanager via X11. // See: https://specifications.freedesktop.org/wm-spec/1.3/ar01s03.html#idm46018259946000 - if (!QX11Info::isPlatformX11()){ + if (!QX11Info::isPlatformX11()) + { return "UNKNOWN"; } xcb_connection_t *connection = QX11Info::connection(); xcb_screen_t *first_screen = xcb_setup_roots_iterator (xcb_get_setup (connection)).data; - if(!first_screen){ + if(!first_screen) + { ADS_PRINT("No screen found via XCB."); return "UNKNOWN"; } @@ -210,26 +254,32 @@ QString detectWindowManagerX11(){ xcb_window_t support_win = 0; QVector sup_windows; xcb_get_prop_list(root, "_NET_SUPPORTING_WM_CHECK", sup_windows, XCB_ATOM_WINDOW); - if(sup_windows.length() == 0){ + if(sup_windows.length() == 0) + { // This doesn't seem to be in use anymore, but wmctrl does the same so lets play safe. // Both XCB_ATOM_CARDINAL and XCB_ATOM_WINDOW break down to a uint32_t, so reusing sup_windows should be fine. xcb_get_prop_list(root, "_WIN_SUPPORTING_WM_CHECK", sup_windows, XCB_ATOM_CARDINAL); } - if(sup_windows.length() == 0){ + if(sup_windows.length() == 0) + { ADS_PRINT("Failed to get the supporting window on non EWMH comform WM."); return "UNKNOWN"; } support_win = sup_windows[0]; QString ret = xcb_get_prop_string(support_win, "_NET_WM_NAME"); - if(ret.length() == 0){ + if(ret.length() == 0) + { ADS_PRINT("Empty WM name occured."); return "UNKNOWN"; } return ret; } -QString windowManager(){ - if(_window_manager.length() == 0){ +//============================================================================ +QString windowManager() +{ + if(_window_manager.length() == 0) + { _window_manager = detectWindowManagerX11(); } return _window_manager; diff --git a/src/ads_globals.h b/src/ads_globals.h index dc278bf..c5fe28d 100644 --- a/src/ads_globals.h +++ b/src/ads_globals.h @@ -135,30 +135,30 @@ static const char* const ClosedProperty = "close"; static const char* const DirtyProperty = "dirty"; #ifdef Q_OS_LINUX - // Utils to directly communicate with the X server - /** - * Get atom from cache or request it from the XServer. - */ - xcb_atom_t xcb_get_atom(const char *name); +// Utils to directly communicate with the X server +/** + * Get atom from cache or request it from the XServer. + */ +xcb_atom_t xcb_get_atom(const char *name); - /** - * Add a property to a window. Only works on "hidden" windows. - */ - void xcb_add_prop(bool state, WId window, const char *type, const char *prop); - /** - * Updates up to two window properties. Can be set on a visible window. - */ - void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2 = nullptr); - /** - * Only for debugging purposes. - */ - bool xcb_dump_props(WId window, const char *type); - /** - * Gets the active window manager from the X11 Server. - * Requires a EWMH conform window manager (Allmost all common used ones are). - * Returns "UNKNOWN" otherwise. - */ - QString windowManager(); +/** + * Add a property to a window. Only works on "hidden" windows. + */ +void xcb_add_prop(bool state, WId window, const char *type, const char *prop); +/** + * Updates up to two window properties. Can be set on a visible window. + */ +void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2 = nullptr); +/** + * Only for debugging purposes. + */ +bool xcb_dump_props(WId window, const char *type); +/** + * Gets the active window manager from the X11 Server. + * Requires a EWMH conform window manager (Allmost all common used ones are). + * Returns "UNKNOWN" otherwise. + */ +QString windowManager(); #endif /** diff --git a/src/linux/FloatingWidgetTitleBar.cpp b/src/linux/FloatingWidgetTitleBar.cpp index 63f88ef..fa1ae5b 100644 --- a/src/linux/FloatingWidgetTitleBar.cpp +++ b/src/linux/FloatingWidgetTitleBar.cpp @@ -154,6 +154,7 @@ void CFloatingWidgetTitleBar::mousePressEvent(QMouseEvent *ev) Super::mousePressEvent(ev); } + //============================================================================ void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent *ev) { @@ -165,6 +166,7 @@ void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent *ev) Super::mouseReleaseEvent(ev); } + //============================================================================ void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent *ev) { @@ -178,12 +180,10 @@ void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent *ev) // move floating window if (DraggingFloatingWidget == d->DragState) { -#ifdef Q_OS_LINUX if(d->FloatingWidget->isMaximized()) { d->FloatingWidget->showNormal(true); } -#endif d->FloatingWidget->moveFloating(); Super::mouseMoveEvent(ev); return; @@ -211,6 +211,8 @@ void CFloatingWidgetTitleBar::updateStyle() internal::repolishStyle(this, internal::RepolishDirectChildren); } + +//============================================================================ void CFloatingWidgetTitleBar::mouseDoubleClickEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) @@ -224,6 +226,8 @@ void CFloatingWidgetTitleBar::mouseDoubleClickEvent(QMouseEvent *event) } } + +//============================================================================ void CFloatingWidgetTitleBar::setMaximizedIcon(bool maximized) { if (maximized) From dcf1ee393ed90275b63c6707b4629b8207be676c Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 31 Aug 2020 09:38:18 +0200 Subject: [PATCH 26/34] Added support for CSS styling of custom widget titlebar close button --- src/FloatingDockContainer.cpp | 2 +- src/ads.qrc | 4 ++ src/linux/FloatingWidgetTitleBar.cpp | 62 ++++++++++++++++---- src/linux/FloatingWidgetTitleBar.h | 8 +++ src/stylesheets/default_linux.css | 16 ++++- src/stylesheets/focus_highlighting_linux.css | 35 ++++++++--- 6 files changed, 107 insertions(+), 20 deletions(-) diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index 8da5626..4f70db2 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -635,7 +635,7 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) : { // 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]; - bool native_window = window_manager != "KWIN"; + native_window = window_manager != "KWIN"; } if (native_window) diff --git a/src/ads.qrc b/src/ads.qrc index 0c9f4e6..a29a542 100644 --- a/src/ads.qrc +++ b/src/ads.qrc @@ -10,5 +10,9 @@ images/tabs-menu-button.svg images/detach-button.svg images/detach-button-disabled.svg + images/maximize-button.svg + images/maximize-button-focused.svg + images/restore-button.svg + images/restore-button-focused.svg diff --git a/src/linux/FloatingWidgetTitleBar.cpp b/src/linux/FloatingWidgetTitleBar.cpp index fa1ae5b..8546748 100644 --- a/src/linux/FloatingWidgetTitleBar.cpp +++ b/src/linux/FloatingWidgetTitleBar.cpp @@ -60,6 +60,9 @@ struct FloatingWidgetTitleBarPrivate tMaximizeButton* MaximizeButton = nullptr; CFloatingDockContainer *FloatingWidget = nullptr; eDragState DragState = DraggingInactive; + QIcon MaximizeIcon; + QIcon NormalIcon; + bool Maximized = false; FloatingWidgetTitleBarPrivate(CFloatingWidgetTitleBar *_public) : _this(_public) @@ -133,6 +136,15 @@ CFloatingWidgetTitleBar::CFloatingWidgetTitleBar(CFloatingDockContainer *parent) { d->FloatingWidget = parent; d->createLayout(); + + auto normalPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarNormalButton, 0, d->MaximizeButton); + d->NormalIcon.addPixmap(normalPixmap, QIcon::Normal); + d->NormalIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled); + + auto maxPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarMaxButton, 0, d->MaximizeButton); + d->MaximizeIcon.addPixmap(maxPixmap, QIcon::Normal); + d->MaximizeIcon.addPixmap(internal::createTransparentPixmap(maxPixmap, 0.25), QIcon::Disabled); + setMaximizedIcon(d->Maximized); } //============================================================================ @@ -230,22 +242,52 @@ void CFloatingWidgetTitleBar::mouseDoubleClickEvent(QMouseEvent *event) //============================================================================ void CFloatingWidgetTitleBar::setMaximizedIcon(bool maximized) { + d->Maximized = maximized; if (maximized) { - QIcon normalIcon; - auto normalPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarNormalButton, 0, d->MaximizeButton); - normalIcon.addPixmap(normalPixmap, QIcon::Normal); - normalIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled); - d->MaximizeButton->setIcon(normalIcon); + d->MaximizeButton->setIcon(d->NormalIcon); } else { - QIcon MaxIcon; - auto maxPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarMaxButton, 0, d->MaximizeButton); - MaxIcon.addPixmap(maxPixmap, QIcon::Normal); - MaxIcon.addPixmap(internal::createTransparentPixmap(maxPixmap, 0.25), QIcon::Disabled); - d->MaximizeButton->setIcon(MaxIcon); + d->MaximizeButton->setIcon(d->MaximizeIcon); } } + +//============================================================================ +void CFloatingWidgetTitleBar::setMaximizeIcon(const QIcon& Icon) +{ + d->MaximizeIcon = Icon; + if (d->Maximized) + { + setMaximizedIcon(d->Maximized); + } +} + + +//============================================================================ +void CFloatingWidgetTitleBar::setNormalIcon(const QIcon& Icon) +{ + d->NormalIcon = Icon; + if (!d->Maximized) + { + setMaximizedIcon(d->Maximized); + } +} + + +//============================================================================ +QIcon CFloatingWidgetTitleBar::maximizeIcon() const +{ + return d->MaximizeIcon; +} + + +//============================================================================ +QIcon CFloatingWidgetTitleBar::normalIcon() const +{ + return d->NormalIcon; +} + + } // namespace ads diff --git a/src/linux/FloatingWidgetTitleBar.h b/src/linux/FloatingWidgetTitleBar.h index ec44cb3..ad6904f 100644 --- a/src/linux/FloatingWidgetTitleBar.h +++ b/src/linux/FloatingWidgetTitleBar.h @@ -30,6 +30,7 @@ // INCLUDES //============================================================================ #include +#include namespace ads { @@ -48,6 +49,8 @@ struct FloatingWidgetTitleBarPrivate; class CFloatingWidgetTitleBar : public QFrame { Q_OBJECT + Q_PROPERTY(QIcon maximizeIcon READ maximizeIcon WRITE setMaximizeIcon) + Q_PROPERTY(QIcon normalIcon READ normalIcon WRITE setNormalIcon) private: FloatingWidgetTitleBarPrivate *d; ///< private data (pimpl) @@ -57,6 +60,11 @@ protected: virtual void mouseMoveEvent(QMouseEvent *ev) override; virtual void mouseDoubleClickEvent(QMouseEvent *event) override; + void setMaximizeIcon(const QIcon& Icon); + QIcon maximizeIcon() const; + void setNormalIcon(const QIcon& Icon); + QIcon normalIcon() const; + public: using Super = QWidget; explicit CFloatingWidgetTitleBar(CFloatingDockContainer *parent = nullptr); diff --git a/src/stylesheets/default_linux.css b/src/stylesheets/default_linux.css index 56b950e..51e52ac 100644 --- a/src/stylesheets/default_linux.css +++ b/src/stylesheets/default_linux.css @@ -92,13 +92,25 @@ QScrollArea#dockWidgetScrollArea { qproperty-iconSize: 16px; } -#floatingTitleCloseButton { - qproperty-icon: url(:/ads/images/close-button.svg); + +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); +} + #floatingTitleCloseButton:hover { background: rgba(0, 0, 0, 24); border: none; diff --git a/src/stylesheets/focus_highlighting_linux.css b/src/stylesheets/focus_highlighting_linux.css index 3f1b393..8e2332a 100644 --- a/src/stylesheets/focus_highlighting_linux.css +++ b/src/stylesheets/focus_highlighting_linux.css @@ -129,42 +129,63 @@ ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar { } +ads--CFloatingWidgetTitleBar { + background: palette(midlight); + qproperty-maximizeIcon: url(:/ads/images/maximize-button.svg); + qproperty-normalIcon: url(:/ads/images/restore-button.svg); +} + ads--CFloatingDockContainer[isActiveWindow="true"] ads--CFloatingWidgetTitleBar { background: palette(highlight); + qproperty-maximizeIcon: url(:/ads/images/maximize-button-focused.svg); + qproperty-normalIcon: url(:/ads/images/restore-button-focused.svg); } ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleLabel { - color: palette(light); + color: palette(light); } -#floatingTitleCloseButton { - qproperty-icon: url(:/ads/images/close-button.svg); +#floatingTitleCloseButton, #floatingTitleMaximizeButton { qproperty-iconSize: 16px; border: none; margin: 3px; } -#floatingTitleCloseButton:hover { + +#floatingTitleCloseButton { + qproperty-icon: url(:/ads/images/close-button.svg); +} + + +#floatingTitleCloseButton:hover, #floatingTitleMaximizeButton:hover { background: rgba(0, 0, 0, 24); border: none; } -#floatingTitleCloseButton:pressed { + +#floatingTitleCloseButton:pressed, #floatingTitleMaximizeButton:pressed { background: rgba(0, 0, 0, 48); } +ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleMaximizeButton { + qproperty-iconSize: 16px; +} + + ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleCloseButton { qproperty-icon: url(:/ads/images/close-button-focused.svg); qproperty-iconSize: 16px; } -ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleCloseButton:hover { +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"] #floatingTitleCloseButton:pressed, +ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleMaximizeButton:pressed { background: rgba(255, 255, 255, 92); } From 059a05548356df5c9ec4e9a5bc758e0775917cf2 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 31 Aug 2020 09:48:32 +0200 Subject: [PATCH 27/34] Renamed FloatingContainerForceCustomTitleBar to FloatingWidgetForceQWidgetTitleBar --- src/DockManager.h | 2 +- src/FloatingDockContainer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DockManager.h b/src/DockManager.h index addbc25..a987990 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -185,7 +185,7 @@ public: FloatingContainerForceNativeTitleBar = 0x800000, //!< Linux only ! Forces all FloatingContainer to use the native title bar. This might break docking for FloatinContainer on some Window Managers (like Kwin/KDE). //!< If neither this nor FloatingContainerForceCustomTitleBar is set (the default) native titlebars are used except on known bad systems. //! Users can overwrite this by setting the environment variable ADS_UseNativeTitle to "1" or "0". - FloatingContainerForceCustomTitleBar = 0x1000000,//!< Linux only ! Forces all FloatingContainer to use a custom title bar. + FloatingContainerForceQWidgetTitleBar = 0x1000000,//!< Linux only ! Forces all FloatingContainer to use a QWidget based title bar. //!< If neither this nor FloatingContainerForceNativeTitleBar is set (the default) native titlebars are used except on known bad systems. //! Users can overwrite this by setting the environment variable ADS_UseNativeTitle to "1" or "0". diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index 4f70db2..09b31bc 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -627,7 +627,7 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) : { native_window = true; } - else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceCustomTitleBar)) + else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceQWidgetTitleBar)) { native_window = false; } From 73f42d55ca0f38fdd8449f5983b189acdc5e6216 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 31 Aug 2020 11:57:30 +0200 Subject: [PATCH 28/34] Updated linux stylesheets to fix titlebar issue on KDE --- src/stylesheets/focus_highlighting_linux.css | 109 ++++++++++--------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/src/stylesheets/focus_highlighting_linux.css b/src/stylesheets/focus_highlighting_linux.css index 8e2332a..bea52d0 100644 --- a/src/stylesheets/focus_highlighting_linux.css +++ b/src/stylesheets/focus_highlighting_linux.css @@ -2,89 +2,89 @@ * Default style sheet on Linux Platforms with focus highlighting flag enabled */ ads--CDockContainerWidget { - background: palette(dark); + background: palette(dark); } ads--CDockContainerWidget QSplitter::handle { - background: palette(dark); + background: palette(dark); } ads--CDockAreaWidget { - background: palette(window); - border: 1px solid white; + background: palette(window); + border: 1px solid white; } ads--CDockAreaWidget #tabsMenuButton::menu-indicator { - image: none; + image: none; } ads--CDockWidgetTab { - background: palette(window); - border-color: palette(light); - border-style: solid; - border-width: 0 1px 0 0; - padding: 0 0px; + background: palette(window); + border-color: palette(light); + 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(light)); - /*background: palette(highlight);*/ + background: qlineargradient(spread : pad, x1 : 0, y1 : 0, x2 : 0, y2 : 0.5, stop : 0 + palette(window), stop:1 palette(light)); + /*background: palette(highlight);*/ } ads--CDockWidgetTab QLabel { - color: palette(dark); + color: palette(dark); } ads--CDockWidgetTab[activeTab="true"] QLabel { - color: palette(foreground); + color: palette(foreground); } ads--CDockWidget { - background: palette(light); - border-color: palette(light); - border-style: solid; - border-width: 1px 0 0 0; + background: palette(light); + border-color: palette(light); + border-style: solid; + border-width: 1px 0 0 0; } ads--CTitleBarButton { - padding: 0px 0px; + padding: 0px 0px; } QScrollArea#dockWidgetScrollArea { - padding: 0px; - border: none; + padding: 0px; + border: none; } #dockAreaCloseButton { - qproperty-icon: url(:/ads/images/close-button.svg), - url(:/ads/images/close-button-disabled.svg) disabled; - qproperty-iconSize: 16px; + 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; + qproperty-icon: url(:/ads/images/detach-button.svg), + url(:/ads/images/detach-button-disabled.svg) disabled; + qproperty-iconSize: 16px; } #tabCloseButton { - margin-top: 2px; - background: none; - border: none; - padding: 0px -2px; - qproperty-icon: url(:/ads/images/close-button.svg), - url(:/ads/images/close-button-disabled.svg) disabled; - qproperty-iconSize: 16px; + margin-top: 2px; + background: none; + border: none; + padding: 0px -2px; + qproperty-icon: url(:/ads/images/close-button.svg), + url(:/ads/images/close-button-disabled.svg) disabled; + qproperty-iconSize: 16px; } #tabCloseButton:hover { - /*border: 1px solid rgba(0, 0, 0, 32);*/ - background: rgba(0, 0, 0, 24); + /*border: 1px solid rgba(0, 0, 0, 32);*/ + background: rgba(0, 0, 0, 24); } #tabCloseButton:pressed { - background: rgba(0, 0, 0, 48); + background: rgba(0, 0, 0, 48); } @@ -96,48 +96,48 @@ QScrollArea#dockWidgetScrollArea { /* Focus related styling */ ads--CDockWidgetTab[focused="true"] { - background: palette(highlight); - border-color: palette(highlight); + background: palette(highlight); + border-color: palette(highlight); } ads--CDockWidgetTab[focused="true"]>#tabCloseButton { - qproperty-icon: url(:/ads/images/close-button-focused.svg) + qproperty-icon: url(:/ads/images/close-button-focused.svg) } ads--CDockWidgetTab[focused="true"]>#tabCloseButton:hover { - background: rgba(255, 255, 255, 48); + background: rgba(255, 255, 255, 48); } ads--CDockWidgetTab[focused="true"]>#tabCloseButton:pressed { - background: rgba(255, 255, 255, 92); + background: rgba(255, 255, 255, 92); } ads--CDockWidgetTab[focused="true"] QLabel { - color: palette(light); + color: palette(light); } ads--CDockAreaTitleBar { - background: transparent; - border-bottom: 2px solid palette(light); - padding-bottom: 0px; + background: transparent; + border-bottom: 2px solid palette(light); + padding-bottom: 0px; } ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar { - background: transparent; - border-bottom: 2px solid palette(highlight); - padding-bottom: 0px; + background: transparent; + border-bottom: 2px solid palette(highlight); + padding-bottom: 0px; } ads--CFloatingWidgetTitleBar { - background: palette(midlight); qproperty-maximizeIcon: url(:/ads/images/maximize-button.svg); qproperty-normalIcon: url(:/ads/images/restore-button.svg); } +/* does not properly work on KDE ads--CFloatingDockContainer[isActiveWindow="true"] ads--CFloatingWidgetTitleBar { - background: palette(highlight); + background: palette(highlight); qproperty-maximizeIcon: url(:/ads/images/maximize-button-focused.svg); qproperty-normalIcon: url(:/ads/images/restore-button-focused.svg); } @@ -145,11 +145,12 @@ ads--CFloatingDockContainer[isActiveWindow="true"] ads--CFloatingWidgetTitleBar ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleLabel { color: palette(light); } +*/ #floatingTitleCloseButton, #floatingTitleMaximizeButton { qproperty-iconSize: 16px; border: none; - margin: 3px; + margin: 6px 3px 6px 3px; } @@ -174,6 +175,7 @@ ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleMaximizeButton } +/* does not properly work on KDE ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleCloseButton { qproperty-icon: url(:/ads/images/close-button-focused.svg); qproperty-iconSize: 16px; @@ -189,3 +191,4 @@ ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleCloseButton:pre ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleMaximizeButton:pressed { background: rgba(255, 255, 255, 92); } +*/ From 0eb3978aee008e08aff0b511f98865820efdee62 Mon Sep 17 00:00:00 2001 From: githubuser0xFFFF Date: Mon, 31 Aug 2020 12:51:42 +0200 Subject: [PATCH 29/34] Update .travis.yml Added x11extras --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index d45b526..fd654a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,7 @@ matrix: packages: - qt55base - qt55tools + - qt55x11extras - gcc-9 - g++-9 script: @@ -44,6 +45,7 @@ matrix: packages: - qt514base - qt514tools + - qt514x11extras - gcc-9 - g++-9 - libc6-i386 @@ -74,6 +76,7 @@ matrix: packages: - qt514base - qt514tools + - qt514x11extras - gcc-9 - g++-9 - libc6-i386 @@ -104,6 +107,7 @@ matrix: packages: - qt514base - qt514tools + - qt514x11extras - gcc-9 - g++-9 - libc6-i386 @@ -140,6 +144,7 @@ matrix: packages: - qt514base - qt514tools + - qt514x11extras - gcc-9 - g++-9 - libc6-i386 From 76304172abfcfc4765f420f9a8331d7efb05376c Mon Sep 17 00:00:00 2001 From: githubuser0xFFFF Date: Mon, 31 Aug 2020 13:00:27 +0200 Subject: [PATCH 30/34] Update linux-builds.yml Added x11extras to workflow --- .github/workflows/linux-builds.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/linux-builds.yml b/.github/workflows/linux-builds.yml index 5f67e7f..4be2a29 100644 --- a/.github/workflows/linux-builds.yml +++ b/.github/workflows/linux-builds.yml @@ -16,6 +16,7 @@ jobs: run: | sudo apt-get update --fix-missing sudo apt-get install qt5-default + sudo apt-get install libqt5x11extras5-dev - name: qmake run: qmake - name: make From 175c836c935cafb2fcf13dea07181c414da55e56 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 31 Aug 2020 13:04:15 +0200 Subject: [PATCH 31/34] Added Qt5x11extras to CMake build --- adsConfig.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/adsConfig.cmake b/adsConfig.cmake index 542e5c9..d006a3f 100644 --- a/adsConfig.cmake +++ b/adsConfig.cmake @@ -2,4 +2,5 @@ include(CMakeFindDependencyMacro) find_dependency(Qt5Core ${REQUIRED_QT_VERSION} REQUIRED) find_dependency(Qt5Gui ${REQUIRED_QT_VERSION} REQUIRED) find_dependency(Qt5Widgets ${REQUIRED_QT_VERSION} REQUIRED) +find_dependency(Qt5X11Extras ${REQUIRED_QT_VERSION} REQUIRED) include("${CMAKE_CURRENT_LIST_DIR}/adsTargets.cmake") \ No newline at end of file From abdc0dc0ddf674355736f66b8d5699ab344bafe9 Mon Sep 17 00:00:00 2001 From: githubuser0xFFFF Date: Mon, 31 Aug 2020 16:10:53 +0200 Subject: [PATCH 32/34] Update .travis.yml Added libqt5x11extras5-dev to travis build --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.travis.yml b/.travis.yml index fd654a5..7e38344 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,8 @@ matrix: os: linux dist: trusty group: stable + before_install: + - sudo apt-get install libqt5x11extras5-dev addons: apt: sources: @@ -36,6 +38,8 @@ matrix: services: - xvfb compiler: gcc + before_install: + - sudo apt-get install libqt5x11extras5-dev addons: apt: sources: @@ -68,6 +72,8 @@ matrix: - xvfb compiler: gcc addons: + before_install: + - sudo apt-get install libqt5x11extras5-dev apt: sources: - ubuntu-toolchain-r-test @@ -98,6 +104,8 @@ matrix: services: - xvfb compiler: gcc + before_install: + - sudo apt-get install libqt5x11extras5-dev addons: apt: sources: @@ -135,6 +143,8 @@ matrix: services: - xvfb compiler: gcc + before_install: + - sudo apt-get install libqt5x11extras5-dev addons: apt: sources: From 831d90ebf57c2bd96d28ffaec4aa142433aaa0a4 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 31 Aug 2020 16:20:36 +0200 Subject: [PATCH 33/34] Added X11Etras package to CMakeLists.txt --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4531cc1..6e31d27 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.5) project(QtAdvancedDockingSystem LANGUAGES CXX VERSION ${VERSION_SHORT}) -find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED) +find_package(Qt5 5.5 COMPONENTS Core Gui Widgets X11Extras REQUIRED) set(CMAKE_INCLUDE_CURRENT_DIR ON) if(BUILD_STATIC) set(CMAKE_STATIC_LIBRARY_SUFFIX "_static${CMAKE_STATIC_LIBRARY_SUFFIX}") From 423bab9954dfb7b1ee96e166901bba0a81703311 Mon Sep 17 00:00:00 2001 From: githubuser0xFFFF Date: Mon, 31 Aug 2020 16:30:29 +0200 Subject: [PATCH 34/34] Update README.md Some small changes in README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9f549f8..c23768e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Advanced Docking System for Qt -[![Build Status](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System.svg?branch=master)](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System) +[![Build status](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/workflows/linux-builds/badge.svg)](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/actions?query=workflow%3Alinux-builds) [![Build status](https://ci.appveyor.com/api/projects/status/qcfb3cy932jw9mpy/branch/master?svg=true)](https://ci.appveyor.com/project/githubuser0xFFFF/qt-advanced-docking-system/branch/master) [![License: LGPL v2.1](https://img.shields.io/badge/License-LGPL%20v2.1-blue.svg)](gnu-lgpl-v2.1.md) @@ -357,4 +357,4 @@ of the open editor windows. [learn more...](https://github.com/stijnherfst/HiveWE) -![HiveWE](doc/showcase_hivewe.png) \ No newline at end of file +![HiveWE](doc/showcase_hivewe.png)