LCOV - code coverage report
Current view: top level - muse/framework/dockwindow_v2/internal - dockbase.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 54.7 % 468 256
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include "dockbase.h"
      24              : 
      25              : #include <QRect>
      26              : #include <QTimer>
      27              : 
      28              : #include "log.h"
      29              : 
      30              : #include "kddockwidgets/src/core/DockWidget.h"
      31              : #include "kddockwidgets/src/core/FloatingWindow.h"
      32              : #include "kddockwidgets/src/core/Group.h"
      33              : #include "kddockwidgets/src/qtquick/views/DockWidget.h"
      34              : #include "kddockwidgets/src/qtquick/views/Group.h"
      35              : #include "kddockwidgets/src/qtquick/views/View.h"
      36              : #include "kddockwidgets/src/qtquick/Action.h"
      37              : 
      38              : // This include pulls in kdbindings/signal.h which is incompatible with
      39              : // Qt's `emit` macro being defined. Temporarily undefine it, then restore it.
      40              : #ifdef emit
      41              : #undef emit
      42              : #include "kddockwidgets/src/core/layouting/Item_p.h"
      43              : #define emit
      44              : #else
      45              : #include "kddockwidgets/src/core/layouting/Item_p.h"
      46              : #endif
      47              : 
      48              : #include "ui/qml/Muse/Ui/navigationsection.h"
      49              : 
      50              : #include "muse_framework_config.h"
      51              : 
      52              : namespace muse::dock {
      53            0 : static QSize adjustSizeByConstraints(const QSize& size, const QSize& min, const QSize& max)
      54              : {
      55            0 :     return size.expandedTo(min).boundedTo(max);
      56              : }
      57              : 
      58            0 : static bool sizeInRange(const QSize& size, const QSize& min, const QSize& max)
      59              : {
      60            0 :     bool widthInRange = size.width() >= min.width() && size.width() <= max.width();
      61            0 :     bool heightInRange = size.height() >= min.height() && size.height() <= max.height();
      62              : 
      63            0 :     return widthInRange && heightInRange;
      64              : }
      65              : 
      66          276 : static KDDockWidgets::Core::Group* groupForDockWidget(KDDockWidgets::Core::DockWidget* dw)
      67              : {
      68          276 :     if (!dw) {
      69            0 :         return nullptr;
      70              :     }
      71          552 :     auto* view = qobject_cast<KDDockWidgets::QtQuick::DockWidget*>(
      72          276 :         KDDockWidgets::QtQuick::asQQuickItem(dw));
      73          276 :     return view ? view->group() : nullptr;
      74              : }
      75              : 
      76           12 : static KDDockWidgets::QtQuick::Group* groupViewFor(KDDockWidgets::Core::Group* group)
      77              : {
      78           12 :     if (!group) {
      79            0 :         return nullptr;
      80              :     }
      81           24 :     return qobject_cast<KDDockWidgets::QtQuick::Group*>(
      82           12 :         KDDockWidgets::QtQuick::asQQuickItem(group));
      83              : }
      84              : }
      85              : 
      86              : using namespace muse::dock;
      87              : 
      88           52 : DockBase::DockBase(DockType type, QQuickItem* parent)
      89           52 :     : QQuickItem(parent), Contextable(muse::iocCtxForQmlObject(this))
      90              : {
      91           52 :     Q_ASSERT(type != DockType::Undefined);
      92              : 
      93           52 :     m_properties.type = type;
      94           52 :     m_properties.floatable = true;
      95           52 :     m_properties.closable = true;
      96           52 :     m_properties.resizable = true;
      97           52 :     m_properties.separatorsVisible = true;
      98           52 : }
      99              : 
     100            0 : QString DockBase::title() const
     101              : {
     102            0 :     return m_title;
     103              : }
     104              : 
     105           68 : int DockBase::minimumWidth() const
     106              : {
     107           68 :     return m_minimumWidth;
     108              : }
     109              : 
     110            6 : int DockBase::minimumHeight() const
     111              : {
     112            6 :     return m_minimumHeight;
     113              : }
     114              : 
     115           68 : int DockBase::maximumWidth() const
     116              : {
     117           68 :     return m_maximumWidth;
     118              : }
     119              : 
     120            6 : int DockBase::maximumHeight() const
     121              : {
     122            6 :     return m_maximumHeight;
     123              : }
     124              : 
     125          133 : int DockBase::contentWidth() const
     126              : {
     127          133 :     return m_contentWidth;
     128              : }
     129              : 
     130            0 : int DockBase::contentHeight() const
     131              : {
     132            0 :     return m_contentHeight;
     133              : }
     134              : 
     135           12 : QSize DockBase::preferredSize() const
     136              : {
     137           12 :     return QSize(width(), height());
     138              : }
     139              : 
     140            0 : int DockBase::locationProperty() const
     141              : {
     142            0 :     return static_cast<int>(m_properties.location);
     143              : }
     144              : 
     145            3 : Location DockBase::location() const
     146              : {
     147            3 :     return m_properties.location;
     148              : }
     149              : 
     150            0 : QPoint DockBase::globalPosition() const
     151              : {
     152            0 :     if (!m_dockWidget) {
     153            0 :         return QPoint();
     154              :     }
     155              : 
     156            0 :     KDDockWidgets::Core::Group* group = groupForDockWidget(m_dockWidget);
     157            0 :     if (!group) {
     158            0 :         return QPoint();
     159              :     }
     160              : 
     161            0 :     QQuickItem* groupView = KDDockWidgets::QtQuick::asQQuickItem(group);
     162            0 :     if (!groupView) {
     163            0 :         return QPoint();
     164              :     }
     165              : 
     166            0 :     return groupView->mapToGlobal(QPointF(0, 0)).toPoint();
     167              : }
     168              : 
     169            0 : QVariantList DockBase::dropDestinationsProperty() const
     170              : {
     171            0 :     return m_dropDestinations;
     172              : }
     173              : 
     174            6 : QList<DropDestination> DockBase::dropDestinations() const
     175              : {
     176            6 :     QList<DropDestination> result;
     177              : 
     178            6 :     for (const QVariant& obj : m_dropDestinations) {
     179            0 :         QVariantMap map = obj.toMap();
     180              : 
     181            0 :         DropDestination destination;
     182            0 :         destination.dock = map["dock"].value<DockBase*>();
     183              : 
     184            0 :         if (map.contains("dropLocation")) {
     185            0 :             destination.dropLocation = static_cast<Location>(map["dropLocation"].toInt());
     186              :         } else {
     187            0 :             destination.dropLocation = Location::Left;
     188              :         }
     189              : 
     190            0 :         if (map.contains("dropDistance")) {
     191            0 :             destination.dropDistance = map["dropDistance"].toInt();
     192              :         }
     193              : 
     194            0 :         result << destination;
     195            0 :     }
     196              : 
     197            6 :     return result;
     198            0 : }
     199              : 
     200            0 : bool DockBase::closable() const
     201              : {
     202            0 :     return m_properties.closable;
     203              : }
     204              : 
     205            0 : bool DockBase::resizable() const
     206              : {
     207            0 :     return m_properties.resizable;
     208              : }
     209              : 
     210            0 : bool DockBase::separatorsVisible() const
     211              : {
     212            0 :     return m_properties.separatorsVisible;
     213              : }
     214              : 
     215           12 : bool DockBase::defaultVisibility() const
     216              : {
     217           12 :     return m_defaultVisibility;
     218              : }
     219              : 
     220           30 : bool DockBase::isCompact() const
     221              : {
     222           30 :     return m_isCompact;
     223              : }
     224              : 
     225           69 : int DockBase::compactPriorityOrder() const
     226              : {
     227           69 :     return m_compactPriorityOrder;
     228              : }
     229              : 
     230            7 : int DockBase::nonCompactWidth() const
     231              : {
     232            7 :     return m_nonCompactWidth;
     233              : }
     234              : 
     235           15 : bool DockBase::floatable() const
     236              : {
     237           15 :     return m_properties.floatable;
     238              : }
     239              : 
     240          101 : bool DockBase::floating() const
     241              : {
     242          101 :     return m_floating;
     243              : }
     244              : 
     245          127 : bool DockBase::inited() const
     246              : {
     247          127 :     return m_inited;
     248              : }
     249              : 
     250            0 : DockType DockBase::type() const
     251              : {
     252            0 :     return m_properties.type;
     253              : }
     254              : 
     255           54 : KDDockWidgets::Core::DockWidget* DockBase::dockWidget() const
     256              : {
     257           54 :     return m_dockWidget;
     258              : }
     259              : 
     260            0 : void DockBase::setTitle(const QString& title)
     261              : {
     262            0 :     if (title == m_title) {
     263            0 :         return;
     264              :     }
     265              : 
     266            0 :     m_title = title;
     267            0 :     emit titleChanged();
     268              : }
     269              : 
     270           49 : void DockBase::setMinimumWidth(int width)
     271              : {
     272           49 :     if (width == minimumWidth()) {
     273           13 :         return;
     274              :     }
     275              : 
     276           36 :     m_minimumWidth = width;
     277           36 :     emit minimumSizeChanged();
     278              : }
     279              : 
     280            6 : void DockBase::setMinimumHeight(int height)
     281              : {
     282            6 :     if (height == minimumHeight()) {
     283            0 :         return;
     284              :     }
     285              : 
     286            6 :     m_minimumHeight = height;
     287            6 :     emit minimumSizeChanged();
     288              : }
     289              : 
     290           49 : void DockBase::setMaximumWidth(int width)
     291              : {
     292           49 :     if (width == maximumWidth()) {
     293            1 :         return;
     294              :     }
     295              : 
     296           48 :     m_maximumWidth = width;
     297           48 :     emit maximumSizeChanged();
     298              : }
     299              : 
     300            6 : void DockBase::setMaximumHeight(int height)
     301              : {
     302            6 :     if (height == maximumHeight()) {
     303            0 :         return;
     304              :     }
     305              : 
     306            6 :     m_maximumHeight = height;
     307            6 :     emit maximumSizeChanged();
     308              : }
     309              : 
     310           53 : void DockBase::setContentWidth(int width)
     311              : {
     312           53 :     if (m_contentWidth == width) {
     313            0 :         return;
     314              :     }
     315              : 
     316           53 :     m_contentWidth = width;
     317           53 :     emit contentSizeChanged();
     318              : }
     319              : 
     320            6 : void DockBase::setContentHeight(int height)
     321              : {
     322            6 :     if (m_contentHeight == height) {
     323            0 :         return;
     324              :     }
     325              : 
     326            6 :     m_contentHeight = height;
     327            6 :     emit contentSizeChanged();
     328              : }
     329              : 
     330           49 : void DockBase::setLocation(int location)
     331              : {
     332           49 :     if (location == m_properties.location) {
     333            0 :         return;
     334              :     }
     335              : 
     336           49 :     m_properties.location = static_cast<Location>(location);
     337           49 :     emit locationChanged();
     338              : }
     339              : 
     340            0 : void DockBase::setDropDestinations(const QVariantList& destinations)
     341              : {
     342            0 :     if (m_dropDestinations == destinations) {
     343            0 :         return;
     344              :     }
     345              : 
     346            0 :     m_dropDestinations = destinations;
     347            0 :     emit dropDestinationsChanged();
     348              : }
     349              : 
     350            3 : void DockBase::setFloatable(bool floatable)
     351              : {
     352            3 :     if (floatable == m_properties.floatable) {
     353            0 :         return;
     354              :     }
     355              : 
     356            3 :     m_properties.floatable = floatable;
     357            3 :     emit floatableChanged();
     358              : }
     359              : 
     360            3 : void DockBase::setClosable(bool closable)
     361              : {
     362            3 :     if (closable == m_properties.closable) {
     363            0 :         return;
     364              :     }
     365              : 
     366            3 :     m_properties.closable = closable;
     367            3 :     emit closableChanged();
     368              : }
     369              : 
     370            0 : void DockBase::setResizable(bool resizable)
     371              : {
     372            0 :     if (resizable == m_properties.resizable) {
     373            0 :         return;
     374              :     }
     375              : 
     376            0 :     m_properties.resizable = resizable;
     377            0 :     emit resizableChanged();
     378              : }
     379              : 
     380            0 : void DockBase::setSeparatorsVisible(bool visible)
     381              : {
     382            0 :     if (visible == m_properties.separatorsVisible) {
     383            0 :         return;
     384              :     }
     385              : 
     386            0 :     m_properties.separatorsVisible = visible;
     387            0 :     emit separatorsVisibleChanged();
     388              : }
     389              : 
     390           11 : void DockBase::setIsCompact(bool compact)
     391              : {
     392           11 :     if (m_isCompact == compact) {
     393            0 :         return;
     394              :     }
     395              : 
     396           11 :     if (compact) {
     397            8 :         m_nonCompactWidth = width();
     398              :     }
     399              : 
     400           11 :     m_isCompact = compact;
     401           11 :     emit isCompactChanged();
     402              : }
     403              : 
     404           40 : void DockBase::setCompactPriorityOrder(int order)
     405              : {
     406           40 :     if (m_compactPriorityOrder == order) {
     407           24 :         return;
     408              :     }
     409              : 
     410           16 :     m_compactPriorityOrder = order;
     411           16 :     emit compactPriorityOrderChanged();
     412              : }
     413              : 
     414            0 : void DockBase::setFloating(bool floating)
     415              : {
     416            0 :     IF_ASSERT_FAILED(m_dockWidget) {
     417            0 :         return;
     418              :     }
     419              : 
     420            0 :     m_dockWidget->setFloating(floating);
     421              : }
     422              : 
     423            0 : void DockBase::setNavigationSection(ui::NavigationSection* section)
     424              : {
     425            0 :     if (m_navigationSection == section) {
     426            0 :         return;
     427              :     }
     428              : 
     429            0 :     m_navigationSection = section;
     430            0 :     emit navigationSectionChanged();
     431              : }
     432              : 
     433            0 : void DockBase::setContentNavigationPanelOrderStart(int order)
     434              : {
     435            0 :     if (m_contentNavigationPanelOrderStart == order) {
     436            0 :         return;
     437              :     }
     438              : 
     439            0 :     m_contentNavigationPanelOrderStart = order;
     440            0 :     emit contentNavigationPanelOrderStartChanged();
     441              : }
     442              : 
     443           12 : void DockBase::init()
     444              : {
     445           12 :     IF_ASSERT_FAILED(m_dockWidget) {
     446            0 :         return;
     447              :     }
     448              : 
     449           12 :     setVisible(m_dockWidget->isOpen());
     450           12 :     setInited(true);
     451              : 
     452           12 :     applySizeConstraints();
     453           12 :     updateFloatingStatus();
     454              : }
     455              : 
     456            0 : void DockBase::deinit()
     457              : {
     458            0 :     setInited(false);
     459            0 : }
     460              : 
     461           12 : bool DockBase::isOpen() const
     462              : {
     463           12 :     IF_ASSERT_FAILED(m_dockWidget) {
     464            0 :         return false;
     465              :     }
     466              : 
     467           12 :     return m_dockWidget->isOpen();
     468              : }
     469              : 
     470            0 : void DockBase::open()
     471              : {
     472            0 :     TRACEFUNC;
     473              : 
     474            0 :     IF_ASSERT_FAILED(m_dockWidget) {
     475            0 :         return;
     476              :     }
     477              : 
     478            0 :     setVisible(true);
     479            0 :     m_dockWidget->open();
     480              : 
     481            0 :     applySizeConstraints();
     482            0 : }
     483              : 
     484            0 : void DockBase::close()
     485              : {
     486            0 :     TRACEFUNC;
     487              : 
     488            0 :     IF_ASSERT_FAILED(m_dockWidget) {
     489            0 :         return;
     490              :     }
     491              : 
     492            0 :     m_dockWidget->close();
     493            0 :     setVisible(false);
     494            0 : }
     495              : 
     496            0 : void DockBase::showHighlighting(const QRect& highlightingRect)
     497              : {
     498            0 :     if (highlightingRect == m_properties.highlightingRect) {
     499            0 :         return;
     500              :     }
     501              : 
     502            0 :     m_properties.highlightingRect = highlightingRect;
     503            0 :     writeProperties();
     504              : }
     505              : 
     506            0 : void DockBase::hideHighlighting()
     507              : {
     508            0 :     showHighlighting(QRect());
     509            0 : }
     510              : 
     511            0 : QRect DockBase::frameGeometry() const
     512              : {
     513            0 :     if (m_dockWidget && m_dockWidget->isVisible()) {
     514            0 :         return m_dockWidget->groupGeometry();
     515              :     }
     516              : 
     517            0 :     return QRect();
     518              : }
     519              : 
     520            0 : bool DockBase::isInSameFrame(const DockBase* other) const
     521              : {
     522            0 :     IF_ASSERT_FAILED(other) {
     523            0 :         return false;
     524              :     }
     525              : 
     526            0 :     KDDockWidgets::Core::Group* group = groupForDockWidget(m_dockWidget);
     527            0 :     KDDockWidgets::Core::Group* otherGroup = groupForDockWidget(other->dockWidget());
     528              : 
     529            0 :     if (!group || !otherGroup) {
     530            0 :         return false;
     531              :     }
     532              : 
     533            0 :     return group == otherGroup;
     534              : }
     535              : 
     536            0 : void DockBase::setFramePanelOrder(int order)
     537              : {
     538            0 :     if (!m_dockWidget) {
     539            0 :         return;
     540              :     }
     541              : 
     542            0 :     KDDockWidgets::Core::Group* group = groupForDockWidget(m_dockWidget);
     543            0 :     if (!group) {
     544            0 :         return;
     545              :     }
     546              : 
     547            0 :     if (group->beingDeletedLater()) {
     548            0 :         return;
     549              :     }
     550              : 
     551            0 :     KDDockWidgets::QtQuick::Group* groupView = groupViewFor(group);
     552            0 :     if (!groupView) {
     553            0 :         return;
     554              :     }
     555              : 
     556            0 :     QQuickItem* frameVisualItem = groupView->visualItem();
     557            0 :     if (!frameVisualItem) {
     558            0 :         return;
     559              :     }
     560              : 
     561            0 :     frameVisualItem->setProperty("titleBarNavigationPanelOrder", order);
     562              : }
     563              : 
     564            0 : void DockBase::resetToDefault()
     565              : {
     566            0 :     setVisible(m_defaultVisibility);
     567            0 : }
     568              : 
     569            0 : void DockBase::resize(int width, int height)
     570              : {
     571            0 :     TRACEFUNC;
     572              : 
     573            0 :     if (!m_dockWidget) {
     574            0 :         return;
     575              :     }
     576              : 
     577            0 :     width = std::max(width, m_minimumWidth);
     578            0 :     height = std::max(height, m_minimumHeight);
     579              : 
     580            0 :     if (m_maximumWidth > 0) {
     581            0 :         width = std::min(width, std::max(m_maximumWidth, m_minimumWidth));
     582              :     }
     583              : 
     584            0 :     if (m_maximumHeight > 0) {
     585            0 :         height = std::min(height, std::max(m_maximumHeight, m_minimumHeight));
     586              :     }
     587              : 
     588              :     //! NOTE: Use the actual size in the layout, the item size may be overridden from QML
     589            0 :     const int deltaWidth = width - m_dockWidget->width();
     590            0 :     const int deltaHeight = height - m_dockWidget->height();
     591            0 :     if (deltaWidth == 0 && deltaHeight == 0) {
     592            0 :         return;
     593              :     }
     594              : 
     595            0 :     int left = 0;
     596            0 :     int top = 0;
     597            0 :     int right = 0;
     598            0 :     int bottom = 0;
     599              : 
     600            0 :     switch (location()) {
     601            0 :     case Location::Bottom: top = deltaHeight;
     602            0 :         break;
     603            0 :     case Location::Top: bottom = deltaHeight;
     604            0 :         break;
     605            0 :     case Location::Left: right = deltaWidth;
     606            0 :         break;
     607            0 :     case Location::Right: left = deltaWidth;
     608            0 :         break;
     609            0 :     case Location::Center:
     610            0 :     case Location::Undefined: break;
     611              :     }
     612              : 
     613            0 :     m_dockWidget->resizeInLayout(left, top, right, bottom);
     614            0 : }
     615              : 
     616            0 : muse::ui::INavigationSection* DockBase::navigationSection() const
     617              : {
     618            0 :     return m_navigationSection;
     619              : }
     620              : 
     621            0 : muse::ui::NavigationSection* DockBase::navigationSection_property() const
     622              : {
     623            0 :     return m_navigationSection;
     624              : }
     625              : 
     626            0 : int DockBase::contentNavigationPanelOrderStart() const
     627              : {
     628            0 :     return m_contentNavigationPanelOrderStart;
     629              : }
     630              : 
     631           12 : void DockBase::componentComplete()
     632              : {
     633           13 :     TRACEFUNC;
     634              : 
     635           12 :     QQuickItem::componentComplete();
     636              : 
     637           12 :     auto children = childItems();
     638           12 :     IF_ASSERT_FAILED_X(children.size() == 1, "Dock must have only one child as its content!") {
     639            0 :         return;
     640              :     }
     641              : 
     642           12 :     QQuickItem* content = children.first();
     643           12 :     IF_ASSERT_FAILED(content) {
     644            0 :         return;
     645              :     }
     646              : 
     647           12 :     const QString name = objectName();
     648              : 
     649           12 :     if (content->objectName().isEmpty()) {
     650           12 :         content->setObjectName(name + "_content");
     651              :     }
     652              : 
     653           12 :     auto* dockWidgetView = new KDDockWidgets::QtQuick::DockWidget(iocContext()->id, name);
     654           12 :     dockWidgetView->setObjectName(name);
     655           12 :     m_dockWidget = dockWidgetView->dockWidget();
     656           12 :     dockWidgetView->setGuestItem(content);
     657           12 :     m_dockWidget->setTitle(m_title);
     658              : 
     659           12 :     writeProperties();
     660           12 :     setUpFrameConnections();
     661              : 
     662           12 :     QQuickItem* dockWidgetItem = KDDockWidgets::QtQuick::asQQuickItem(m_dockWidget);
     663           12 :     connect(dockWidgetItem, &QQuickItem::widthChanged, this, [this]() {
     664           58 :         if (m_dockWidget) {
     665           58 :             setWidth(m_dockWidget->width());
     666           58 :             if (inited()) {
     667           16 :                 applySizeConstraints();
     668              :             }
     669              :         }
     670           58 :     });
     671              : 
     672           12 :     connect(dockWidgetItem, &QQuickItem::heightChanged, this, [this]() {
     673           69 :         if (m_dockWidget) {
     674           69 :             setHeight(m_dockWidget->height());
     675           69 :             if (inited()) {
     676           24 :                 applySizeConstraints();
     677              :             }
     678              :         }
     679           69 :     });
     680              : 
     681           12 :     connect(this, &DockBase::minimumSizeChanged, this, &DockBase::applySizeConstraints);
     682           12 :     connect(this, &DockBase::maximumSizeChanged, this, &DockBase::applySizeConstraints);
     683              : 
     684           12 :     m_defaultVisibility = isVisible();
     685           12 : }
     686              : 
     687           91 : void DockBase::applySizeConstraints()
     688              : {
     689           91 :     if (!m_dockWidget) {
     690            0 :         return;
     691              :     }
     692              : 
     693           92 :     TRACEFUNC;
     694              : 
     695           91 :     KDDockWidgets::Core::View* dockWidgetView = m_dockWidget->view();
     696              : 
     697           91 :     int minWidth = m_minimumWidth > 0 ? m_minimumWidth : dockWidgetView->minSize().width();
     698           91 :     int minHeight = m_minimumHeight > 0 ? m_minimumHeight : dockWidgetView->minSize().height();
     699           91 :     int maxWidth = m_maximumWidth > 0 ? m_maximumWidth : dockWidgetView->maxSizeHint().width();
     700           91 :     int maxHeight = m_maximumHeight > 0 ? m_maximumHeight : dockWidgetView->maxSizeHint().height();
     701              : 
     702           91 :     minWidth = std::min(minWidth, maxWidth);
     703           91 :     minHeight = std::min(minHeight, maxHeight);
     704           91 :     maxWidth = std::max(maxWidth, minWidth);
     705           91 :     maxHeight = std::max(maxHeight, minHeight);
     706              : 
     707           91 :     QSize minimumSize(minWidth, minHeight);
     708           91 :     QSize maximumSize(maxWidth, maxHeight);
     709              : 
     710           91 :     if (!m_properties.resizable) {
     711            0 :         maximumSize = minimumSize;
     712              :     }
     713              : 
     714           91 :     KDDockWidgets::Core::Group* group = groupForDockWidget(m_dockWidget);
     715              : 
     716              :     //! NOTE: Skip applying floating size constraints while the dock's group is still in the main
     717              :     //!       layout - fixes the top row growing taller on undock.
     718           91 :     if (m_floating && group && group->isInMainWindow()) {
     719            0 :         return;
     720              :     }
     721              : 
     722           91 :     if (group) {
     723           85 :         group->view()->setMinimumSize(minimumSize);
     724           85 :         group->view()->setMaximumSize(maximumSize);
     725              :     }
     726              : 
     727           91 :     dockWidgetView->setMinimumSize(minimumSize);
     728           91 :     dockWidgetView->setMaximumSize(maximumSize);
     729              : 
     730           91 :     if (KDDockWidgets::Core::FloatingWindow* window = m_dockWidget->floatingWindow()) {
     731              :         //! NOTE: The floating window draws shadow around the dock content (see DockFloatingWindow.qml),
     732              :         //! so the window must be larger than the content by that shadow on each side.
     733            0 :         const int shadow = 2 * (DOCK_WINDOW_SHADOW + 1 /*border*/);
     734            0 :         const QSize windowMinimumSize = minimumSize + QSize(shadow, shadow);
     735            0 :         const QSize windowMaximumSize = maximumSize + QSize(shadow, shadow);
     736              : 
     737            0 :         window->view()->setMinimumSize(windowMinimumSize);
     738            0 :         window->view()->setMaximumSize(windowMaximumSize);
     739              : 
     740            0 :         const QSize winSize = adjustSizeByConstraints(window->view()->geometry().size(), windowMinimumSize, windowMaximumSize);
     741            0 :         const QRect winRect(window->dragRect().topLeft(), winSize);
     742            0 :         window->view()->setGeometry(winRect);
     743              :     }
     744              : 
     745              :     //! NOTE: The group derives its minimum size from its dock widgets, so the layout
     746              :     //! picks up the old minimum when the group constraints are applied
     747           91 :     syncLayoutItemMinSize();
     748              : 
     749              :     //! NOTE: The layout doesn't shrink the item when the maximum size decreases
     750           91 :     fitSizeIntoMaximum();
     751           91 : }
     752              : 
     753           91 : void DockBase::fitSizeIntoMaximum()
     754              : {
     755           91 :     if (!m_dockWidget || !m_inited) {
     756           18 :         return;
     757              :     }
     758              : 
     759           73 :     KDDockWidgets::Core::Group* group = groupForDockWidget(m_dockWidget);
     760           73 :     if (!group || !group->isInMainWindow()) {
     761            0 :         return;
     762              :     }
     763              : 
     764              :     //! NOTE: The layout treats the maximum size only as a hint and doesn't shrink the item
     765              :     //! when it decreases, so shrink it explicitly. The side at the edge of the layout
     766              :     //! isn't changed, so shrink the opposite side if the excess remains
     767          152 :     auto excessWidth = [this]() {
     768          152 :         return m_maximumWidth > 0 ? m_dockWidget->width() - std::max(m_maximumWidth, m_minimumWidth) : 0;
     769           73 :     };
     770              : 
     771          236 :     auto excessHeight = [this]() {
     772          236 :         return m_maximumHeight > 0 ? m_dockWidget->height() - std::max(m_maximumHeight, m_minimumHeight) : 0;
     773           73 :     };
     774              : 
     775              :     //! NOTE: Left side
     776           73 :     if (excessWidth() > 0) {
     777            5 :         m_dockWidget->resizeInLayout(-excessWidth(), 0, 0, 0);
     778              :     }
     779              : 
     780              :     //! NOTE: Right side
     781           73 :     if (excessWidth() > 0) {
     782            1 :         m_dockWidget->resizeInLayout(0, 0, -excessWidth(), 0);
     783              :     }
     784              : 
     785              :     //! NOTE: Top side
     786           73 :     if (excessHeight() > 0) {
     787           45 :         m_dockWidget->resizeInLayout(0, -excessHeight(), 0, 0);
     788              :     }
     789              : 
     790              :     //! NOTE: Bottom side
     791           73 :     if (excessHeight() > 0) {
     792           45 :         m_dockWidget->resizeInLayout(0, 0, 0, -excessHeight());
     793              :     }
     794              : }
     795              : 
     796          100 : void DockBase::syncLayoutItemMinSize()
     797              : {
     798          100 :     if (!m_dockWidget) {
     799           18 :         return;
     800              :     }
     801              : 
     802          100 :     KDDockWidgets::Core::Group* group = groupForDockWidget(m_dockWidget);
     803          100 :     if (!group) {
     804            6 :         return;
     805              :     }
     806              : 
     807           94 :     KDDockWidgets::Core::Item* item = group->layoutItem();
     808           94 :     if (!item) {
     809           12 :         return;
     810              :     }
     811              : 
     812              :     //! NOTE: The layouting item caches the guest minimum; force it to match the group's current
     813              :     //! minimum so the container's minimum size reflects
     814           82 :     const QSize min = group->view()->minSize();
     815           82 :     if (item->minSize() != min) {
     816            9 :         item->setMinSize(min);
     817              :     }
     818              : }
     819              : 
     820           12 : void DockBase::setUpFrameConnections()
     821              : {
     822           12 :     IF_ASSERT_FAILED(m_dockWidget) {
     823            0 :         return;
     824              :     }
     825              : 
     826           12 :     QQuickItem* dockWidgetItem = KDDockWidgets::QtQuick::asQQuickItem(m_dockWidget);
     827           12 :     IF_ASSERT_FAILED(dockWidgetItem) {
     828            0 :         return;
     829              :     }
     830              : 
     831           12 :     auto floatingChangedConnection = std::make_shared<QMetaObject::Connection>();
     832           12 :     auto widgetChangedConnection = std::make_shared<QMetaObject::Connection>();
     833              : 
     834           12 :     connect(dockWidgetItem, &QQuickItem::parentChanged, this,
     835           24 :             [this, floatingChangedConnection, widgetChangedConnection]()
     836              :     {
     837           12 :         if (floatingChangedConnection) {
     838           12 :             disconnect(*floatingChangedConnection);
     839           12 :             doSetFloating(false);
     840              :         }
     841              : 
     842           12 :         if (widgetChangedConnection) {
     843           12 :             disconnect(*widgetChangedConnection);
     844              :         }
     845              : 
     846           12 :         QQuickItem* dockWidgetItem = KDDockWidgets::QtQuick::asQQuickItem(m_dockWidget);
     847           12 :         if (!m_dockWidget || !dockWidgetItem || !dockWidgetItem->parentItem()) {
     848            0 :             return;
     849              :         }
     850              : 
     851           12 :         KDDockWidgets::Core::Group* group = groupForDockWidget(m_dockWidget);
     852           12 :         if (!group) {
     853            0 :             return;
     854              :         }
     855              : 
     856              :         //! NOTE: window will be available later
     857              :         //! So it is important to apply size constraints
     858              :         //! and emit floatingChanged() after that
     859           12 :         QTimer::singleShot(0, this, [this]() {
     860           12 :             updateFloatingStatus();
     861              : 
     862           12 :             if (m_floating) {
     863            0 :                 applySizeConstraints();
     864              :             }
     865           12 :         });
     866              : 
     867           12 :         KDDockWidgets::QtQuick::Group* groupView = groupViewFor(group);
     868           12 :         if (groupView) {
     869           24 :             *floatingChangedConnection = connect(groupView, &QQuickItem::parentChanged,
     870           12 :                                                  this, &DockBase::onIsInMainWindowChanged,
     871           12 :                                                  Qt::UniqueConnection);
     872           24 :             *widgetChangedConnection = connect(groupView, &KDDockWidgets::QtQuick::Group::currentDockWidgetChanged,
     873           24 :                                                this, &DockBase::frameCurrentWidgetChanged,
     874           12 :                                                Qt::UniqueConnection);
     875              :         }
     876              :     });
     877              : 
     878           12 :     auto* action = static_cast<KDDockWidgets::QtQuick::Action*>(m_dockWidget->toggleAction());
     879           12 :     connect(action, &KDDockWidgets::QtQuick::Action::toggled, this, [this]() {
     880           12 :         if (!isOpen()) {
     881            0 :             doSetFloating(false);
     882              :         }
     883           12 :     });
     884           12 : }
     885              : 
     886           36 : void DockBase::updateFloatingStatus()
     887              : {
     888           36 :     bool floating = m_dockWidget && m_dockWidget->floatingWindow();
     889              : 
     890           36 :     doSetFloating(floating);
     891           36 : }
     892              : 
     893           12 : void DockBase::onIsInMainWindowChanged()
     894              : {
     895           12 :     updateFloatingStatus();
     896           12 :     applySizeConstraints();
     897           12 : }
     898              : 
     899           51 : void DockBase::doSetFloating(bool floating)
     900              : {
     901           51 :     if (m_floating == floating) {
     902           48 :         return;
     903              :     }
     904              : 
     905            3 :     m_floating = floating;
     906            3 :     emit floatingChanged();
     907              : }
     908              : 
     909           12 : void DockBase::writeProperties()
     910              : {
     911           12 :     if (m_dockWidget) {
     912           12 :         writePropertiesToObject(m_properties, *m_dockWidget);
     913              :     }
     914           12 : }
     915              : 
     916           12 : void DockBase::setInited(bool inited)
     917              : {
     918           12 :     if (m_inited == inited) {
     919            0 :         return;
     920              :     }
     921              : 
     922           12 :     m_inited = inited;
     923           12 :     emit initedChanged();
     924              : }
     925              : 
     926            0 : bool DropDestination::operator==(const DropDestination& dest) const
     927              : {
     928            0 :     return dock == dest.dock && dropLocation == dest.dropLocation && dropDistance == dest.dropDistance;
     929              : }
     930              : 
     931            0 : bool DropDestination::isValid() const
     932              : {
     933            0 :     return dock != nullptr;
     934              : }
     935              : 
     936            0 : void DropDestination::clear()
     937              : {
     938            0 :     dock = nullptr;
     939            0 :     dropLocation = Location::Undefined;
     940            0 :     dropDistance = 0;
     941            0 : }
        

Generated by: LCOV version 2.0-1