2222
2323#include " dockwindow.h"
2424
25- #include < QTimer>
26-
2725#include " kddockwidgets/src/LayoutSaver.h"
28- #include " kddockwidgets/src/Config.h"
2926#include " kddockwidgets/src/core/DockRegistry.h"
3027#include " kddockwidgets/src/core/Layout.h"
3128#include " kddockwidgets/src/core/MainWindow.h"
4441#include " docktoolbarview.h"
4542#include " dockingholderview.h"
4643#include " dockwindow.h"
44+ #include " topleveltoolbarslayout.h"
4745
4846#include " muse_framework_config.h"
4947
@@ -53,9 +51,6 @@ using namespace muse::dock;
5351using namespace muse ::async;
5452
5553namespace muse ::dock {
56- // ! NOTE: Toolbar's maximum lenght, see DockToolBar.qml
57- static constexpr int UNCONSTRAINED_TOOLBAR_WIDTH = 16777215 ;
58-
5954static const QList<Location> POSSIBLE_LOCATIONS {
6055 Location::Left,
6156 Location::Right,
@@ -103,22 +98,6 @@ static void clearRegistry(int ctx)
10398}
10499}
105100
106- class DockWindow ::UniqueConnectionHolder : public QObject
107- {
108- Q_OBJECT
109- public:
110- UniqueConnectionHolder (DockPageView* page, DockWindow* parent)
111- : QObject(parent), m_page(page) {}
112-
113- void alignTopLevelToolBars ()
114- {
115- static_cast <DockWindow*>(parent ())->alignTopLevelToolBars (m_page);
116- }
117-
118- private:
119- DockPageView* m_page = nullptr ;
120- };
121-
122101DockWindow::DockWindow (QQuickItem* parent)
123102 : QQuickItem(parent), muse::Contextable(muse::iocCtxForQmlObject(this )),
124103 m_toolBars(this ),
@@ -129,12 +108,6 @@ DockWindow::DockWindow(QQuickItem* parent)
129108DockWindow::~DockWindow ()
130109{
131110 dockWindowProvider ()->deinit ();
132-
133- // Without this, the connections would be deleted by the QObject destructor,
134- // because they are child objects of this. But since they use DockWindow-
135- // specific code (rather than QObject-specific), we need to delete them
136- // before the end of the DockWindow destructor.
137- qDeleteAll (m_pageConnections);
138111}
139112
140113void DockWindow::componentComplete ()
@@ -149,91 +122,28 @@ void DockWindow::componentComplete()
149122 KDDockWidgets::MainWindowOption_None,
150123 this );
151124
125+ m_topLevelToolBarsLayout = new TopLevelToolBarsLayout (m_mainWindow, this );
126+
152127 connect (qApp, &QCoreApplication::aboutToQuit, this , &DockWindow::onQuit);
153128 connect (this , &QQuickItem::windowChanged, this , &DockWindow::windowPropertyChanged);
154129}
155130
156131void DockWindow::geometryChange (const QRectF& newGeometry, const QRectF& oldGeometry)
157132{
158- const bool widthChanged = m_currentPage && !qFuzzyCompare (newGeometry.width (), oldGeometry.width ());
159- const bool shrinking = widthChanged && newGeometry.width () < oldGeometry.width ();
160-
161- if (widthChanged) {
162- m_pendingWidth = int (newGeometry.width ());
163-
164- if (shrinking) {
165- // ! NOTE: Unpin the paddings first so compact mode can actually shrink the toolbars' content
166- for (DockToolBarView* toolBar : topLevelToolBars (m_currentPage)) {
167- toolBar->setMinimumWidth (toolBar->contentWidth ());
168- }
169- }
170-
171- adjustContentForAvailableSpace (m_currentPage);
172- alignTopLevelToolBars (m_currentPage);
173-
174- // ! NOTE: Apply the new size to the layout synchronously
175- applyLayoutSizeToFitWindow ();
176-
177- m_pendingWidth = -1 ;
178-
179- // ! NOTE: The synchronous resize above can be partial when KDDockWidgets' async item-size sync
180- // ! hasn't settled yet. So let's shedule another layout
181- scheduleDeferredLayoutFix ();
182- }
183-
184133 QQuickItem::geometryChange (newGeometry, oldGeometry);
185- }
186-
187- void DockWindow::applyLayoutSizeToFitWindow ()
188- {
189- KDDockWidgets::Core::MainWindow* mw = m_mainWindow ? m_mainWindow->mainWindow () : nullptr ;
190- KDDockWidgets::Core::Layout* layout = mw ? mw->layout () : nullptr ;
191- if (!layout) {
192- return ;
193- }
194-
195- const int targetWidth = m_pendingWidth >= 0 ? m_pendingWidth : int (width ());
196- const int layoutMin = layout->layoutMinimumSize ().width ();
197-
198- const int applyWidth = std::max (targetWidth, layoutMin);
199134
200- if (applyWidth != layout-> layoutSize () .width ()) {
201- layout-> setLayoutSize ( QSize (applyWidth, layout-> layoutSize (). height ()) );
135+ if (m_currentPage && ! qFuzzyCompare (newGeometry. width (), oldGeometry .width () )) {
136+ polish ( );
202137 }
203138}
204139
205- void DockWindow::scheduleDeferredLayoutFix ()
140+ void DockWindow::updatePolish ()
206141{
207- if (m_layoutFixScheduled) {
208- return ;
209- }
142+ QQuickItem::updatePolish ();
210143
211- m_layoutFixScheduled = true ;
212-
213- QTimer::singleShot (0 , this , [this ]() {
214- runDeferredLayoutFix ();
215- });
216- }
217-
218- void DockWindow::runDeferredLayoutFix ()
219- {
220- m_layoutFixScheduled = false ;
221-
222- if (!m_currentPage) {
223- return ;
224- }
225-
226- adjustContentForAvailableSpace (m_currentPage);
227- alignTopLevelToolBars (m_currentPage);
228-
229- // ! NOTE: Force the layouting items to pick up the current dock minimums
230- for (DockBase* dock : m_currentPage->allDocks ()) {
231- if (dock) {
232- dock->syncLayoutItemMinSize ();
233- }
144+ if (m_topLevelToolBarsLayout) {
145+ m_topLevelToolBarsLayout->relayout ();
234146 }
235-
236- applyLayoutSizeToFitWindow ();
237147}
238148
239149void DockWindow::onQuit ()
@@ -492,95 +402,6 @@ void DockWindow::loadPanels(const DockPageView* page)
492402 }
493403}
494404
495- void DockWindow::alignTopLevelToolBars (const DockPageView* page)
496- {
497- const QList<DockToolBarView*> topToolBars = topLevelToolBars (page);
498-
499- // ! NOTE: Reset paddings/pins first, so that widths from a previous
500- // ! configuration do not accumulate
501- for (DockToolBarView* toolBar : topToolBars) {
502- toolBar->setMaximumWidth (UNCONSTRAINED_TOOLBAR_WIDTH );
503- toolBar->setMinimumWidth (toolBar->contentWidth ());
504- }
505-
506- DockToolBarView* lastLeftToolBar = nullptr ;
507- DockToolBarView* lastCentralToolBar = nullptr ;
508-
509- int leftBlockWidth = 0 ;
510- int centralBlockWidth = 0 ;
511- int rightBlockWidth = 0 ;
512-
513- int leftCount = 0 ;
514- int centralCount = 0 ;
515- int rightCount = 0 ;
516-
517- const int separator = KDDockWidgets::Config::self (iocContext ()->id ).separatorThickness ();
518-
519- for (DockToolBarView* toolBar : topToolBars) {
520- if (toolBar->floating () || !toolBar->isVisible ()) {
521- continue ;
522- }
523-
524- switch (static_cast <DockToolBarAlignment::Type>(toolBar->alignment ())) {
525- case DockToolBarAlignment::Left:
526- lastLeftToolBar = toolBar;
527- leftBlockWidth += toolBar->contentWidth ();
528- ++leftCount;
529- break ;
530- case DockToolBarAlignment::Center:
531- lastCentralToolBar = toolBar;
532- centralBlockWidth += toolBar->contentWidth ();
533- ++centralCount;
534- break ;
535- case DockToolBarAlignment::Right:
536- rightBlockWidth += toolBar->contentWidth ();
537- ++rightCount;
538- break ;
539- }
540- }
541-
542- leftBlockWidth += separator * std::max (0 , leftCount - 1 );
543- centralBlockWidth += separator * std::max (0 , centralCount - 1 );
544- rightBlockWidth += separator * std::max (0 , rightCount - 1 );
545-
546- const int separatorLeftCentral = (leftCount > 0 && centralCount > 0 ) ? separator : 0 ;
547- const int separatorCentralRight = (centralCount > 0 && rightCount > 0 ) ? separator : 0 ;
548- const int separatorLeftRight = (leftCount > 0 && centralCount == 0 && rightCount > 0 ) ? separator : 0 ;
549-
550- const int occupied = leftBlockWidth + centralBlockWidth + rightBlockWidth
551- + separatorLeftCentral + separatorCentralRight + separatorLeftRight;
552-
553- // ! NOTE: During a resize the new width isn't propagated to width yet
554- const int availableWidth = m_pendingWidth >= 0 ? m_pendingWidth : int (width ());
555-
556- const int freeSpace = availableWidth - occupied;
557- if (freeSpace <= 0 ) {
558- return ;
559- }
560-
561- DockToolBarView* grower = lastLeftToolBar ? lastLeftToolBar : lastCentralToolBar;
562-
563- int paddingForLastCentral = 0 ;
564- if (lastCentralToolBar && lastCentralToolBar != grower) {
565- paddingForLastCentral = (availableWidth - centralBlockWidth) / 2 - rightBlockWidth - separatorCentralRight;
566- paddingForLastCentral = std::min (std::max (paddingForLastCentral, 0 ), freeSpace);
567- }
568-
569- for (DockToolBarView* toolBar : topToolBars) {
570- if (toolBar->floating () || !toolBar->isVisible () || toolBar == grower) {
571- continue ;
572- }
573-
574- const int pinnedWidth = (toolBar == lastCentralToolBar)
575- ? toolBar->contentWidth () + paddingForLastCentral
576- : toolBar->contentWidth ();
577-
578- // ! NOTE: max before min
579- toolBar->setMaximumWidth (pinnedWidth);
580- toolBar->setMinimumWidth (pinnedWidth);
581- }
582- }
583-
584405void DockWindow::addDock (DockBase* dock, Location location, const DockBase* relativeTo)
585406{
586407 TRACEFUNC ;
@@ -850,7 +671,7 @@ void DockWindow::initDocks(DockPageView* page)
850671 TRACEFUNC ;
851672
852673 // ! before init we should correct toolbars sizes
853- adjustContentForAvailableSpace (page);
674+ m_topLevelToolBarsLayout-> adjustContentForAvailableSpace (page);
854675
855676 for (DockToolBarView* toolbar : m_toolBars.list ()) {
856677 toolbar->setParentItem (this );
@@ -862,88 +683,8 @@ void DockWindow::initDocks(DockPageView* page)
862683 page->init ();
863684 }
864685
865- alignTopLevelToolBars (page);
866-
867- if (!m_pageConnections.contains (page)) {
868- m_pageConnections[page] = new UniqueConnectionHolder (page, this );
869- }
870-
871- UniqueConnectionHolder* holder = m_pageConnections[page];
872-
873- for (DockToolBarView* toolbar : topLevelToolBars (page)) {
874- connect (toolbar, &DockToolBarView::floatingChanged,
875- this , &DockWindow::scheduleDeferredLayoutFix, Qt::UniqueConnection);
876-
877- connect (toolbar, &DockToolBarView::contentSizeChanged,
878- holder, &UniqueConnectionHolder::alignTopLevelToolBars, Qt::UniqueConnection);
879-
880- connect (toolbar, &DockToolBarView::visibleChanged,
881- holder, &UniqueConnectionHolder::alignTopLevelToolBars, Qt::UniqueConnection);
882- }
883- }
884-
885- void DockWindow::adjustContentForAvailableSpace (DockPageView* page)
886- {
887- if (!page) {
888- return ;
889- }
890-
891- int spaceWidth = m_pendingWidth >= 0 ? m_pendingWidth : int (width ());
892-
893- auto adjustDocks = [&spaceWidth](QList<DockBase*> docks) {
894- int width = 0 ;
895- for (DockBase* dock : docks) {
896- width += dock->contentWidth ();
897- }
898-
899- docks.erase (std::remove_if (docks.begin (), docks.end (), [](const DockBase* dock){
900- return dock->compactPriorityOrder () == -1 ;
901- }), docks.end ());
902-
903- if (docks.empty ()) {
904- return ;
905- }
906-
907- std::sort (docks.begin (), docks.end (), [](const DockBase* dock1, DockBase* dock2) {
908- return dock1->compactPriorityOrder () < dock2->compactPriorityOrder ();
909- });
910-
911- if (width >= spaceWidth) {
912- for (DockBase* dock : docks) {
913- if (!dock->isCompact ()) {
914- dock->setIsCompact (true );
915-
916- width -= dock->nonCompactWidth ();
917- width += dock->width ();
918- }
919- }
920- } else {
921- for (int i = docks.size () - 1 ; i >= 0 ; i--) {
922- DockBase* dock = docks.at (i);
923- if (!dock->isCompact ()) {
924- continue ;
925- }
926-
927- int actualWidth = dock->contentWidth ();
928- int nonCompactWidth = dock->nonCompactWidth ();
929- if (width - actualWidth + nonCompactWidth < spaceWidth) {
930- dock->setIsCompact (false );
931- }
932-
933- break ;
934- }
935- }
936- };
937-
938- QList<DockBase*> topLevelToolBarsDocks;
939-
940- for (DockToolBarView* toolBar : topLevelToolBars (page)) {
941- if (!toolBar->dockWidget ()->isFloating () && toolBar->isVisible ()) {
942- topLevelToolBarsDocks << toolBar;
943- }
944- }
945-
946- adjustDocks (topLevelToolBarsDocks);
686+ m_topLevelToolBarsLayout->setUpPageConnections (page);
687+ m_topLevelToolBarsLayout->scheduleRelayout ();
947688}
948689
949690void DockWindow::notifyAboutDocksOpenStatus ()
@@ -985,5 +726,3 @@ QList<DockToolBarView*> DockWindow::topLevelToolBars(const DockPageView* page) c
985726
986727 return toolBars;
987728}
988-
989- #include " dockwindow.moc"
0 commit comments