6#include "QtWidgets/qapplication.h"
7#include "QtWidgets/qwidget.h"
9#include "QtWidgets/qtabbar.h"
11#include "QtWidgets/qstyle.h"
12#include "QtWidgets/qapplication.h"
13#include "QtCore/qvariant.h"
20#include <private/qlayoutengine_p.h>
24#include "qtoolbarlayout_p.h"
28#include <qstyleoption.h>
47using StateMarkers = QMainWindowLayoutState::StateMarkers;
50
51
53QPlaceHolderItem::QPlaceHolderItem(QWidget *w)
55 objectName = w->objectName();
56 hidden = w->isHidden();
57 window = w->isWindow();
59 topLevelRect = w->geometry();
63
64
66QDockAreaLayoutItem::QDockAreaLayoutItem(QLayoutItem *_widgetItem)
67 : widgetItem(_widgetItem), subinfo(
nullptr), placeHolderItem(
nullptr), pos(0), size(-1), flags(NoFlags)
71QDockAreaLayoutItem::QDockAreaLayoutItem(QDockAreaLayoutInfo *_subinfo)
72 : widgetItem(
nullptr), subinfo(_subinfo), placeHolderItem(
nullptr), pos(0), size(-1), flags(NoFlags)
76QDockAreaLayoutItem::QDockAreaLayoutItem(QPlaceHolderItem *_placeHolderItem)
77 : widgetItem(
nullptr), subinfo(
nullptr), placeHolderItem(_placeHolderItem), pos(0), size(-1), flags(NoFlags)
81QDockAreaLayoutItem::QDockAreaLayoutItem(
const QDockAreaLayoutItem &other)
82 : widgetItem(other.widgetItem), subinfo(
nullptr), placeHolderItem(
nullptr), pos(other.pos),
83 size(other.size), flags(other.flags)
85 if (other.subinfo !=
nullptr)
86 subinfo =
new QDockAreaLayoutInfo(*other.subinfo);
87 else if (other.placeHolderItem !=
nullptr)
88 placeHolderItem =
new QPlaceHolderItem(*other.placeHolderItem);
91QDockAreaLayoutItem::~QDockAreaLayoutItem()
94 delete placeHolderItem;
97bool QDockAreaLayoutItem::skip()
const
99 if (placeHolderItem !=
nullptr)
105 if (widgetItem !=
nullptr)
106 return widgetItem->isEmpty();
108 if (subinfo !=
nullptr) {
109 for (
int i = 0; i < subinfo->item_list.size(); ++i) {
110 if (!subinfo->item_list.at(i).skip())
118QSize QDockAreaLayoutItem::minimumSize()
const
121 return widgetItem->minimumSize().grownBy(widgetItem->widget()->contentsMargins());
122 if (subinfo !=
nullptr)
123 return subinfo->minimumSize();
127QSize QDockAreaLayoutItem::maximumSize()
const
130 return widgetItem->maximumSize().grownBy(widgetItem->widget()->contentsMargins());
131 if (subinfo !=
nullptr)
132 return subinfo->maximumSize();
133 return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
136bool QDockAreaLayoutItem::hasFixedSize(Qt::Orientation o)
const
138 return perp(o, minimumSize()) == perp(o, maximumSize());
141bool QDockAreaLayoutItem::expansive(Qt::Orientation o)
const
143 if ((flags & GapItem) || placeHolderItem !=
nullptr)
145 if (widgetItem !=
nullptr)
146 return ((widgetItem->expandingDirections() & o) == o);
147 if (subinfo !=
nullptr)
148 return subinfo->expansive(o);
152QSize QDockAreaLayoutItem::sizeHint()
const
154 if (placeHolderItem !=
nullptr)
157 return widgetItem->sizeHint().grownBy(widgetItem->widget()->contentsMargins());
158 if (subinfo !=
nullptr)
159 return subinfo->sizeHint();
160 return QSize(-1, -1);
164 &QDockAreaLayoutItem::operator = (
const QDockAreaLayoutItem &other)
169 widgetItem = other.widgetItem;
171 if (other.subinfo ==
nullptr)
174 subinfo =
new QDockAreaLayoutInfo(*other.subinfo);
176 delete placeHolderItem;
177 if (other.placeHolderItem ==
nullptr)
178 placeHolderItem =
nullptr;
180 placeHolderItem =
new QPlaceHolderItem(*other.placeHolderItem);
189#ifndef QT_NO_DEBUG_STREAM
190QDebug operator<<(QDebug dbg,
const QDockAreaLayoutItem *item)
192 QDebugStateSaver saver(dbg);
194 return item ? dbg << *item : dbg <<
"QDockAreaLayoutItem(0x0)";
197QDebug operator<<(QDebug dbg,
const QDockAreaLayoutItem &item)
199 QDebugStateSaver saver(dbg);
201 dbg <<
"QDockAreaLayoutItem(" <<
static_cast<
const void *>(&item) <<
"->";
202 if (item.widgetItem) {
203 QWidget *widget = item.widgetItem->widget();
204 if (
auto *dockWidget = qobject_cast<QDockWidget *>(widget)) {
205 dbg <<
"widgetItem(" << dockWidget <<
")";
206 }
else if (
auto *groupWindow = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
207 dbg <<
"widgetItem(" << groupWindow <<
"->(" << groupWindow->dockWidgets() <<
"))";
209 dbg <<
"widgetItem(" << widget <<
")";
211 }
else if (item.subinfo) {
212 dbg <<
"subInfo(" << item.subinfo <<
"->(" << item.subinfo->item_list <<
")";
213 }
else if (item.placeHolderItem) {
214 dbg <<
"placeHolderItem(" << item.placeHolderItem
215 <<
"objectName:" << item.placeHolderItem->objectName <<
"; "
216 <<
"hidden:" << item.placeHolderItem->hidden <<
"; "
217 <<
"window:" << item.placeHolderItem->window <<
"; "
218 <<
"topLevelRect:" << item.placeHolderItem->topLevelRect <<
")";
224QDebug operator<<(QDebug dbg, StateFlags flags)
226 QDebugStateSaver saver(dbg);
227 dbg.nospace().noquote();
230 f << QLatin1StringView(
"Visible");
232 f << QLatin1StringView(
"Floating");
234 f << QLatin1StringView(
"FloatingTabs");
236 f << QLatin1StringView(
"Closed");
237 dbg <<
"StateFlags(" << f.join(u'|') <<
")";
243
244
247static quintptr tabId(
const QDockAreaLayoutItem &item)
249 if (item.widgetItem ==
nullptr)
251 return reinterpret_cast<quintptr>(item.widgetItem->widget());
257QDockAreaLayoutInfo::QDockAreaLayoutInfo()
258 : sep(&zero), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(
nullptr)
260 , tabbed(
false), tabBar(
nullptr), tabBarShape(QTabBar::RoundedSouth)
265QDockAreaLayoutInfo::QDockAreaLayoutInfo(
const int *_sep, QInternal::DockPosition _dockPos,
266 Qt::Orientation _o,
int tbshape,
268 : sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window)
270 , tabbed(
false), tabBar(
nullptr), tabBarShape(
static_cast<QTabBar::Shape>(tbshape))
273#if !QT_CONFIG(tabbar)
278QSize QDockAreaLayoutInfo::size()
const
280 return isEmpty() ? QSize(0, 0) : rect.size();
283void QDockAreaLayoutInfo::clear()
293bool QDockAreaLayoutInfo::isEmpty()
const
295 return next(-1) == -1;
298bool QDockAreaLayoutInfo::onlyHasPlaceholders()
const
300 for (
const QDockAreaLayoutItem &item : item_list) {
301 if (!item.placeHolderItem)
308QSize QDockAreaLayoutInfo::minimumSize()
const
315 for (
int i = 0; i < item_list.size(); ++i) {
316 const QDockAreaLayoutItem &item = item_list.at(i);
320 QSize min_size = item.minimumSize();
323 a = qMax(a, pick(o, min_size));
329 a += pick(o, min_size);
331 b = qMax(b, perp(o, min_size));
337 rpick(o, result) = a;
338 rperp(o, result) = b;
341 QSize tbm = tabBarMinimumSize();
343 switch (tabBarShape) {
344 case QTabBar::RoundedNorth:
345 case QTabBar::RoundedSouth:
346 case QTabBar::TriangularNorth:
347 case QTabBar::TriangularSouth:
348 result.rheight() += tbm.height();
349 result.rwidth() = qMax(tbm.width(), result.width());
351 case QTabBar::RoundedEast:
352 case QTabBar::RoundedWest:
353 case QTabBar::TriangularEast:
354 case QTabBar::TriangularWest:
355 result.rheight() = qMax(tbm.height(), result.height());
356 result.rwidth() += tbm.width();
367QSize QDockAreaLayoutInfo::maximumSize()
const
370 return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
372 int a = 0, b = QWIDGETSIZE_MAX;
381 for (
int i = 0; i < item_list.size(); ++i) {
382 const QDockAreaLayoutItem &item = item_list.at(i);
386 QSize max_size = item.maximumSize();
387 min_perp = qMax(min_perp, perp(o, item.minimumSize()));
391 a = qMin(a, pick(o, max_size));
397 a += pick(o, max_size);
399 b = qMin(b, perp(o, max_size));
401 a = qMin(a,
int(QWIDGETSIZE_MAX));
402 b = qMin(b,
int(QWIDGETSIZE_MAX));
407 b = qMax(b, min_perp);
410 rpick(o, result) = a;
411 rperp(o, result) = b;
414 QSize tbh = tabBarSizeHint();
416 switch (tabBarShape) {
417 case QTabBar::RoundedNorth:
418 case QTabBar::RoundedSouth:
419 result.rheight() += tbh.height();
421 case QTabBar::RoundedEast:
422 case QTabBar::RoundedWest:
423 result.rwidth() += tbh.width();
434QSize QDockAreaLayoutInfo::sizeHint()
const
441 int max_perp = QWIDGETSIZE_MAX;
442 const QDockAreaLayoutItem *previous =
nullptr;
443 for (
int i = 0; i < item_list.size(); ++i) {
444 const QDockAreaLayoutItem &item = item_list.at(i);
448 bool gap = item.flags & QDockAreaLayoutItem::GapItem;
450 QSize size_hint = item.sizeHint();
451 min_perp = qMax(min_perp, perp(o, item.minimumSize()));
452 max_perp = qMin(max_perp, perp(o, item.maximumSize()));
456 a = qMax(a, gap ? item.size : pick(o, size_hint));
460 if (previous && !gap && !(previous->flags & QDockAreaLayoutItem::GapItem)
461 && !previous->hasFixedSize(o)) {
464 a += gap ? item.size : pick(o, size_hint);
466 b = qMax(b, perp(o, size_hint));
471 max_perp = qMax(max_perp, min_perp);
472 b = qMax(b, min_perp);
473 b = qMin(b, max_perp);
476 rpick(o, result) = a;
477 rperp(o, result) = b;
481 QSize tbh = tabBarSizeHint();
482 switch (tabBarShape) {
483 case QTabBar::RoundedNorth:
484 case QTabBar::RoundedSouth:
485 case QTabBar::TriangularNorth:
486 case QTabBar::TriangularSouth:
487 result.rheight() += tbh.height();
488 result.rwidth() = qMax(tbh.width(), result.width());
490 case QTabBar::RoundedEast:
491 case QTabBar::RoundedWest:
492 case QTabBar::TriangularEast:
493 case QTabBar::TriangularWest:
494 result.rheight() = qMax(tbh.height(), result.height());
495 result.rwidth() += tbh.width();
506bool QDockAreaLayoutInfo::expansive(Qt::Orientation o)
const
508 for (
int i = 0; i < item_list.size(); ++i) {
509 if (item_list.at(i).expansive(o))
516
517
518
519
520
526 for (
int i = 0; i < info.item_list.size(); ++i) {
527 const QDockAreaLayoutItem &item = info.item_list.at(i);
532 if ((item.flags & QDockAreaLayoutItem::KeepSize) && item.size != -1)
535 min = pick(info.o, item.minimumSize());
551 for (
int i = 0; i < info.item_list.size(); ++i) {
552 const QDockAreaLayoutItem &item = info.item_list.at(i);
557 if ((item.flags & QDockAreaLayoutItem::KeepSize) && item.size != -1)
560 max = pick(info.o, item.maximumSize());
566 if (result >= QWIDGETSIZE_MAX)
567 return QWIDGETSIZE_MAX;
575void QDockAreaLayoutInfo::fitItems()
583 QList<QLayoutStruct> layout_struct_list(item_list.size() * 2);
586 int size = pick(o, rect.size());
587 int min_size = realMinSize(*
this);
588 int max_size = realMaxSize(*
this);
591 const QDockAreaLayoutItem *previous =
nullptr;
592 for (
int i = 0; i < item_list.size(); ++i) {
593 QDockAreaLayoutItem &item = item_list[i];
597 bool gap = item.flags & QDockAreaLayoutItem::GapItem;
598 if (previous && !gap) {
599 if (!(previous->flags & QDockAreaLayoutItem::GapItem)) {
600 QLayoutStruct &ls = layout_struct_list[j++];
602 ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : *sep;
607 if (item.flags & QDockAreaLayoutItem::KeepSize) {
611 if (size < min_size) {
613 item.flags &= ~QDockAreaLayoutItem::KeepSize;
614 min_size -= item.size;
615 min_size += pick(o, item.minimumSize());
616 min_size = qMax(0, min_size);
617 }
else if (size > max_size) {
619 item.flags &= ~QDockAreaLayoutItem::KeepSize;
620 max_size -= item.size;
621 max_size += pick(o, item.maximumSize());
622 max_size = qMin<
int>(QWIDGETSIZE_MAX, max_size);
627 QLayoutStruct &ls = layout_struct_list[j++];
630 if (item.flags & QDockAreaLayoutItem::KeepSize) {
631 ls.minimumSize = ls.maximumSize = ls.sizeHint = item.size;
632 ls.expansive =
false;
635 ls.maximumSize = pick(o, item.maximumSize());
636 ls.expansive = item.expansive(o);
637 ls.minimumSize = pick(o, item.minimumSize());
638 ls.sizeHint = item.size == -1 ? pick(o, item.sizeHint()) : item.size;
639 ls.stretch = ls.expansive ? ls.sizeHint : 0;
642 item.flags &= ~QDockAreaLayoutItem::KeepSize;
645 layout_struct_list.resize(j);
649 if (size > max_size && last_index != -1) {
650 layout_struct_list[last_index].maximumSize = QWIDGETSIZE_MAX;
651 layout_struct_list[last_index].expansive =
true;
654 qGeomCalc(layout_struct_list, 0, j, pick(o, rect.topLeft()), size, 0);
657 bool prev_gap =
false;
659 for (
int i = 0; i < item_list.size(); ++i) {
660 QDockAreaLayoutItem &item = item_list[i];
664 bool gap = item.flags & QDockAreaLayoutItem::GapItem;
665 if (!first && !gap && !prev_gap)
668 const QLayoutStruct &ls = layout_struct_list.at(j++);
672 if (item.subinfo !=
nullptr) {
673 item.subinfo->rect = itemRect(i);
674 item.subinfo->fitItems();
684 Qt::Orientation o,
bool nestingEnabled,
685 QDockAreaLayoutInfo::TabMode tabMode)
687 if (tabMode == QDockAreaLayoutInfo::ForceTabs)
690 QPoint pos = _pos - rect.topLeft();
694 int w = rect.width();
695 int h = rect.height();
697 if (tabMode != QDockAreaLayoutInfo::NoTabs) {
699 if (nestingEnabled) {
701
702
703
704
705
706
707
709 QRect center(w/6, h/6, 2*w/3, 2*h/3);
710 if (center.contains(pos))
712 }
else if (o == Qt::Horizontal) {
714
715
716
717
718
719
720
722 if (x > w/6 && x < w*5/6)
726
727
728
729
730
731
732 if (y > h/6 && y < 5*h/6)
738 if (nestingEnabled) {
739 if (o == Qt::Horizontal) {
741
742
743
744
745
746
749 return QInternal::LeftDock;
751 return QInternal::RightDock;
753 return QInternal::TopDock;
754 return QInternal::BottomDock;
757
758
759
760
761
764 return QInternal::TopDock;
766 return QInternal::BottomDock;
768 return QInternal::LeftDock;
769 return QInternal::RightDock;
772 if (o == Qt::Horizontal) {
774 ? QInternal::LeftDock
775 : QInternal::RightDock;
779 : QInternal::BottomDock;
784QList<
int> QDockAreaLayoutInfo::gapIndex(
const QPoint& _pos,
785 bool nestingEnabled, TabMode tabMode)
const
793 item_rect = tabContentRect();
797 int pos = pick(o, _pos);
800 for (
int i = 0; i < item_list.size(); ++i) {
801 const QDockAreaLayoutItem &item = item_list.at(i);
807 if (item.pos + item.size < pos)
810 if (item.subinfo !=
nullptr
812 && !item.subinfo->tabbed
815 result = item.subinfo->gapIndex(_pos, nestingEnabled,
821 item_rect = itemRect(i);
826 if (item_rect.isNull()) {
827 result.append(last + 1);
832 Q_ASSERT(!item_rect.isNull());
835 = dockPosHelper(item_rect, _pos, o, nestingEnabled, tabMode);
839 case QInternal::LeftDock:
840 if (o == Qt::Horizontal)
841 result << item_index;
843 result << item_index << 0;
846 case QInternal::RightDock:
847 if (o == Qt::Horizontal)
848 result << item_index + 1;
850 result << item_index << 1;
852 case QInternal::TopDock:
853 if (o == Qt::Horizontal)
854 result << item_index << 0;
856 result << item_index;
858 case QInternal::BottomDock:
859 if (o == Qt::Horizontal)
860 result << item_index << 1;
862 result << item_index + 1;
864 case QInternal::DockCount:
869 result << (-item_index - 1) << 0;
881 int old_size = ls.size;
882 ls.size = qMax(ls.size - delta, ls.minimumSize);
883 return old_size - ls.size;
890 int old_size = ls.size;
891 ls.size = qMin(ls.size + delta, ls.maximumSize);
892 return ls.size - old_size;
899 for (
int i = 0; i < list.size(); ++i) {
911 for (
int i = 0; i<=index; ++i) {
915 if (ls.maximumSize == QLAYOUTSIZE_MAX) {
916 growlimit = QLAYOUTSIZE_MAX;
919 growlimit += ls.maximumSize - ls.size;
921 if (delta > growlimit)
925 for (
int i = index + 1; d < delta && i < list.size(); ++i)
926 d += shrink(list[i], delta - d);
929 for (
int i = index; d < delta && i >= 0; --i)
930 d += grow(list[i], delta - d);
931 }
else if (delta < 0) {
933 for (
int i = index + 1; i < list.size(); ++i) {
937 if (ls.maximumSize == QLAYOUTSIZE_MAX) {
938 growlimit = QLAYOUTSIZE_MAX;
941 growlimit += ls.maximumSize - ls.size;
943 if (-delta > growlimit)
947 for (
int i = index; d < -delta && i >= 0; --i)
948 d += shrink(list[i], -delta - d);
951 for (
int i = index + 1; d < -delta && i < list.size(); ++i)
952 d += grow(list[i], -delta - d);
957 for (
int i = 0; i < list.size(); ++i) {
960 ls.pos = pos + (first ? 0 : sep);
973int QDockAreaLayoutInfo::separatorMove(
int index,
int delta)
979 QList<QLayoutStruct> list(item_list.size());
980 for (
int i = 0; i < list.size(); ++i) {
981 const QDockAreaLayoutItem &item = item_list.at(i);
982 QLayoutStruct &ls = list[i];
983 Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
987 const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
990 ls.size = item.size + separatorSpace;
991 ls.minimumSize = pick(o, item.minimumSize()) + separatorSpace;
992 ls.maximumSize = pick(o, item.maximumSize()) + separatorSpace;
998 delta = separatorMoveHelper(list, index, delta, 0 );
1000 for (
int i = 0; i < list.size(); ++i) {
1001 QDockAreaLayoutItem &item = item_list[i];
1004 QLayoutStruct &ls = list[i];
1005 const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
1006 item.size = ls.size - separatorSpace;
1008 if (item.subinfo !=
nullptr) {
1009 item.subinfo->rect = itemRect(i);
1010 item.subinfo->fitItems();
1017void QDockAreaLayoutInfo::unnest(
int index)
1019 QDockAreaLayoutItem &item = item_list[index];
1020 if (item.subinfo ==
nullptr)
1022 if (item.subinfo->item_list.size() > 1)
1025 if (item.subinfo->item_list.size() == 0) {
1026 item_list.removeAt(index);
1027 }
else if (item.subinfo->item_list.size() == 1) {
1028 QDockAreaLayoutItem &child = item.subinfo->item_list.first();
1029 if (child.widgetItem !=
nullptr) {
1030 item.widgetItem = child.widgetItem;
1031 delete item.subinfo;
1032 item.subinfo =
nullptr;
1033 }
else if (child.subinfo !=
nullptr) {
1034 QDockAreaLayoutInfo *tmp = item.subinfo;
1035 item.subinfo = child.subinfo;
1036 child.subinfo =
nullptr;
1037 tmp->item_list.clear();
1043void QDockAreaLayoutInfo::remove(
const QList<
int> &path)
1045 Q_ASSERT(!path.isEmpty());
1047 if (path.size() > 1) {
1048 const int index = path.first();
1049 QDockAreaLayoutItem &item = item_list[index];
1050 Q_ASSERT(item.subinfo !=
nullptr);
1051 item.subinfo->remove(path.mid(1));
1054 int index = path.first();
1055 item_list.removeAt(index);
1059void QDockAreaLayoutInfo::remove(QWidget *widget)
1061 const QList<
int> path = indexOf(widget);
1067QLayoutItem *QDockAreaLayoutInfo::plug(
const QList<
int> &path)
1069 Q_ASSERT(!path.isEmpty());
1071 int index = path.first();
1075 if (path.size() > 1) {
1076 QDockAreaLayoutItem &item = item_list[index];
1077 Q_ASSERT(item.subinfo !=
nullptr);
1078 return item.subinfo->plug(path.mid(1));
1081 QDockAreaLayoutItem &item = item_list[index];
1083 Q_ASSERT(item.widgetItem !=
nullptr);
1084 Q_ASSERT(item.flags & QDockAreaLayoutItem::GapItem);
1085 item.flags &= ~QDockAreaLayoutItem::GapItem;
1086 return item.widgetItem;
1089QLayoutItem *QDockAreaLayoutInfo::unplug(
const QList<
int> &path)
1091 Q_ASSERT(!path.isEmpty());
1093 const int index = path.first();
1094 if (path.size() > 1) {
1095 QDockAreaLayoutItem &item = item_list[index];
1096 Q_ASSERT(item.subinfo !=
nullptr);
1097 return item.subinfo->unplug(path.mid(1));
1100 QDockAreaLayoutItem &item = item_list[index];
1101 int prev =
this->prev(index);
1102 int next =
this->next(index);
1104 Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
1105 item.flags |= QDockAreaLayoutItem::GapItem;
1107#if QT_CONFIG(tabbar)
1112 if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
1116 if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1120 return item.widgetItem;
1123#if QT_CONFIG(tabbar)
1125quintptr QDockAreaLayoutInfo::currentTabId()
const
1127 if (!tabbed || tabBar ==
nullptr)
1130 int index = tabBar->currentIndex();
1134 return qvariant_cast<quintptr>(tabBar->tabData(index));
1137void QDockAreaLayoutInfo::setCurrentTab(QWidget *widget)
1139 setCurrentTabId(
reinterpret_cast<quintptr>(widget));
1142void QDockAreaLayoutInfo::setCurrentTabId(quintptr id)
1144 if (!tabbed || tabBar ==
nullptr)
1147 for (
int i = 0; i < tabBar->count(); ++i) {
1148 if (qvariant_cast<quintptr>(tabBar->tabData(i)) == id) {
1149 tabBar->setCurrentIndex(i);
1159 int titleHeight = 0;
1161 QDockWidgetLayout *layout
1162 = qobject_cast<QDockWidgetLayout*>(widget->layout());
1163 if (layout && layout->nativeWindowDeco())
1164 titleHeight = layout->titleHeight();
1166 QRect result = widget->geometry();
1167 result.adjust(0, -titleHeight, 0, 0);
1171bool QDockAreaLayoutInfo::hasGapItem(
const QList<
int> &path)
const
1179 const int index = path.constFirst();
1180 if (index < 0 || index >= item_list.count())
1183 return item_list[index].flags & QDockAreaLayoutItem::GapItem;
1186bool QDockAreaLayoutInfo::insertGap(
const QList<
int> &path, QLayoutItem *dockWidgetItem)
1188 Q_ASSERT(!path.isEmpty());
1190 bool insert_tabbed =
false;
1191 int index = path.first();
1193 insert_tabbed =
true;
1197 if (path.size() > 1) {
1198 QDockAreaLayoutItem &item = item_list[index];
1200 if (item.subinfo ==
nullptr
1201#if QT_CONFIG(tabbar)
1202 || (item.subinfo->tabbed && !insert_tabbed)
1208 QDockAreaLayoutInfo *subinfo = item.subinfo;
1209 QLayoutItem *widgetItem = item.widgetItem;
1210 QPlaceHolderItem *placeHolderItem = item.placeHolderItem;
1211 QRect r = subinfo ==
nullptr ? widgetItem ? dockedGeometry(widgetItem->widget()) : placeHolderItem->topLevelRect : subinfo->rect;
1213 Qt::Orientation opposite = o == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal;
1214#if !QT_CONFIG(tabbar)
1215 const int tabBarShape = 0;
1217 QDockAreaLayoutInfo *new_info
1218 =
new QDockAreaLayoutInfo(sep, dockPos, opposite, tabBarShape, mainWindow);
1221 item.subinfo = new_info;
1222 item.widgetItem =
nullptr;
1223 item.placeHolderItem =
nullptr;
1225 QDockAreaLayoutItem new_item
1226 = widgetItem ==
nullptr
1227 ? QDockAreaLayoutItem(subinfo)
1228 : widgetItem ? QDockAreaLayoutItem(widgetItem) : QDockAreaLayoutItem(placeHolderItem);
1229 new_item.size = pick(opposite, r.size());
1230 new_item.pos = pick(opposite, r.topLeft());
1231 new_info->item_list.append(new_item);
1232#if QT_CONFIG(tabbar)
1233 if (insert_tabbed) {
1234 new_info->tabbed =
true;
1239 return item.subinfo->insertGap(path.mid(1), dockWidgetItem);
1243 QDockAreaLayoutItem gap_item;
1244 gap_item.flags |= QDockAreaLayoutItem::GapItem;
1245 gap_item.widgetItem = dockWidgetItem;
1247#if QT_CONFIG(tabbar)
1251 int prev =
this->prev(index);
1252 int next =
this->next(index - 1);
1258 case QInternal::LeftDock:
1259 case QInternal::RightDock:
1260 if (o == Qt::Vertical) {
1262 space = pick(Qt::Vertical, rect.size());
1264 space = pick(Qt::Horizontal, dockWidgetItem->widget()->size());
1267 case QInternal::TopDock:
1268 case QInternal::BottomDock:
1270 if (o == Qt::Horizontal) {
1272 space = pick(Qt::Horizontal, rect.size());
1274 space = pick(Qt::Vertical, dockWidgetItem->widget()->size());
1279 for (
int i = 0; i < item_list.size(); ++i) {
1280 const QDockAreaLayoutItem &item = item_list.at(i);
1283 Q_ASSERT_X(!(item.flags & QDockAreaLayoutItem::GapItem),
1284 "QDockAreaLayoutInfo::insertGap",
"inserting two gaps after each other");
1285 space += item.size - pick(o, item.minimumSize());
1286 qCDebug(lcQpaDockWidgets) <<
"Item space:" << item.flags <<
this;
1297 QRect r = dockedGeometry(dockWidgetItem->widget());
1298 gap_size = pick(o, r.size());
1299 if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem))
1301 if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1304 if (gap_size + sep_size > space)
1305 gap_size = pick(o, gap_item.minimumSize());
1306 gap_item.size = gap_size + sep_size;
1310 item_list.insert(index, gap_item);
1311 qCDebug(lcQpaDockWidgets) <<
"Insert gap after:" << index <<
this;
1316QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(QWidget *widget)
1318 for (
int i = 0; i < item_list.size(); ++i) {
1319 const QDockAreaLayoutItem &item = item_list.at(i);
1323#if QT_CONFIG(tabbar)
1324 if (tabbed && widget == tabBar)
1328 if (item.widgetItem !=
nullptr && item.widgetItem->widget() == widget)
1331 if (item.subinfo !=
nullptr) {
1332 if (QDockAreaLayoutInfo *result = item.subinfo->info(widget))
1340QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(
const QList<
int> &path)
1342 int index = path.first();
1345 if (index >= item_list.size())
1347 if (path.size() == 1 || item_list[index].subinfo ==
nullptr)
1349 return item_list[index].subinfo->info(path.mid(1));
1352QRect QDockAreaLayoutInfo::itemRect(
int index,
bool isGap)
const
1354 const QDockAreaLayoutItem &item = item_list.at(index);
1359 if (isGap && !(item.flags & QDockAreaLayoutItem::GapItem))
1364#if QT_CONFIG(tabbar)
1366 if (isGap || tabId(item) == currentTabId())
1367 result = tabContentRect();
1372 int size = item.size;
1375 int prev =
this->prev(index);
1376 int next =
this->next(index);
1377 if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
1381 if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1387 rperp(o, p) = perp(o, rect.topLeft());
1390 rperp(o, s) = perp(o, rect.size());
1391 result = QRect(p, s);
1397QRect QDockAreaLayoutInfo::itemRect(
const QList<
int> &path)
const
1399 Q_ASSERT(!path.isEmpty());
1401 const int index = path.first();
1402 if (path.size() > 1) {
1403 const QDockAreaLayoutItem &item = item_list.at(index);
1404 Q_ASSERT(item.subinfo !=
nullptr);
1405 return item.subinfo->itemRect(path.mid(1));
1408 return itemRect(index);
1411QRect QDockAreaLayoutInfo::separatorRect(
int index)
const
1413#if QT_CONFIG(tabbar)
1418 const QDockAreaLayoutItem &item = item_list.at(index);
1422 QPoint pos = rect.topLeft();
1423 rpick(o, pos) = item.pos + item.size;
1424 QSize s = rect.size();
1427 return QRect(pos, s);
1430QRect QDockAreaLayoutInfo::separatorRect(
const QList<
int> &path)
const
1432 Q_ASSERT(!path.isEmpty());
1434 const int index = path.first();
1435 if (path.size() > 1) {
1436 const QDockAreaLayoutItem &item = item_list.at(index);
1437 Q_ASSERT(item.subinfo !=
nullptr);
1438 return item.subinfo->separatorRect(path.mid(1));
1440 return separatorRect(index);
1443QList<
int> QDockAreaLayoutInfo::findSeparator(
const QPoint &_pos)
const
1445#if QT_CONFIG(tabbar)
1447 return QList<
int>();
1450 int pos = pick(o, _pos);
1452 for (
int i = 0; i < item_list.size(); ++i) {
1453 const QDockAreaLayoutItem &item = item_list.at(i);
1454 if (item.skip() || (item.flags & QDockAreaLayoutItem::GapItem))
1457 if (item.pos + item.size > pos) {
1458 if (item.subinfo !=
nullptr) {
1459 QList<
int> result = item.subinfo->findSeparator(_pos);
1460 if (!result.isEmpty()) {
1464 return QList<
int>();
1469 int next =
this->next(i);
1470 if (next == -1 || (item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1473 QRect sepRect = separatorRect(i);
1474 if (!sepRect.isNull() && *sep == 1)
1475 sepRect.adjust(-2, -2, 2, 2);
1477 if (sepRect.contains(_pos) && !item.hasFixedSize(o)) {
1478 return QList<
int>() << i;
1483 return QList<
int>();
1486QList<
int> QDockAreaLayoutInfo::indexOfPlaceHolder(
const QString &objectName)
const
1488 for (
int i = 0; i < item_list.size(); ++i) {
1489 const QDockAreaLayoutItem &item = item_list.at(i);
1491 if (item.subinfo !=
nullptr) {
1492 QList<
int> result = item.subinfo->indexOfPlaceHolder(objectName);
1493 if (!result.isEmpty()) {
1500 if (item.placeHolderItem !=
nullptr && item.placeHolderItem->objectName == objectName) {
1507 return QList<
int>();
1510QList<
int> QDockAreaLayoutInfo::indexOf(
const QWidget *widget)
const
1512 for (
int i = 0; i < item_list.size(); ++i) {
1513 const QDockAreaLayoutItem &item = item_list.at(i);
1515 if (item.placeHolderItem !=
nullptr)
1518 if (item.subinfo !=
nullptr) {
1519 QList<
int> result = item.subinfo->indexOf(widget);
1520 if (!result.isEmpty()) {
1527 if (!(item.flags & QDockAreaLayoutItem::GapItem) && item.widgetItem && item.widgetItem->widget() == widget) {
1534 return QList<
int>();
1537std::unique_ptr<QLayoutItem> QDockAreaLayoutInfo::takeWidgetItem(QWidget *widget)
1539 std::unique_ptr<QLayoutItem> widgetItem;
1540 if (
const auto path = indexOf(widget); !path.isEmpty())
1541 widgetItem.reset(item(path).widgetItem);
1545QMainWindowLayout *QDockAreaLayoutInfo::mainWindowLayout()
const
1547 QMainWindowLayout *result = qt_mainwindow_layout(mainWindow);
1548 Q_ASSERT(result !=
nullptr);
1552bool QDockAreaLayoutInfo::hasFixedSize()
const
1554 return perp(o, minimumSize()) == perp(o, maximumSize());
1558
1559
1560QDockWidget *QDockAreaLayoutInfo::apply(QWidgetAnimator::AnimationRule rule)
1562 QWidgetAnimator &widgetAnimator = mainWindowLayout()->widgetAnimator;
1564#if QT_CONFIG(tabbar)
1567 QSize tbh = tabBarSizeHint();
1569 if (!tbh.isNull()) {
1570 switch (tabBarShape) {
1571 case QTabBar::RoundedNorth:
1572 case QTabBar::TriangularNorth:
1573 tab_rect = QRect(rect.left(), rect.top(), rect.width(), tbh.height());
1575 case QTabBar::RoundedSouth:
1576 case QTabBar::TriangularSouth:
1577 tab_rect = QRect(rect.left(), rect.bottom() - tbh.height() + 1,
1578 rect.width(), tbh.height());
1580 case QTabBar::RoundedEast:
1581 case QTabBar::TriangularEast:
1582 tab_rect = QRect(rect.right() - tbh.width() + 1, rect.top(),
1583 tbh.width(), rect.height());
1585 case QTabBar::RoundedWest:
1586 case QTabBar::TriangularWest:
1587 tab_rect = QRect(rect.left(), rect.top(),
1588 tbh.width(), rect.height());
1595 widgetAnimator.animate(tabBar, tab_rect, rule);
1599 QDockWidget *activated =
nullptr;
1601 for (
int i = 0; i < item_list.size(); ++i) {
1602 QDockAreaLayoutItem &item = item_list[i];
1604 if (item.flags & QDockAreaLayoutItem::GapItem)
1607 if (item.subinfo !=
nullptr) {
1608 item.subinfo->apply(rule);
1615 Q_ASSERT(item.widgetItem);
1616 QRect r = itemRect(i);
1617 QWidget *w = item.widgetItem->widget();
1619 QRect geo = w->geometry();
1620 widgetAnimator.animate(w, r, rule);
1621 if (!w->isHidden() && w->window()->isVisible()) {
1622 QDockWidget *dw = qobject_cast<QDockWidget*>(w);
1623 if (!r.isValid() && geo.right() >= 0 && geo.bottom() >= 0) {
1625 emit dw->visibilityChanged(
false);
1626 }
else if (r.isValid()
1627 && (geo.right() < 0 || geo.bottom() < 0)) {
1628 emit dw->visibilityChanged(
true);
1633#if QT_CONFIG(tabbar)
1635 updateSeparatorWidgets();
1641static void paintSep(QPainter *p, QWidget *w,
const QRect &r, Qt::Orientation o,
bool mouse_over)
1643 QStyleOption opt(0);
1644 opt.state = QStyle::State_None;
1646 opt.state |= QStyle::State_Enabled;
1647 if (o != Qt::Horizontal)
1648 opt.state |= QStyle::State_Horizontal;
1650 opt.state |= QStyle::State_MouseOver;
1652 opt.palette = w->palette();
1654 w->style()->drawPrimitive(QStyle::PE_IndicatorDockWidgetResizeHandle, &opt, p, w);
1657QRegion QDockAreaLayoutInfo::separatorRegion()
const
1663#if QT_CONFIG(tabbar)
1668 for (
int i = 0; i < item_list.size(); ++i) {
1669 const QDockAreaLayoutItem &item = item_list.at(i);
1674 int next =
this->next(i);
1677 result |= item.subinfo->separatorRegion();
1681 result |= separatorRect(i);
1687void QDockAreaLayoutInfo::paintSeparators(QPainter *p, QWidget *widget,
1688 const QRegion &clip,
1689 const QPoint &mouse)
const
1693#if QT_CONFIG(tabbar)
1698 for (
int i = 0; i < item_list.size(); ++i) {
1699 const QDockAreaLayoutItem &item = item_list.at(i);
1704 int next =
this->next(i);
1705 if ((item.flags & QDockAreaLayoutItem::GapItem)
1706 || (next != -1 && (item_list.at(next).flags & QDockAreaLayoutItem::GapItem)))
1710 if (clip.contains(item.subinfo->rect))
1711 item.subinfo->paintSeparators(p, widget, clip, mouse);
1716 QRect r = separatorRect(i);
1717 if (clip.contains(r) && !item.hasFixedSize(o))
1718 paintSep(p, widget, r, o, r.contains(mouse));
1722int QDockAreaLayoutInfo::next(
int index)
const
1724 for (
int i = index + 1; i < item_list.size(); ++i) {
1725 if (!item_list.at(i).skip())
1731int QDockAreaLayoutInfo::prev(
int index)
const
1733 for (
int i = index - 1; i >= 0; --i) {
1734 if (!item_list.at(i).skip())
1740#if QT_CONFIG(tabbar)
1741void QDockAreaLayoutInfo::tab(
int index, QLayoutItem *dockWidgetItem)
1744 item_list.append(QDockAreaLayoutItem(dockWidgetItem));
1746 setCurrentTab(dockWidgetItem->widget());
1748 QDockAreaLayoutInfo *new_info
1749 =
new QDockAreaLayoutInfo(sep, dockPos, o, tabBarShape, mainWindow);
1750 item_list[index].subinfo = new_info;
1751 new_info->item_list.append(QDockAreaLayoutItem(item_list.at(index).widgetItem));
1752 item_list[index].widgetItem =
nullptr;
1753 new_info->item_list.append(QDockAreaLayoutItem(dockWidgetItem));
1754 new_info->tabbed =
true;
1755 new_info->updateTabBar();
1756 new_info->setCurrentTab(dockWidgetItem->widget());
1761void QDockAreaLayoutInfo::split(
int index, Qt::Orientation orientation,
1762 QLayoutItem *dockWidgetItem)
1764 if (orientation == o) {
1765 item_list.insert(index + 1, QDockAreaLayoutItem(dockWidgetItem));
1767#if !QT_CONFIG(tabbar)
1768 const int tabBarShape = 0;
1770 QDockAreaLayoutInfo *new_info
1771 =
new QDockAreaLayoutInfo(sep, dockPos, orientation, tabBarShape, mainWindow);
1772 item_list[index].subinfo = new_info;
1773 new_info->item_list.append(QDockAreaLayoutItem(item_list.at(index).widgetItem));
1774 item_list[index].widgetItem =
nullptr;
1775 new_info->item_list.append(QDockAreaLayoutItem(dockWidgetItem));
1779QDockAreaLayoutItem &QDockAreaLayoutInfo::item(
const QList<
int> &path)
1781 Q_ASSERT(!path.isEmpty());
1782 const int index = path.first();
1783 if (path.size() > 1) {
1784 const QDockAreaLayoutItem &item = item_list[index];
1785 Q_ASSERT(item.subinfo !=
nullptr);
1786 return item.subinfo->item(path.mid(1));
1788 return item_list[index];
1791QLayoutItem *QDockAreaLayoutInfo::itemAt(
int *x,
int index)
const
1793 for (
int i = 0; i < item_list.size(); ++i) {
1794 const QDockAreaLayoutItem &item = item_list.at(i);
1795 if (item.placeHolderItem !=
nullptr)
1798 if (QLayoutItem *ret = item.subinfo->itemAt(x, index))
1800 }
else if (item.widgetItem) {
1801 if ((*x)++ == index)
1802 return item.widgetItem;
1808QLayoutItem *QDockAreaLayoutInfo::takeAt(
int *x,
int index)
1810 for (
int i = 0; i < item_list.size(); ++i) {
1811 QDockAreaLayoutItem &item = item_list[i];
1812 if (item.placeHolderItem !=
nullptr)
1814 else if (item.subinfo) {
1815 if (QLayoutItem *ret = item.subinfo->takeAt(x, index)) {
1819 }
else if (item.widgetItem) {
1820 if ((*x)++ == index) {
1821 QWidget *widget = item.widgetItem->widget();
1822 if (widget->isWidgetType())
1823 item.placeHolderItem =
new QPlaceHolderItem(widget);
1825 qCDebug(lcQpaDockWidgets) << widget <<
"is in destruction. No gap created.";
1826 QLayoutItem *ret = item.widgetItem;
1827 item.widgetItem =
nullptr;
1828 if (item.size != -1)
1829 item.flags |= QDockAreaLayoutItem::KeepSize;
1838void QDockAreaLayoutInfo::add(QWidget *widget)
1841 if (!indexOf(widget).isEmpty())
1844 if (
auto *dockWidget = qobject_cast<QDockWidget *>(widget)) {
1845 item_list.append(QDockAreaLayoutItem(
new QDockWidgetItem(dockWidget)));
1849 if (
auto *groupWindow = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
1850 item_list.append(QDockAreaLayoutItem(
new QDockWidgetGroupWindowItem(groupWindow)));
1854 qFatal(
"Coding error. Add supports only QDockWidget and QDockWidgetGroupWindow");
1857void QDockAreaLayoutInfo::deleteAllLayoutItems()
1859 for (
int i = 0; i < item_list.size(); ++i) {
1860 QDockAreaLayoutItem &item= item_list[i];
1862 item.subinfo->deleteAllLayoutItems();
1864 delete item.widgetItem;
1865 item.widgetItem =
nullptr;
1870void QDockAreaLayoutInfo::saveState(QDataStream &stream)
const
1873 for (qsizetype i = 0; i < item_list.size(); ++i) {
1874 const QDockAreaLayoutItem &item = item_list.at(i);
1875 if (item.widgetItem && qobject_cast<QDockWidgetGroupWindow *>(item.widgetItem->widget())) {
1881#if QT_CONFIG(tabbar)
1883 stream << StateMarkers::Tab;
1886 quintptr id = currentTabId();
1888 for (
int i = 0; i < item_list.size(); ++i) {
1889 if (tabId(item_list.at(i)) == id) {
1898 stream << StateMarkers::Sequence;
1901 stream <<
static_cast<uchar>(o) <<
static_cast<
int>(cnt);
1903 for (
int i = 0; i < item_list.size(); ++i) {
1904 const QDockAreaLayoutItem &item = item_list.at(i);
1905 if (item.widgetItem !=
nullptr) {
1906 QWidget *w = item.widgetItem->widget();
1907 if (qobject_cast<QDockWidgetGroupWindow *>(w)) {
1908 qCDebug(lcQpaDockWidgets) <<
"Ignoring dock widget group window" << w;
1911 stream << StateMarkers::Widget;
1912 QString name = w->objectName();
1913 if (Q_UNLIKELY(name.isEmpty())) {
1914 qWarning() <<
"QMainWindow::saveState(): 'objectName' not set for"
1915 << w << qUtf16Printable(w->windowTitle());
1921 flags.setFlag(StateFlag::Visible);
1923 flags.setFlag(StateFlag::Floating);
1924 if (qobject_cast<QDockWidgetGroupWindow *>(w->parent()))
1925 flags.setFlag(StateFlag::FloatingTabs);
1926 if (
auto *dw = qobject_cast<QDockWidget *>(w)) {
1927 const auto priv =
static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(dw));
1928 flags.setFlag(StateFlag::Closed, priv->closed);
1930 stream <<
static_cast<uchar>(flags.toInt());
1932 qCDebug(lcQpaDockWidgets) <<
"Saving state for dock widget:" << w->objectName() << flags;
1933 if (w->isWindow()) {
1934 const QRect geometry = w->geometry();
1935 stream << geometry.x() << geometry.y() << geometry.width() << geometry.height();
1937 stream << item.pos << item.size << pick(o, item.minimumSize())
1938 << pick(o, item.maximumSize());
1940 }
else if (item.placeHolderItem !=
nullptr) {
1941 stream << StateMarkers::Widget;
1942 stream << item.placeHolderItem->objectName;
1944 if (!item.placeHolderItem->hidden)
1945 flags.setFlag(StateFlag::Visible);
1946 if (item.placeHolderItem->window)
1947 flags.setFlag(StateFlag::Floating);
1948 qCDebug(lcQpaDockWidgets) <<
"Saving state for placeholder item:" << item << flags;
1949 stream <<
static_cast<uchar>(flags.toInt());
1950 if (item.placeHolderItem->window) {
1951 QRect r = item.placeHolderItem->topLevelRect;
1952 stream << r.x() << r.y() << r.width() << r.height();
1954 stream << item.pos << item.size << (
int)0 << (
int)0;
1956 }
else if (item.subinfo !=
nullptr) {
1957 stream << StateMarkers::Sequence;
1958 stream << item.pos << item.size << pick(o, item.minimumSize()) << pick(o, item.maximumSize());
1959 item.subinfo->saveState(stream);
1967 case QInternal::LeftDock:
return Qt::LeftDockWidgetArea;
1968 case QInternal::RightDock:
return Qt::RightDockWidgetArea;
1969 case QInternal::TopDock:
return Qt::TopDockWidgetArea;
1970 case QInternal::BottomDock:
return Qt::BottomDockWidgetArea;
1973 return Qt::NoDockWidgetArea;
1976bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> &widgets,
1977 QInternal::CallMode callMode,
int depth)
1981 constexpr int maxDepth = 100;
1982 if (depth >= maxDepth)
1985 const bool testing = callMode == QInternal::Testing;
1986 const QLatin1StringView debugCallMode = testing ? QLatin1StringView(
"(testing)")
1987 : QLatin1StringView(
"(restoring)");
1988 QMainWindowLayoutState::StateMarkers marker;
1990 if (marker != StateMarkers::Tab && marker != StateMarkers::Sequence)
1993#if QT_CONFIG(tabbar)
1994 tabbed = marker == StateMarkers::Tab;
2002 stream >> orientation;
2003 o =
static_cast<Qt::Orientation>(orientation);
2008 for (
int i = 0; i < cnt; ++i) {
2009 QMainWindowLayoutState::StateMarkers nextMarker;
2010 stream >> nextMarker;
2011 if (nextMarker == StateMarkers::Widget) {
2014 stream >> name >> f;
2015 StateFlags flags(f);
2016 if (name.isEmpty()) {
2018 stream >> dummy >> dummy >> dummy >> dummy;
2022 QDockWidget *widget =
nullptr;
2023 for (qsizetype j = 0; j < widgets.size(); ++j) {
2024 if (widgets.at(j)->objectName() == name) {
2025 widget = widgets.takeAt(j);
2030 if (widget ==
nullptr) {
2031 QPlaceHolderItem *placeHolder =
new QPlaceHolderItem;
2032 QDockAreaLayoutItem item(placeHolder);
2034 placeHolder->window = flags.testFlag(StateFlag::Floating);
2035 placeHolder->hidden = !flags.testFlag(StateFlag::Visible);
2036 if (placeHolder->window) {
2038 stream >> x >> y >> w >> h;
2039 placeHolder->topLevelRect = QRect(x, y, w, h);
2042 stream >> item.pos >> item.size >> dummy >> dummy;
2044 if (item.size != -1)
2045 item.flags |= QDockAreaLayoutItem::KeepSize;
2046 placeHolder->objectName = std::move(name);
2047 qCDebug(lcQpaDockWidgets) <<
"Restoring placeholder" << item << debugCallMode << flags;
2049 item_list.append(item);
2051 if (flags.testFlag(StateFlag::FloatingTabs))
2052 qCDebug(lcQpaDockWidgets) <<
"Found floating tab:" << name << flags << debugCallMode;
2053 QDockAreaLayoutItem item(
new QDockWidgetItem(widget));
2054 if (flags.testFlag(StateFlag::Floating)) {
2057 widget->setFloating(
true);
2061 stream >> x >> y >> w >> h;
2064 widget->setGeometry(QDockAreaLayout::constrainedRect(QRect(x, y, w, h), widget));
2065 widget->setVisible(flags.testFlag(StateFlag::Visible));
2066 item_list.append(item);
2070 stream >> item.pos >> item.size >> dummy >> dummy;
2072 item_list.append(item);
2073 if (flags.testFlag(StateFlag::Closed)) {
2076 widget->setFloating(
false);
2077 widget->setVisible(flags.testFlag(StateFlag::Visible));
2079 emit widget->dockLocationChanged(toDockWidgetArea(dockPos));
2082 qCDebug(lcQpaDockWidgets) <<
"Restoring QDockWidget" << item << flags << debugCallMode;
2085 delete item.widgetItem;
2086 item.widgetItem =
nullptr;
2089 }
else if (nextMarker == StateMarkers::Sequence) {
2091#if !QT_CONFIG(tabbar)
2092 const int tabBarShape = 0;
2094 QDockAreaLayoutItem item(
new QDockAreaLayoutInfo(sep, dockPos, o,
2095 tabBarShape, mainWindow));
2096 stream >> item.pos >> item.size >> dummy >> dummy;
2097 qCDebug(lcQpaDockWidgets) <<
"Restoring separator item" << item << debugCallMode;
2100 item_list.append(item);
2103 QDockAreaLayoutItem &lastItem = testing ? item : item_list.last();
2105 if (!lastItem.subinfo->restoreState(stream, widgets, callMode, depth + 1))
2113#if QT_CONFIG(tabbar)
2114 if (!testing && tabbed && index >= 0 && index < item_list.size()) {
2116 setCurrentTabId(tabId(item_list.at(index)));
2118 if (!testing && *sep == 1)
2119 updateSeparatorWidgets();
2125#if QT_CONFIG(tabbar)
2127static void raiseSeparatorWidget(QWidget *separatorWidget)
2129 Q_ASSERT(separatorWidget);
2131#if QT_CONFIG(toolbar)
2134 Q_ASSERT(separatorWidget->parent());
2135 const auto toolBars = separatorWidget->parent()->findChildren<QToolBar*>(Qt::FindDirectChildrenOnly);
2136 for (
auto *toolBar : toolBars) {
2137 if (
auto *toolBarLayout = qobject_cast<QToolBarLayout*>(toolBar->layout())) {
2138 if (toolBarLayout->expanded) {
2139 separatorWidget->stackUnder(toolBar);
2146 separatorWidget->raise();
2150void QDockAreaLayoutInfo::updateSeparatorWidgets()
const
2153 separatorWidgets.clear();
2158 for (
int i = 0; i < item_list.size(); ++i) {
2159 const QDockAreaLayoutItem &item = item_list.at(i);
2164 int next =
this->next(i);
2165 if ((item.flags & QDockAreaLayoutItem::GapItem)
2166 || (next != -1 && (item_list.at(next).flags & QDockAreaLayoutItem::GapItem)))
2170 item.subinfo->updateSeparatorWidgets();
2177 if (j < separatorWidgets.size()) {
2178 sepWidget = separatorWidgets.at(j);
2180 qWarning(
"QDockAreaLayoutInfo::updateSeparatorWidgets: null separator widget");
2181 sepWidget = mainWindowLayout()->getSeparatorWidget();
2182 separatorWidgets[j] = sepWidget;
2185 sepWidget = mainWindowLayout()->getSeparatorWidget();
2186 separatorWidgets.append(sepWidget);
2190 Q_ASSERT(sepWidget);
2191 raiseSeparatorWidget(sepWidget);
2193 QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
2194 sepWidget->setGeometry(sepRect);
2195 sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
2199 for (
int k = j; k < separatorWidgets.size(); ++k) {
2200 separatorWidgets[k]->hide();
2202 separatorWidgets.resize(j);
2206
2207
2208
2209
2210void QDockAreaLayoutInfo::reparentWidgets(QWidget *parent)
2213 tabBar->setParent(parent);
2215 for (
int i = 0; i < item_list.size(); ++i) {
2216 const QDockAreaLayoutItem &item = item_list.at(i);
2217 if (item.flags & QDockAreaLayoutItem::GapItem)
2220 item.subinfo->reparentWidgets(parent);
2221 if (item.widgetItem) {
2222 QWidget *w = item.widgetItem->widget();
2223 if (qobject_cast<QDockWidgetGroupWindow *>(w))
2225 if (w->parent() != parent) {
2226 bool hidden = w->isHidden();
2227 w->setParent(parent, w->windowFlags());
2236bool QDockAreaLayoutInfo::updateTabBar()
const
2241 QDockAreaLayoutInfo *that =
const_cast<QDockAreaLayoutInfo*>(
this);
2243 if (that->tabBar ==
nullptr) {
2244 that->tabBar = mainWindowLayout()->getTabBar();
2245 that->tabBar->setShape(
static_cast<QTabBar::Shape>(tabBarShape));
2246 that->tabBar->setDrawBase(
true);
2249 const QSignalBlocker blocker(tabBar);
2252 const quintptr oldCurrentId = currentTabId();
2255 for (
int i = 0; i < item_list.size(); ++i) {
2256 const QDockAreaLayoutItem &item = item_list.at(i);
2259 if (item.flags & QDockAreaLayoutItem::GapItem) {
2263 if (item.widgetItem ==
nullptr)
2266 QDockWidget *dw = qobject_cast<QDockWidget*>(item.widgetItem->widget());
2267 QString title = dw->d_func()->fixedWindowTitle;
2268 quintptr id = tabId(item);
2269 const QIcon windowIcon = dw->testAttribute(Qt::WA_SetWindowIcon) ? dw->windowIcon()
2271 if (tab_idx == tabBar->count()) {
2272 tabBar->insertTab(tab_idx, windowIcon, title);
2273#if QT_CONFIG(tooltip)
2274 tabBar->setTabToolTip(tab_idx, title);
2276 tabBar->setTabData(tab_idx, id);
2277 }
else if (qvariant_cast<quintptr>(tabBar->tabData(tab_idx)) != id) {
2278 if (tab_idx + 1 < tabBar->count()
2279 && qvariant_cast<quintptr>(tabBar->tabData(tab_idx + 1)) == id)
2280 tabBar->removeTab(tab_idx);
2282 tabBar->insertTab(tab_idx, windowIcon, title);
2283#if QT_CONFIG(tooltip)
2284 tabBar->setTabToolTip(tab_idx, title);
2286 tabBar->setTabData(tab_idx, id);
2290 if (title != tabBar->tabText(tab_idx)) {
2291 tabBar->setTabText(tab_idx, title);
2292#if QT_CONFIG(tooltip)
2293 tabBar->setTabToolTip(tab_idx, title);
2300 while (tab_idx < tabBar->count()) {
2301 tabBar->removeTab(tab_idx);
2304 if (oldCurrentId > 0 && currentTabId() != oldCurrentId)
2305 that->setCurrentTabId(oldCurrentId);
2307 if (QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(tabBar->parent()))
2308 dwgw->adjustFlags();
2311 return ( (gap ? 1 : 0) + tabBar->count()) > 1;
2314void QDockAreaLayoutInfo::setTabBarShape(
int shape)
2316 if (shape == tabBarShape)
2318 tabBarShape = shape;
2319 if (tabBar !=
nullptr)
2320 tabBar->setShape(
static_cast<QTabBar::Shape>(shape));
2322 for (
int i = 0; i < item_list.size(); ++i) {
2323 QDockAreaLayoutItem &item = item_list[i];
2324 if (item.subinfo !=
nullptr)
2325 item.subinfo->setTabBarShape(shape);
2329QSize QDockAreaLayoutInfo::tabBarMinimumSize()
const
2331 if (!updateTabBar())
2334 return tabBar->minimumSizeHint();
2337QSize QDockAreaLayoutInfo::tabBarSizeHint()
const
2339 if (!updateTabBar())
2342 return tabBar->sizeHint();
2345QSet<QTabBar*> QDockAreaLayoutInfo::usedTabBars()
const
2347 QSet<QTabBar*> result;
2351 result.insert(tabBar);
2354 for (
int i = 0; i < item_list.size(); ++i) {
2355 const QDockAreaLayoutItem &item = item_list.at(i);
2356 if (item.subinfo !=
nullptr)
2357 result += item.subinfo->usedTabBars();
2365QSet<QWidget*> QDockAreaLayoutInfo::usedSeparatorWidgets()
const
2367 QSet<QWidget*> result;
2368 const int numSeparatorWidgets = separatorWidgets.size();
2369 result.reserve(numSeparatorWidgets);
2371 for (
int i = 0; i < numSeparatorWidgets; ++i)
2372 result << separatorWidgets.at(i);
2374 for (
int i = 0; i < item_list.size(); ++i) {
2375 const QDockAreaLayoutItem &item = item_list.at(i);
2376 if (item.subinfo !=
nullptr)
2377 result += item.subinfo->usedSeparatorWidgets();
2383QRect QDockAreaLayoutInfo::tabContentRect()
const
2388 QRect result = rect;
2389 QSize tbh = tabBarSizeHint();
2391 if (!tbh.isNull()) {
2392 switch (tabBarShape) {
2393 case QTabBar::RoundedNorth:
2394 case QTabBar::TriangularNorth:
2395 result.adjust(0, tbh.height(), 0, 0);
2397 case QTabBar::RoundedSouth:
2398 case QTabBar::TriangularSouth:
2399 result.adjust(0, 0, 0, -tbh.height());
2401 case QTabBar::RoundedEast:
2402 case QTabBar::TriangularEast:
2403 result.adjust(0, 0, -tbh.width(), 0);
2405 case QTabBar::RoundedWest:
2406 case QTabBar::TriangularWest:
2407 result.adjust(tbh.width(), 0, 0, 0);
2417int QDockAreaLayoutInfo::tabIndexToListIndex(
int tabIndex)
const
2419 Q_ASSERT(tabbed && tabBar);
2420 quintptr data = qvariant_cast<quintptr>(tabBar->tabData(tabIndex));
2421 for (
int i = 0; i < item_list.size(); ++i) {
2422 if (tabId(item_list.at(i)) == data)
2428void QDockAreaLayoutInfo::moveTab(
int from,
int to)
2430 item_list.move(tabIndexToListIndex(from), tabIndexToListIndex(to));
2435
2436
2438QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : fallbackToSizeHints(
true)
2441 sep = win->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent,
nullptr, win);
2442#if QT_CONFIG(tabbar)
2443 const int tabShape = QTabBar::RoundedSouth;
2445 const int tabShape = 0;
2447 docks[QInternal::LeftDock]
2448 = QDockAreaLayoutInfo(&sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
2449 docks[QInternal::RightDock]
2450 = QDockAreaLayoutInfo(&sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
2451 docks[QInternal::TopDock]
2452 = QDockAreaLayoutInfo(&sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
2453 docks[QInternal::BottomDock]
2454 = QDockAreaLayoutInfo(&sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
2455 centralWidgetItem =
nullptr;
2458 corners[Qt::TopLeftCorner] = Qt::TopDockWidgetArea;
2459 corners[Qt::TopRightCorner] = Qt::TopDockWidgetArea;
2460 corners[Qt::BottomLeftCorner] = Qt::BottomDockWidgetArea;
2461 corners[Qt::BottomRightCorner] = Qt::BottomDockWidgetArea;
2464bool QDockAreaLayout::isValid()
const
2466 return rect.isValid();
2469void QDockAreaLayout::saveState(QDataStream &stream)
const
2471 stream << StateMarkers::DockWidget;
2473 for (
const auto &dock : docks) {
2474 if (!dock.item_list.isEmpty())
2478 for (std::size_t i = 0; i < docks.size(); ++i) {
2479 if (docks[i].item_list.isEmpty())
2481 stream <<
int(i) << docks[i].rect.size();
2482 docks[i].saveState(stream);
2485 stream << centralWidgetRect.size();
2487 for (
const auto &corner : corners)
2488 stream <<
static_cast<
int>(corner);
2491bool QDockAreaLayout::restoreState(QDataStream &stream,
const QList<QDockWidget*> &_dockwidgets, QInternal::CallMode callMode)
2493 QList<QDockWidget*> dockwidgets = _dockwidgets;
2494 const bool testing = callMode == QInternal::Testing;
2497 static const int dockCount =
int(docks.size());
2498 if (cnt < 0 || cnt > dockCount) {
2499 qWarning() <<
"Invalid data stream. Dock count" << cnt <<
"is out of bound. Maximum:" << dockCount;
2500 stream.setStatus(QDataStream::Status::ReadCorruptData);
2503 for (
int i = 0; i < cnt; ++i) {
2506 if (pos < 0 || pos >= dockCount) {
2507 qWarning() <<
"Invalid data stream. Dock position" << pos <<
"is out of bound. Maximum:" << dockCount - 1;
2508 stream.setStatus(QDataStream::Status::ReadCorruptData);
2515 docks[pos].rect = QRect(QPoint(0, 0), size);
2517 if (!docks[pos].restoreState(stream, dockwidgets, callMode)) {
2518 stream.setStatus(QDataStream::ReadCorruptData);
2525 centralWidgetRect = QRect(QPoint(0, 0), size);
2527 bool ok = stream.status() == QDataStream::Ok;
2530 QDockAreaLayoutCorners cornerData;
2531 for (
auto &val : cornerData)
2534 if (stream.status() == QDataStream::Ok)
2535 corners = std::move(cornerData);
2538 fallbackToSizeHints =
false;
2544QList<
int> QDockAreaLayout::indexOfPlaceHolder(
const QString &objectName)
const
2546 for (std::size_t i = 0; i < docks.size(); ++i) {
2547 QList<
int> result = docks[i].indexOfPlaceHolder(objectName);
2548 if (!result.isEmpty()) {
2549 result.prepend(
int(i));
2553 return QList<
int>();
2556QList<
int> QDockAreaLayout::indexOf(
const QWidget *dockWidget)
const
2558 for (std::size_t i = 0; i < docks.size(); ++i) {
2559 QList<
int> result = docks[i].indexOf(dockWidget);
2560 if (!result.isEmpty()) {
2561 result.prepend(
int(i));
2565 return QList<
int>();
2568QList<
int> QDockAreaLayout::gapIndex(
const QPoint &pos,
bool disallowTabs)
const
2570 QMainWindow::DockOptions opts = mainWindow->dockOptions();
2571 bool nestingEnabled = opts & QMainWindow::AllowNestedDocks;
2572 QDockAreaLayoutInfo::TabMode tabMode = QDockAreaLayoutInfo::NoTabs;
2573#if QT_CONFIG(tabbar)
2574 if (!disallowTabs) {
2575 if (opts & QMainWindow::AllowTabbedDocks || opts & QMainWindow::VerticalTabs)
2576 tabMode = QDockAreaLayoutInfo::AllowTabs;
2577 if (opts & QMainWindow::ForceTabbedDocks)
2578 tabMode = QDockAreaLayoutInfo::ForceTabs;
2580 if (tabMode == QDockAreaLayoutInfo::ForceTabs)
2581 nestingEnabled =
false;
2586 for (std::size_t i = 0; i < docks.size(); ++i) {
2587 const QDockAreaLayoutInfo &info = docks[i];
2589 if (!info.isEmpty() && info.rect.contains(pos)) {
2590 QList<
int> result = info.gapIndex(pos, nestingEnabled, tabMode);
2591 if (!result.isEmpty())
2592 result.prepend(
int(i));
2597 for (std::size_t i = 0; i < docks.size(); ++i) {
2598 const QDockAreaLayoutInfo &info = docks[i];
2600 if (info.isEmpty()) {
2601 const QRect r = gapRect(
static_cast<QInternal::DockPosition>(i));
2602 if (r.contains(pos)) {
2603 if (opts & QMainWindow::ForceTabbedDocks && !info.item_list.isEmpty()) {
2606 return {
int(i), -1, 0};
2614 return QList<
int>();
2617QRect QDockAreaLayout::gapRect(QInternal::DockPosition dockPos)
const
2619 Q_ASSERT_X(mainWindow,
"QDockAreaLayout::gapRect",
"Called without valid mainWindow pointer.");
2622 const QSize gapSize = (mainWindow->size()/2).boundedTo(QSize(EmptyDropAreaSize, EmptyDropAreaSize));
2626 if (mainWindow->height() < (2 * sep)) {
2627 qCWarning(lcQpaDockWidgets,
2628 "QDockAreaLayout::gapRect: Main window height %i is too small. Docking will not be possible.",
2629 mainWindow->height());
2632 if (mainWindow->width() < (2 * sep)) {
2633 qCWarning(lcQpaDockWidgets,
2634 "QDockAreaLayout::gapRect: Main window width %i is too small. Docking will not be possible.",
2635 mainWindow->width());
2640 case QInternal::LeftDock:
2641 return QRect(rect.left(), rect.top(), gapSize.width(), rect.height());
2642 case QInternal::RightDock:
2643 return QRect(rect.right() - gapSize.width(), rect.top(), gapSize.width(), rect.height());
2644 case QInternal::TopDock:
2645 return QRect(rect.left(), rect.top(), rect.width(), gapSize.height());
2646 case QInternal::BottomDock:
2647 return QRect(rect.left(), rect.bottom() - gapSize.height(), rect.width(), gapSize.height());
2648 case QInternal::DockCount:
2654QList<
int> QDockAreaLayout::findSeparator(
const QPoint &pos)
const
2657 for (std::size_t i = 0; i < docks.size(); ++i) {
2658 const QDockAreaLayoutInfo &info = docks[i];
2661 QRect rect = separatorRect(
int(i));
2662 if (!rect.isNull() && sep == 1)
2663 rect.adjust(-2, -2, 2, 2);
2664 if (rect.contains(pos) && !info.hasFixedSize()) {
2667 }
else if (info.rect.contains(pos)) {
2668 result = docks[i].findSeparator(pos);
2669 if (!result.isEmpty()) {
2670 result.prepend(
int(i));
2679QDockAreaLayoutInfo *QDockAreaLayout::info(QWidget *widget)
2681 for (
auto &dock : docks) {
2682 if (QDockAreaLayoutInfo *result = dock.info(widget))
2689QDockAreaLayoutInfo *QDockAreaLayout::info(
const QList<
int> &path)
2691 Q_ASSERT(!path.isEmpty());
2692 const int index = path.first();
2693 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2695 if (path.size() == 1)
2696 return &docks[index];
2698 return docks[index].info(path.mid(1));
2701const QDockAreaLayoutInfo *QDockAreaLayout::info(
const QList<
int> &path)
const
2703 return const_cast<QDockAreaLayout*>(
this)->info(path);
2706QDockAreaLayoutItem &QDockAreaLayout::item(
const QList<
int> &path)
2708 Q_ASSERT(!path.isEmpty());
2709 const int index = path.first();
2710 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2711 return docks[index].item(path.mid(1));
2714QRect QDockAreaLayout::itemRect(
const QList<
int> &path)
const
2716 Q_ASSERT(!path.isEmpty());
2717 const int index = path.first();
2718 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2719 return docks[index].itemRect(path.mid(1));
2722QRect QDockAreaLayout::separatorRect(
int index)
const
2724 const QDockAreaLayoutInfo &dock = docks[index];
2727 QRect r = dock.rect;
2729 case QInternal::LeftDock:
2730 return QRect(r.right() + 1, r.top(), sep, r.height());
2731 case QInternal::RightDock:
2732 return QRect(r.left() - sep, r.top(), sep, r.height());
2733 case QInternal::TopDock:
2734 return QRect(r.left(), r.bottom() + 1, r.width(), sep);
2735 case QInternal::BottomDock:
2736 return QRect(r.left(), r.top() - sep, r.width(), sep);
2743QRect QDockAreaLayout::separatorRect(
const QList<
int> &path)
const
2745 Q_ASSERT(!path.isEmpty());
2747 const int index = path.first();
2748 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2750 if (path.size() == 1)
2751 return separatorRect(index);
2753 return docks[index].separatorRect(path.mid(1));
2756bool QDockAreaLayout::insertGap(
const QList<
int> &path, QLayoutItem *dockWidgetItem)
2758 Q_ASSERT(!path.isEmpty());
2759 const int index = path.first();
2760 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2761 return docks[index].insertGap(path.mid(1), dockWidgetItem);
2764QLayoutItem *QDockAreaLayout::plug(
const QList<
int> &path)
2766#if QT_CONFIG(tabbar)
2767 Q_ASSERT(!path.isEmpty());
2768 const int index = path.first();
2769 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2770 QLayoutItem *item = docks[index].plug(path.mid(1));
2771 docks[index].reparentWidgets(mainWindow);
2778QLayoutItem *QDockAreaLayout::unplug(
const QList<
int> &path)
2780 Q_ASSERT(!path.isEmpty());
2781 const int index = path.first();
2782 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2783 return docks[index].unplug(path.mid(1));
2786void QDockAreaLayout::remove(
const QList<
int> &path)
2788 Q_ASSERT(!path.isEmpty());
2789 const int index = path.first();
2790 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2791 docks[index].remove(path.mid(1));
2794void QDockAreaLayout::removePlaceHolder(
const QString &name)
2796 QList<
int> index = indexOfPlaceHolder(name);
2797 if (!index.isEmpty())
2800 mainWindow->findChildren<QDockWidgetGroupWindow *>(Qt::FindDirectChildrenOnly);
2801 for (QDockWidgetGroupWindow *dwgw : groups) {
2802 index = dwgw->layoutInfo()->indexOfPlaceHolder(name);
2803 if (!index.isEmpty()) {
2804 dwgw->layoutInfo()->remove(index);
2805 dwgw->destroyOrHideIfEmpty();
2810static inline int qMax(
int i1,
int i2,
int i3) {
return qMax(i1, qMax(i2, i3)); }
2812void QDockAreaLayout::getGrid(QList<QLayoutStruct> *_ver_struct_list,
2813 QList<QLayoutStruct> *_hor_struct_list)
2815 QSize center_hint(0, 0);
2816 QSize center_min(0, 0);
2817 QSize center_max(0, 0);
2818 const bool have_central = centralWidgetItem !=
nullptr && !centralWidgetItem->isEmpty();
2820 center_hint = centralWidgetRect.size();
2821 if (!center_hint.isValid())
2822 center_hint = centralWidgetItem->sizeHint();
2823 center_min = centralWidgetItem->minimumSize();
2824 center_max = centralWidgetItem->maximumSize();
2827 QRect center_rect = rect;
2828 if (!docks[QInternal::LeftDock].isEmpty())
2829 center_rect.setLeft(rect.left() + docks[QInternal::LeftDock].rect.width() + sep);
2830 if (!docks[QInternal::TopDock].isEmpty())
2831 center_rect.setTop(rect.top() + docks[QInternal::TopDock].rect.height() + sep);
2832 if (!docks[QInternal::RightDock].isEmpty())
2833 center_rect.setRight(rect.right() - docks[QInternal::RightDock].rect.width() - sep);
2834 if (!docks[QInternal::BottomDock].isEmpty())
2835 center_rect.setBottom(rect.bottom() - docks[QInternal::BottomDock].rect.height() - sep);
2837 QSize left_hint = docks[QInternal::LeftDock].size();
2838 if (left_hint.isNull() || fallbackToSizeHints)
2839 left_hint = docks[QInternal::LeftDock].sizeHint();
2840 QSize left_min = docks[QInternal::LeftDock].minimumSize();
2841 QSize left_max = docks[QInternal::LeftDock].maximumSize();
2842 left_hint = left_hint.boundedTo(left_max).expandedTo(left_min);
2844 QSize right_hint = docks[QInternal::RightDock].size();
2845 if (right_hint.isNull() || fallbackToSizeHints)
2846 right_hint = docks[QInternal::RightDock].sizeHint();
2847 QSize right_min = docks[QInternal::RightDock].minimumSize();
2848 QSize right_max = docks[QInternal::RightDock].maximumSize();
2849 right_hint = right_hint.boundedTo(right_max).expandedTo(right_min);
2851 QSize top_hint = docks[QInternal::TopDock].size();
2852 if (top_hint.isNull() || fallbackToSizeHints)
2853 top_hint = docks[QInternal::TopDock].sizeHint();
2854 QSize top_min = docks[QInternal::TopDock].minimumSize();
2855 QSize top_max = docks[QInternal::TopDock].maximumSize();
2856 top_hint = top_hint.boundedTo(top_max).expandedTo(top_min);
2858 QSize bottom_hint = docks[QInternal::BottomDock].size();
2859 if (bottom_hint.isNull() || fallbackToSizeHints)
2860 bottom_hint = docks[QInternal::BottomDock].sizeHint();
2861 QSize bottom_min = docks[QInternal::BottomDock].minimumSize();
2862 QSize bottom_max = docks[QInternal::BottomDock].maximumSize();
2863 bottom_hint = bottom_hint.boundedTo(bottom_max).expandedTo(bottom_min);
2865 if (_ver_struct_list !=
nullptr) {
2866 QList<QLayoutStruct> &ver_struct_list = *_ver_struct_list;
2867 ver_struct_list.resize(3);
2870 ver_struct_list[0].init();
2871 ver_struct_list[0].stretch = 0;
2872 ver_struct_list[0].sizeHint = top_hint.height();
2873 ver_struct_list[0].minimumSize = top_min.height();
2874 ver_struct_list[0].maximumSize = top_max.height();
2875 ver_struct_list[0].expansive =
false;
2876 ver_struct_list[0].empty = docks[QInternal::TopDock].isEmpty();
2877 ver_struct_list[0].pos = docks[QInternal::TopDock].rect.top();
2878 ver_struct_list[0].size = docks[QInternal::TopDock].rect.height();
2881 ver_struct_list[1].init();
2882 ver_struct_list[1].stretch = center_hint.height();
2884 bool tl_significant = corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
2885 || docks[QInternal::TopDock].isEmpty();
2886 bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
2887 || docks[QInternal::BottomDock].isEmpty();
2888 bool tr_significant = corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
2889 || docks[QInternal::TopDock].isEmpty();
2890 bool br_significant = corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
2891 || docks[QInternal::BottomDock].isEmpty();
2893 int left = (tl_significant && bl_significant) ? left_hint.height() : 0;
2894 int right = (tr_significant && br_significant) ? right_hint.height() : 0;
2895 ver_struct_list[1].sizeHint = qMax(left, center_hint.height(), right);
2897 left = (tl_significant && bl_significant) ? left_min.height() : 0;
2898 right = (tr_significant && br_significant) ? right_min.height() : 0;
2899 ver_struct_list[1].minimumSize = qMax(left, center_min.height(), right);
2900 ver_struct_list[1].maximumSize = center_max.height();
2901 ver_struct_list[1].expansive = have_central;
2902 ver_struct_list[1].empty = docks[QInternal::LeftDock].isEmpty()
2904 && docks[QInternal::RightDock].isEmpty();
2905 ver_struct_list[1].pos = center_rect.top();
2906 ver_struct_list[1].size = center_rect.height();
2909 ver_struct_list[2].init();
2910 ver_struct_list[2].stretch = 0;
2911 ver_struct_list[2].sizeHint = bottom_hint.height();
2912 ver_struct_list[2].minimumSize = bottom_min.height();
2913 ver_struct_list[2].maximumSize = bottom_max.height();
2914 ver_struct_list[2].expansive =
false;
2915 ver_struct_list[2].empty = docks[QInternal::BottomDock].isEmpty();
2916 ver_struct_list[2].pos = docks[QInternal::BottomDock].rect.top();
2917 ver_struct_list[2].size = docks[QInternal::BottomDock].rect.height();
2919 for (
int i = 0; i < 3; ++i) {
2920 ver_struct_list[i].sizeHint
2921 = qMax(ver_struct_list[i].sizeHint, ver_struct_list[i].minimumSize);
2923 if (have_central && ver_struct_list[0].empty && ver_struct_list[2].empty)
2924 ver_struct_list[1].maximumSize = QWIDGETSIZE_MAX;
2927 if (_hor_struct_list !=
nullptr) {
2928 QList<QLayoutStruct> &hor_struct_list = *_hor_struct_list;
2929 hor_struct_list.resize(3);
2932 hor_struct_list[0].init();
2933 hor_struct_list[0].stretch = 0;
2934 hor_struct_list[0].sizeHint = left_hint.width();
2935 hor_struct_list[0].minimumSize = left_min.width();
2936 hor_struct_list[0].maximumSize = left_max.width();
2937 hor_struct_list[0].expansive =
false;
2938 hor_struct_list[0].empty = docks[QInternal::LeftDock].isEmpty();
2939 hor_struct_list[0].pos = docks[QInternal::LeftDock].rect.left();
2940 hor_struct_list[0].size = docks[QInternal::LeftDock].rect.width();
2943 hor_struct_list[1].init();
2944 hor_struct_list[1].stretch = center_hint.width();
2946 bool tl_significant = corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
2947 || docks[QInternal::LeftDock].isEmpty();
2948 bool tr_significant = corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
2949 || docks[QInternal::RightDock].isEmpty();
2950 bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
2951 || docks[QInternal::LeftDock].isEmpty();
2952 bool br_significant = corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
2953 || docks[QInternal::RightDock].isEmpty();
2955 int top = (tl_significant && tr_significant) ? top_hint.width() : 0;
2956 int bottom = (bl_significant && br_significant) ? bottom_hint.width() : 0;
2957 hor_struct_list[1].sizeHint = qMax(top, center_hint.width(), bottom);
2959 top = (tl_significant && tr_significant) ? top_min.width() : 0;
2960 bottom = (bl_significant && br_significant) ? bottom_min.width() : 0;
2961 hor_struct_list[1].minimumSize = qMax(top, center_min.width(), bottom);
2963 hor_struct_list[1].maximumSize = center_max.width();
2964 hor_struct_list[1].expansive = have_central;
2965 hor_struct_list[1].empty = !have_central;
2966 hor_struct_list[1].pos = center_rect.left();
2967 hor_struct_list[1].size = center_rect.width();
2970 hor_struct_list[2].init();
2971 hor_struct_list[2].stretch = 0;
2972 hor_struct_list[2].sizeHint = right_hint.width();
2973 hor_struct_list[2].minimumSize = right_min.width();
2974 hor_struct_list[2].maximumSize = right_max.width();
2975 hor_struct_list[2].expansive =
false;
2976 hor_struct_list[2].empty = docks[QInternal::RightDock].isEmpty();
2977 hor_struct_list[2].pos = docks[QInternal::RightDock].rect.left();
2978 hor_struct_list[2].size = docks[QInternal::RightDock].rect.width();
2980 for (
int i = 0; i < 3; ++i) {
2981 hor_struct_list[i].sizeHint
2982 = qMax(hor_struct_list[i].sizeHint, hor_struct_list[i].minimumSize);
2984 if (have_central && hor_struct_list[0].empty && hor_struct_list[2].empty)
2985 hor_struct_list[1].maximumSize = QWIDGETSIZE_MAX;
2990void QDockAreaLayout::setGrid(QList<QLayoutStruct> *ver_struct_list,
2991 QList<QLayoutStruct> *hor_struct_list)
2996 if (!docks[QInternal::TopDock].isEmpty()) {
2997 QRect r = docks[QInternal::TopDock].rect;
2998 if (hor_struct_list !=
nullptr) {
2999 r.setLeft(corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
3000 || docks[QInternal::LeftDock].isEmpty()
3001 ? rect.left() : hor_struct_list->at(1).pos);
3002 r.setRight(corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
3003 || docks[QInternal::RightDock].isEmpty()
3004 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
3006 if (ver_struct_list !=
nullptr) {
3007 r.setTop(rect.top());
3008 r.setBottom(ver_struct_list->at(1).pos - sep - 1);
3010 docks[QInternal::TopDock].rect = r;
3011 docks[QInternal::TopDock].fitItems();
3016 if (!docks[QInternal::BottomDock].isEmpty()) {
3017 QRect r = docks[QInternal::BottomDock].rect;
3018 if (hor_struct_list !=
nullptr) {
3019 r.setLeft(corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
3020 || docks[QInternal::LeftDock].isEmpty()
3021 ? rect.left() : hor_struct_list->at(1).pos);
3022 r.setRight(corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
3023 || docks[QInternal::RightDock].isEmpty()
3024 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
3026 if (ver_struct_list !=
nullptr) {
3027 r.setTop(ver_struct_list->at(2).pos);
3028 r.setBottom(rect.bottom());
3030 docks[QInternal::BottomDock].rect = r;
3031 docks[QInternal::BottomDock].fitItems();
3036 if (!docks[QInternal::LeftDock].isEmpty()) {
3037 QRect r = docks[QInternal::LeftDock].rect;
3038 if (hor_struct_list !=
nullptr) {
3039 r.setLeft(rect.left());
3040 r.setRight(hor_struct_list->at(1).pos - sep - 1);
3042 if (ver_struct_list !=
nullptr) {
3043 r.setTop(corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
3044 || docks[QInternal::TopDock].isEmpty()
3045 ? rect.top() : ver_struct_list->at(1).pos);
3046 r.setBottom(corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
3047 || docks[QInternal::BottomDock].isEmpty()
3048 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
3050 docks[QInternal::LeftDock].rect = r;
3051 docks[QInternal::LeftDock].fitItems();
3056 if (!docks[QInternal::RightDock].isEmpty()) {
3057 QRect r = docks[QInternal::RightDock].rect;
3058 if (hor_struct_list !=
nullptr) {
3059 r.setLeft(hor_struct_list->at(2).pos);
3060 r.setRight(rect.right());
3062 if (ver_struct_list !=
nullptr) {
3063 r.setTop(corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
3064 || docks[QInternal::TopDock].isEmpty()
3065 ? rect.top() : ver_struct_list->at(1).pos);
3066 r.setBottom(corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
3067 || docks[QInternal::BottomDock].isEmpty()
3068 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
3070 docks[QInternal::RightDock].rect = r;
3071 docks[QInternal::RightDock].fitItems();
3076 if (hor_struct_list !=
nullptr) {
3077 centralWidgetRect.setLeft(hor_struct_list->at(1).pos);
3078 centralWidgetRect.setWidth(hor_struct_list->at(1).size);
3080 if (ver_struct_list !=
nullptr) {
3081 centralWidgetRect.setTop(ver_struct_list->at(1).pos);
3082 centralWidgetRect.setHeight(ver_struct_list->at(1).size);
3086void QDockAreaLayout::fitLayout()
3088 QList<QLayoutStruct> ver_struct_list(3);
3089 QList<QLayoutStruct> hor_struct_list(3);
3090 getGrid(&ver_struct_list, &hor_struct_list);
3092 qGeomCalc(ver_struct_list, 0, 3, rect.top(), rect.height(), sep);
3093 qGeomCalc(hor_struct_list, 0, 3, rect.left(), rect.width(), sep);
3095 setGrid(&ver_struct_list, &hor_struct_list);
3098void QDockAreaLayout::clear()
3100 for (
auto &dock : docks)
3104 centralWidgetRect = QRect();
3107template<
typename SizePMF,
typename CenterPMF>
3108QSize QDockAreaLayout::size_helper(SizePMF sizeFn, CenterPMF centerFn)
const
3115 if (centralWidgetItem !=
nullptr) {
3116 left_sep = docks[QInternal::LeftDock].isEmpty() ? 0 : sep;
3117 right_sep = docks[QInternal::RightDock].isEmpty() ? 0 : sep;
3118 top_sep = docks[QInternal::TopDock].isEmpty() ? 0 : sep;
3119 bottom_sep = docks[QInternal::BottomDock].isEmpty() ? 0 : sep;
3122 const QSize left = (docks[QInternal::LeftDock].*sizeFn)() + QSize(left_sep, 0);
3123 const QSize right = (docks[QInternal::RightDock].*sizeFn)() + QSize(right_sep, 0);
3124 const QSize top = (docks[QInternal::TopDock].*sizeFn)() + QSize(0, top_sep);
3125 const QSize bottom = (docks[QInternal::BottomDock].*sizeFn)() + QSize(0, bottom_sep);
3126 const QSize center = centralWidgetItem ==
nullptr
3127 ? QSize(0, 0) : (centralWidgetItem->*centerFn)();
3129 int row1 = top.width();
3130 int row2 = left.width() + center.width() + right.width();
3131 int row3 = bottom.width();
3132 int col1 = left.height();
3133 int col2 = top.height() + center.height() + bottom.height();
3134 int col3 = right.height();
3136 if (corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea)
3137 row1 += left.width();
3139 col1 += top.height();
3141 if (corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea)
3142 row1 += right.width();
3144 col3 += top.height();
3146 if (corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea)
3147 row3 += left.width();
3149 col1 += bottom.height();
3151 if (corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea)
3152 row3 += right.width();
3154 col3 += bottom.height();
3156 return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
3159QSize QDockAreaLayout::sizeHint()
const
3161 return size_helper(&QDockAreaLayoutInfo::sizeHint, &QLayoutItem::sizeHint);
3164QSize QDockAreaLayout::minimumSize()
const
3166 return size_helper(&QDockAreaLayoutInfo::minimumSize, &QLayoutItem::minimumSize);
3170
3171
3172
3173
3174QSize QDockAreaLayout::minimumStableSize()
const
3176 return size_helper(&QDockAreaLayoutInfo::size, &QLayoutItem::minimumSize);
3180
3181
3182
3183
3184
3185QRect QDockAreaLayout::constrainedRect(QRect rect, QWidget* widget)
3187 QScreen *screen =
nullptr;
3188 if (QGuiApplication::primaryScreen()->virtualSiblings().size() > 1)
3189 screen = QGuiApplication::screenAt(rect.topLeft());
3191 screen = widget->screen();
3193 const QRect screenRect = screen->geometry();
3194 if (screenRect.isValid()) {
3195 rect.setWidth(qMin(rect.width(), screenRect.width()));
3196 rect.setHeight(qMin(rect.height(), screenRect.height()));
3197 rect.moveLeft(qMax(rect.left(), screenRect.left()));
3198 rect.moveTop(qMax(rect.top(), screenRect.top()));
3199 rect.moveRight(qMin(rect.right(), screenRect.right()));
3200 rect.moveBottom(qMin(rect.bottom(), screenRect.bottom()));
3206bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
3208 QDockAreaLayoutItem *item =
nullptr;
3210 mainWindow->findChildren<QDockWidgetGroupWindow *>(Qt::FindDirectChildrenOnly);
3211 for (QDockWidgetGroupWindow *dwgw : groups) {
3212 QList<
int> index = dwgw->layoutInfo()->indexOfPlaceHolder(dockWidget->objectName());
3213 if (!index.isEmpty()) {
3214 dockWidget->setParent(dwgw);
3215 item =
const_cast<QDockAreaLayoutItem *>(&dwgw->layoutInfo()->item(index));
3220 QList<
int> index = indexOfPlaceHolder(dockWidget->objectName());
3221 if (index.isEmpty())
3223 item =
const_cast<QDockAreaLayoutItem *>(&
this->item(index));
3226 QPlaceHolderItem *placeHolder = item->placeHolderItem;
3227 Q_ASSERT(placeHolder !=
nullptr);
3229 item->widgetItem =
new QDockWidgetItem(dockWidget);
3231 if (placeHolder->window) {
3232 const QRect r = constrainedRect(placeHolder->topLevelRect, dockWidget);
3233 dockWidget->d_func()->setWindowState(QDockWidgetPrivate::WindowStates(
3234 {QDockWidgetPrivate::WindowState::Floating,
3235 QDockWidgetPrivate::WindowState::Unplug}), r);
3237 dockWidget->setVisible(!placeHolder->hidden);
3239 item->placeHolderItem =
nullptr;
3245void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *dockWidget,
3246 Qt::Orientation orientation)
3248 QLayoutItem *dockWidgetItem =
new QDockWidgetItem(dockWidget);
3249 Q_ASSERT(size_t(pos) < docks.size());
3250 QDockAreaLayoutInfo &info = docks[pos];
3251 if (orientation == info.o || info.item_list.size() <= 1) {
3254 info.o = orientation;
3256 QDockAreaLayoutItem new_item(dockWidgetItem);
3257 info.item_list.append(new_item);
3258#if QT_CONFIG(tabbar)
3259 if (info.tabbed && !new_item.skip()) {
3260 info.updateTabBar();
3261 info.setCurrentTabId(tabId(new_item));
3265#if QT_CONFIG(tabbar)
3266 int tbshape = info.tabBarShape;
3270 QDockAreaLayoutInfo new_info(&sep, pos, orientation, tbshape, mainWindow);
3271 new_info.item_list.append(QDockAreaLayoutItem(
new QDockAreaLayoutInfo(info)));
3272 new_info.item_list.append(QDockAreaLayoutItem(dockWidgetItem));
3276 removePlaceHolder(dockWidget->objectName());
3279#if QT_CONFIG(tabbar)
3280void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
3282 const QList<
int> path = indexOf(first);
3286 QDockAreaLayoutInfo *info =
this->info(path);
3287 Q_ASSERT(info !=
nullptr);
3288 info->tab(path.last(),
new QDockWidgetItem(second));
3290 removePlaceHolder(second->objectName());
3294void QDockAreaLayout::resizeDocks(
const QList<QDockWidget *> &docks,
3295 const QList<
int> &sizes, Qt::Orientation o)
3297 if (Q_UNLIKELY(docks.size() != sizes.size())) {
3298 qWarning(
"QMainWidget::resizeDocks: size of the lists are not the same");
3301 const int count = docks.size();
3302 fallbackToSizeHints =
false;
3303 for (
int i = 0; i < count; ++i) {
3304 QList<
int> path = indexOf(docks[i]);
3305 if (Q_UNLIKELY(path.isEmpty())) {
3306 qWarning(
"QMainWidget::resizeDocks: one QDockWidget is not part of the layout");
3309 int size = sizes[i];
3310 if (Q_UNLIKELY(size <= 0)) {
3311 qWarning(
"QMainWidget::resizeDocks: all sizes need to be larger than 0");
3315 while (path.size() > 1) {
3316 QDockAreaLayoutInfo *info =
this->info(path);
3317#if QT_CONFIG(tabbar)
3318 if (!info->tabbed && info->o == o) {
3319 info->item_list[path.constLast()].size = size;
3321 for (
const QDockAreaLayoutItem &item : std::as_const(info->item_list)) {
3325 totalSize += item.size == -1 ? pick(o, item.sizeHint()) : item.size;
3334 const int dockNum = path.constFirst();
3335 Q_ASSERT(std::size_t(dockNum) <
this->docks.size());
3336 QRect &r =
this->docks[dockNum].rect;
3343void QDockAreaLayout::splitDockWidget(QDockWidget *after,
3344 QDockWidget *dockWidget,
3345 Qt::Orientation orientation)
3347 const QList<
int> path = indexOf(after);
3351 QDockAreaLayoutInfo *info =
this->info(path);
3352 Q_ASSERT(info !=
nullptr);
3353 info->split(path.last(), orientation,
new QDockWidgetItem(dockWidget));
3355 removePlaceHolder(dockWidget->objectName());
3358void QDockAreaLayout::apply(QWidgetAnimator::AnimationRule rule)
3360 QWidgetAnimator &widgetAnimator = qt_mainwindow_layout(mainWindow)->widgetAnimator;
3362 for (
auto &dock : docks)
3364 if (centralWidgetItem !=
nullptr && !centralWidgetItem->isEmpty()) {
3365 widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect,
3368#if QT_CONFIG(tabbar)
3370 updateSeparatorWidgets();
3374void QDockAreaLayout::paintSeparators(QPainter *p, QWidget *widget,
3375 const QRegion &clip,
3376 const QPoint &mouse)
const
3378 for (
int i = 0; i < QInternal::DockCount; ++i) {
3379 const QDockAreaLayoutInfo &dock = docks[i];
3382 QRect r = separatorRect(i);
3383 if (clip.contains(r) && !dock.hasFixedSize()) {
3384 Qt::Orientation opposite = dock.o == Qt::Horizontal
3385 ? Qt::Vertical : Qt::Horizontal;
3386 paintSep(p, widget, r, opposite, r.contains(mouse));
3388 if (clip.contains(dock.rect))
3389 dock.paintSeparators(p, widget, clip, mouse);
3393QRegion QDockAreaLayout::separatorRegion()
const
3397 for (
int i = 0; i < QInternal::DockCount; ++i) {
3398 const QDockAreaLayoutInfo &dock = docks[i];
3401 result |= separatorRect(i);
3402 result |= dock.separatorRegion();
3408int QDockAreaLayout::separatorMove(
const QList<
int> &separator,
const QPoint &origin,
3412 const auto dockPosition =
static_cast<QInternal::DockPosition>(separator.last());
3413 const bool isHorizontal =
3414 dockPosition == QInternal::LeftDock || dockPosition == QInternal::RightDock;
3415 const bool isLeftOrTop = dockPosition == QInternal::LeftDock || dockPosition == QInternal::TopDock;
3416 const bool separatorIsWithinDock = separator.size() > 1;
3418 if (separatorIsWithinDock) {
3422 QDockAreaLayoutInfo *info =
this->info(separator);
3423 delta = pick(info->o, dest - origin);
3425 delta = info->separatorMove(dockPosition, delta);
3426 info->apply(QWidgetAnimator::AnimationRule::Stop);
3436 QList<QLayoutStruct> list;
3439 getGrid(
nullptr, &list);
3441 getGrid(&list,
nullptr);
3443 const int sep_index = isLeftOrTop ? 0 : 1;
3444 const Qt::Orientation o = isHorizontal ? Qt::Horizontal : Qt::Vertical;
3446 delta = pick(o, dest - origin);
3447 delta = separatorMoveHelper(list, sep_index, delta, sep);
3449 fallbackToSizeHints =
false;
3452 setGrid(
nullptr, &list);
3454 setGrid(&list,
nullptr);
3456 apply(QWidgetAnimator::AnimationRule::Stop);
3461int QDockAreaLayoutInfo::separatorMove(
const QList<
int> &separator,
const QPoint &origin,
3465 int index = separator.last();
3466 QDockAreaLayoutInfo *info =
this->info(separator);
3467 delta = pick(info->o, dest - origin);
3469 delta = info->separatorMove(index, delta);
3470 info->apply(QWidgetAnimator::AnimationRule::Stop);
3474#if QT_CONFIG(tabbar)
3477void QDockAreaLayout::updateSeparatorWidgets()
const
3481 for (
int i = 0; i < QInternal::DockCount; ++i) {
3482 const QDockAreaLayoutInfo &dock = docks[i];
3487 if (j < separatorWidgets.size()) {
3488 sepWidget = separatorWidgets.at(j);
3490 qWarning(
"QDockAreaLayout::updateSeparatorWidgets: null separator widget");
3491 sepWidget = qt_mainwindow_layout(mainWindow)->getSeparatorWidget();
3492 separatorWidgets[j] = sepWidget;
3495 sepWidget = qt_mainwindow_layout(mainWindow)->getSeparatorWidget();
3496 separatorWidgets.append(sepWidget);
3500 Q_ASSERT(sepWidget);
3501 raiseSeparatorWidget(sepWidget);
3503 QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
3504 sepWidget->setGeometry(sepRect);
3505 sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
3508 for (
int i = j; i < separatorWidgets.size(); ++i)
3509 separatorWidgets.at(i)->hide();
3511 separatorWidgets.resize(j);
3515QLayoutItem *QDockAreaLayout::itemAt(
int *x,
int index)
const
3517 Q_ASSERT(x !=
nullptr);
3519 for (
const auto &dock : docks) {
3520 if (QLayoutItem *ret = dock.itemAt(x, index))
3524 if (centralWidgetItem && (*x)++ == index)
3525 return centralWidgetItem;
3530QLayoutItem *QDockAreaLayout::takeAt(
int *x,
int index)
3532 Q_ASSERT(x !=
nullptr);
3534 for (
auto &dock : docks) {
3535 if (QLayoutItem *ret = dock.takeAt(x, index))
3539 if (centralWidgetItem && (*x)++ == index) {
3540 QLayoutItem *ret = centralWidgetItem;
3541 centralWidgetItem =
nullptr;
3548void QDockAreaLayout::deleteAllLayoutItems()
3550 for (
auto &dock : docks)
3551 dock.deleteAllLayoutItems();
3554#if QT_CONFIG(tabbar)
3555QSet<QTabBar*> QDockAreaLayout::usedTabBars()
const
3557 QSet<QTabBar*> result;
3558 for (
const auto &dock : docks)
3559 result += dock.usedTabBars();
3564QSet<QWidget*> QDockAreaLayout::usedSeparatorWidgets()
const
3566 QSet<QWidget*> result;
3567 const int numSeparators = separatorWidgets.size();
3568 result.reserve(numSeparators);
3569 for (
int i = 0; i < numSeparators; ++i)
3570 result << separatorWidgets.at(i);
3571 for (
const auto &dock : docks)
3572 result += dock.usedSeparatorWidgets();
3577QRect QDockAreaLayout::gapRect(
const QList<
int> &path)
const
3579 const QDockAreaLayoutInfo *info =
this->info(path);
3580 if (info ==
nullptr)
3582 int index = path.last();
3583 if (index < 0 || index >= info->item_list.size())
3585 return info->itemRect(index,
true);
3588void QDockAreaLayout::keepSize(QDockWidget *w)
3590 QList<
int> path = indexOf(w);
3593 QDockAreaLayoutItem &item =
this->item(path);
3594 if (item.size != -1)
3595 item.flags |= QDockAreaLayoutItem::KeepSize;
3598void QDockAreaLayout::styleChangedEvent()
3600 sep = mainWindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent,
nullptr, mainWindow);
static int grow(QLayoutStruct &ls, int delta)
static QRect dockedGeometry(QWidget *widget)
static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
static int realMinSize(const QDockAreaLayoutInfo &info)
static int qMax(int i1, int i2, int i3)
static int shrink(QLayoutStruct &ls, int delta)
static std::optional< QInternal::DockPosition > dockPosHelper(const QRect &rect, const QPoint &_pos, Qt::Orientation o, bool nestingEnabled, QDockAreaLayoutInfo::TabMode tabMode)
Q_DECLARE_FLAGS(StateFlags, StateFlag)
static int separatorMoveHelper(QList< QLayoutStruct > &list, int index, int delta, int sep)
static void paintSep(QPainter *p, QWidget *w, const QRect &r, Qt::Orientation o, bool mouse_over)
static int realMaxSize(const QDockAreaLayoutInfo &info)
QMainWindowLayout * qt_mainwindow_layout(const QMainWindow *window)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")