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>
32Q_LOGGING_CATEGORY(lcQpaDockWidgets,
"qt.widgets.dockwidgets");
46using StateMarkers = QMainWindowLayoutState::StateMarkers;
49
50
52QPlaceHolderItem::QPlaceHolderItem(QWidget *w)
54 objectName = w->objectName();
55 hidden = w->isHidden();
56 window = w->isWindow();
58 topLevelRect = w->geometry();
62
63
65QDockAreaLayoutItem::QDockAreaLayoutItem(QLayoutItem *_widgetItem)
66 : widgetItem(_widgetItem), subinfo(
nullptr), placeHolderItem(
nullptr), pos(0), size(-1), flags(NoFlags)
70QDockAreaLayoutItem::QDockAreaLayoutItem(QDockAreaLayoutInfo *_subinfo)
71 : widgetItem(
nullptr), subinfo(_subinfo), placeHolderItem(
nullptr), pos(0), size(-1), flags(NoFlags)
75QDockAreaLayoutItem::QDockAreaLayoutItem(QPlaceHolderItem *_placeHolderItem)
76 : widgetItem(
nullptr), subinfo(
nullptr), placeHolderItem(_placeHolderItem), pos(0), size(-1), flags(NoFlags)
80QDockAreaLayoutItem::QDockAreaLayoutItem(
const QDockAreaLayoutItem &other)
81 : widgetItem(other.widgetItem), subinfo(
nullptr), placeHolderItem(
nullptr), pos(other.pos),
82 size(other.size), flags(other.flags)
84 if (other.subinfo !=
nullptr)
85 subinfo =
new QDockAreaLayoutInfo(*other.subinfo);
86 else if (other.placeHolderItem !=
nullptr)
87 placeHolderItem =
new QPlaceHolderItem(*other.placeHolderItem);
90QDockAreaLayoutItem::~QDockAreaLayoutItem()
93 delete placeHolderItem;
96bool QDockAreaLayoutItem::skip()
const
98 if (placeHolderItem !=
nullptr)
104 if (widgetItem !=
nullptr)
105 return widgetItem->isEmpty();
107 if (subinfo !=
nullptr) {
108 for (
int i = 0; i < subinfo->item_list.size(); ++i) {
109 if (!subinfo->item_list.at(i).skip())
117QSize QDockAreaLayoutItem::minimumSize()
const
120 return widgetItem->minimumSize().grownBy(widgetItem->widget()->contentsMargins());
121 if (subinfo !=
nullptr)
122 return subinfo->minimumSize();
126QSize QDockAreaLayoutItem::maximumSize()
const
129 return widgetItem->maximumSize().grownBy(widgetItem->widget()->contentsMargins());
130 if (subinfo !=
nullptr)
131 return subinfo->maximumSize();
132 return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
135bool QDockAreaLayoutItem::hasFixedSize(Qt::Orientation o)
const
137 return perp(o, minimumSize()) == perp(o, maximumSize());
140bool QDockAreaLayoutItem::expansive(Qt::Orientation o)
const
142 if ((flags & GapItem) || placeHolderItem !=
nullptr)
144 if (widgetItem !=
nullptr)
145 return ((widgetItem->expandingDirections() & o) == o);
146 if (subinfo !=
nullptr)
147 return subinfo->expansive(o);
151QSize QDockAreaLayoutItem::sizeHint()
const
153 if (placeHolderItem !=
nullptr)
156 return widgetItem->sizeHint().grownBy(widgetItem->widget()->contentsMargins());
157 if (subinfo !=
nullptr)
158 return subinfo->sizeHint();
159 return QSize(-1, -1);
163 &QDockAreaLayoutItem::operator = (
const QDockAreaLayoutItem &other)
168 widgetItem = other.widgetItem;
170 if (other.subinfo ==
nullptr)
173 subinfo =
new QDockAreaLayoutInfo(*other.subinfo);
175 delete placeHolderItem;
176 if (other.placeHolderItem ==
nullptr)
177 placeHolderItem =
nullptr;
179 placeHolderItem =
new QPlaceHolderItem(*other.placeHolderItem);
188#ifndef QT_NO_DEBUG_STREAM
189QDebug operator<<(QDebug dbg,
const QDockAreaLayoutItem *item)
191 QDebugStateSaver saver(dbg);
193 return item ? dbg << *item : dbg <<
"QDockAreaLayoutItem(0x0)";
196QDebug operator<<(QDebug dbg,
const QDockAreaLayoutItem &item)
198 QDebugStateSaver saver(dbg);
200 dbg <<
"QDockAreaLayoutItem(" <<
static_cast<
const void *>(&item) <<
"->";
201 if (item.widgetItem) {
202 QWidget *widget = item.widgetItem->widget();
203 if (
auto *dockWidget = qobject_cast<QDockWidget *>(widget)) {
204 dbg <<
"widgetItem(" << dockWidget <<
")";
205 }
else if (
auto *groupWindow = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
206 dbg <<
"widgetItem(" << groupWindow <<
"->(" << groupWindow->dockWidgets() <<
"))";
208 dbg <<
"widgetItem(" << widget <<
")";
210 }
else if (item.subinfo) {
211 dbg <<
"subInfo(" << item.subinfo <<
"->(" << item.subinfo->item_list <<
")";
212 }
else if (item.placeHolderItem) {
213 dbg <<
"placeHolderItem(" << item.placeHolderItem
214 <<
"objectName:" << item.placeHolderItem->objectName <<
"; "
215 <<
"hidden:" << item.placeHolderItem->hidden <<
"; "
216 <<
"window:" << item.placeHolderItem->window <<
"; "
217 <<
"topLevelRect:" << item.placeHolderItem->topLevelRect <<
")";
223QDebug operator<<(QDebug dbg, StateFlags flags)
225 QDebugStateSaver saver(dbg);
226 dbg.nospace().noquote();
229 f << QLatin1StringView(
"Visible");
231 f << QLatin1StringView(
"Floating");
233 f << QLatin1StringView(
"FloatingTabs");
235 f << QLatin1StringView(
"Closed");
236 dbg <<
"StateFlags(" << f.join(u'|') <<
")";
242
243
246static quintptr tabId(
const QDockAreaLayoutItem &item)
248 if (item.widgetItem ==
nullptr)
250 return reinterpret_cast<quintptr>(item.widgetItem->widget());
256QDockAreaLayoutInfo::QDockAreaLayoutInfo()
257 : sep(&zero), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(
nullptr)
259 , tabbed(
false), tabBar(
nullptr), tabBarShape(QTabBar::RoundedSouth)
264QDockAreaLayoutInfo::QDockAreaLayoutInfo(
const int *_sep, QInternal::DockPosition _dockPos,
265 Qt::Orientation _o,
int tbshape,
267 : sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window)
269 , tabbed(
false), tabBar(
nullptr), tabBarShape(
static_cast<QTabBar::Shape>(tbshape))
272#if !QT_CONFIG(tabbar)
277QSize QDockAreaLayoutInfo::size()
const
279 return isEmpty() ? QSize(0, 0) : rect.size();
282void QDockAreaLayoutInfo::clear()
292bool QDockAreaLayoutInfo::isEmpty()
const
294 return next(-1) == -1;
297bool QDockAreaLayoutInfo::onlyHasPlaceholders()
const
299 for (
const QDockAreaLayoutItem &item : item_list) {
300 if (!item.placeHolderItem)
307QSize QDockAreaLayoutInfo::minimumSize()
const
314 for (
int i = 0; i < item_list.size(); ++i) {
315 const QDockAreaLayoutItem &item = item_list.at(i);
319 QSize min_size = item.minimumSize();
322 a = qMax(a, pick(o, min_size));
328 a += pick(o, min_size);
330 b = qMax(b, perp(o, min_size));
336 rpick(o, result) = a;
337 rperp(o, result) = b;
340 QSize tbm = tabBarMinimumSize();
342 switch (tabBarShape) {
343 case QTabBar::RoundedNorth:
344 case QTabBar::RoundedSouth:
345 case QTabBar::TriangularNorth:
346 case QTabBar::TriangularSouth:
347 result.rheight() += tbm.height();
348 result.rwidth() = qMax(tbm.width(), result.width());
350 case QTabBar::RoundedEast:
351 case QTabBar::RoundedWest:
352 case QTabBar::TriangularEast:
353 case QTabBar::TriangularWest:
354 result.rheight() = qMax(tbm.height(), result.height());
355 result.rwidth() += tbm.width();
366QSize QDockAreaLayoutInfo::maximumSize()
const
369 return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
371 int a = 0, b = QWIDGETSIZE_MAX;
380 for (
int i = 0; i < item_list.size(); ++i) {
381 const QDockAreaLayoutItem &item = item_list.at(i);
385 QSize max_size = item.maximumSize();
386 min_perp = qMax(min_perp, perp(o, item.minimumSize()));
390 a = qMin(a, pick(o, max_size));
396 a += pick(o, max_size);
398 b = qMin(b, perp(o, max_size));
400 a = qMin(a,
int(QWIDGETSIZE_MAX));
401 b = qMin(b,
int(QWIDGETSIZE_MAX));
406 b = qMax(b, min_perp);
409 rpick(o, result) = a;
410 rperp(o, result) = b;
413 QSize tbh = tabBarSizeHint();
415 switch (tabBarShape) {
416 case QTabBar::RoundedNorth:
417 case QTabBar::RoundedSouth:
418 result.rheight() += tbh.height();
420 case QTabBar::RoundedEast:
421 case QTabBar::RoundedWest:
422 result.rwidth() += tbh.width();
433QSize QDockAreaLayoutInfo::sizeHint()
const
440 int max_perp = QWIDGETSIZE_MAX;
441 const QDockAreaLayoutItem *previous =
nullptr;
442 for (
int i = 0; i < item_list.size(); ++i) {
443 const QDockAreaLayoutItem &item = item_list.at(i);
447 bool gap = item.flags & QDockAreaLayoutItem::GapItem;
449 QSize size_hint = item.sizeHint();
450 min_perp = qMax(min_perp, perp(o, item.minimumSize()));
451 max_perp = qMin(max_perp, perp(o, item.maximumSize()));
455 a = qMax(a, gap ? item.size : pick(o, size_hint));
459 if (previous && !gap && !(previous->flags & QDockAreaLayoutItem::GapItem)
460 && !previous->hasFixedSize(o)) {
463 a += gap ? item.size : pick(o, size_hint);
465 b = qMax(b, perp(o, size_hint));
470 max_perp = qMax(max_perp, min_perp);
471 b = qMax(b, min_perp);
472 b = qMin(b, max_perp);
475 rpick(o, result) = a;
476 rperp(o, result) = b;
480 QSize tbh = tabBarSizeHint();
481 switch (tabBarShape) {
482 case QTabBar::RoundedNorth:
483 case QTabBar::RoundedSouth:
484 case QTabBar::TriangularNorth:
485 case QTabBar::TriangularSouth:
486 result.rheight() += tbh.height();
487 result.rwidth() = qMax(tbh.width(), result.width());
489 case QTabBar::RoundedEast:
490 case QTabBar::RoundedWest:
491 case QTabBar::TriangularEast:
492 case QTabBar::TriangularWest:
493 result.rheight() = qMax(tbh.height(), result.height());
494 result.rwidth() += tbh.width();
505bool QDockAreaLayoutInfo::expansive(Qt::Orientation o)
const
507 for (
int i = 0; i < item_list.size(); ++i) {
508 if (item_list.at(i).expansive(o))
515
516
517
518
519
525 for (
int i = 0; i < info.item_list.size(); ++i) {
526 const QDockAreaLayoutItem &item = info.item_list.at(i);
531 if ((item.flags & QDockAreaLayoutItem::KeepSize) && item.size != -1)
534 min = pick(info.o, item.minimumSize());
550 for (
int i = 0; i < info.item_list.size(); ++i) {
551 const QDockAreaLayoutItem &item = info.item_list.at(i);
556 if ((item.flags & QDockAreaLayoutItem::KeepSize) && item.size != -1)
559 max = pick(info.o, item.maximumSize());
565 if (result >= QWIDGETSIZE_MAX)
566 return QWIDGETSIZE_MAX;
574void QDockAreaLayoutInfo::fitItems()
582 QList<QLayoutStruct> layout_struct_list(item_list.size() * 2);
585 int size = pick(o, rect.size());
586 int min_size = realMinSize(*
this);
587 int max_size = realMaxSize(*
this);
590 const QDockAreaLayoutItem *previous =
nullptr;
591 for (
int i = 0; i < item_list.size(); ++i) {
592 QDockAreaLayoutItem &item = item_list[i];
596 bool gap = item.flags & QDockAreaLayoutItem::GapItem;
597 if (previous && !gap) {
598 if (!(previous->flags & QDockAreaLayoutItem::GapItem)) {
599 QLayoutStruct &ls = layout_struct_list[j++];
601 ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : *sep;
606 if (item.flags & QDockAreaLayoutItem::KeepSize) {
610 if (size < min_size) {
612 item.flags &= ~QDockAreaLayoutItem::KeepSize;
613 min_size -= item.size;
614 min_size += pick(o, item.minimumSize());
615 min_size = qMax(0, min_size);
616 }
else if (size > max_size) {
618 item.flags &= ~QDockAreaLayoutItem::KeepSize;
619 max_size -= item.size;
620 max_size += pick(o, item.maximumSize());
621 max_size = qMin<
int>(QWIDGETSIZE_MAX, max_size);
626 QLayoutStruct &ls = layout_struct_list[j++];
629 if (item.flags & QDockAreaLayoutItem::KeepSize) {
630 ls.minimumSize = ls.maximumSize = ls.sizeHint = item.size;
631 ls.expansive =
false;
634 ls.maximumSize = pick(o, item.maximumSize());
635 ls.expansive = item.expansive(o);
636 ls.minimumSize = pick(o, item.minimumSize());
637 ls.sizeHint = item.size == -1 ? pick(o, item.sizeHint()) : item.size;
638 ls.stretch = ls.expansive ? ls.sizeHint : 0;
641 item.flags &= ~QDockAreaLayoutItem::KeepSize;
644 layout_struct_list.resize(j);
648 if (size > max_size && last_index != -1) {
649 layout_struct_list[last_index].maximumSize = QWIDGETSIZE_MAX;
650 layout_struct_list[last_index].expansive =
true;
653 qGeomCalc(layout_struct_list, 0, j, pick(o, rect.topLeft()), size, 0);
656 bool prev_gap =
false;
658 for (
int i = 0; i < item_list.size(); ++i) {
659 QDockAreaLayoutItem &item = item_list[i];
663 bool gap = item.flags & QDockAreaLayoutItem::GapItem;
664 if (!first && !gap && !prev_gap)
667 const QLayoutStruct &ls = layout_struct_list.at(j++);
671 if (item.subinfo !=
nullptr) {
672 item.subinfo->rect = itemRect(i);
673 item.subinfo->fitItems();
684 QDockAreaLayoutInfo::TabMode tabMode)
686 if (tabMode == QDockAreaLayoutInfo::ForceTabs)
687 return QInternal::DockCount;
689 QPoint pos = _pos - rect.topLeft();
693 int w = rect.width();
694 int h = rect.height();
696 if (tabMode != QDockAreaLayoutInfo::NoTabs) {
698 if (nestingEnabled) {
700
701
702
703
704
705
706
708 QRect center(w/6, h/6, 2*w/3, 2*h/3);
709 if (center.contains(pos))
710 return QInternal::DockCount;
711 }
else if (o == Qt::Horizontal) {
713
714
715
716
717
718
719
721 if (x > w/6 && x < w*5/6)
722 return QInternal::DockCount;
725
726
727
728
729
730
731 if (y > h/6 && y < 5*h/6)
732 return QInternal::DockCount;
737 if (nestingEnabled) {
738 if (o == Qt::Horizontal) {
740
741
742
743
744
745
748 return QInternal::LeftDock;
750 return QInternal::RightDock;
752 return QInternal::TopDock;
753 return QInternal::BottomDock;
756
757
758
759
760
763 return QInternal::TopDock;
765 return QInternal::BottomDock;
767 return QInternal::LeftDock;
768 return QInternal::RightDock;
771 if (o == Qt::Horizontal) {
773 ? QInternal::LeftDock
774 : QInternal::RightDock;
778 : QInternal::BottomDock;
783QList<
int> QDockAreaLayoutInfo::gapIndex(
const QPoint& _pos,
784 bool nestingEnabled, TabMode tabMode)
const
792 item_rect = tabContentRect();
796 int pos = pick(o, _pos);
799 for (
int i = 0; i < item_list.size(); ++i) {
800 const QDockAreaLayoutItem &item = item_list.at(i);
806 if (item.pos + item.size < pos)
809 if (item.subinfo !=
nullptr
811 && !item.subinfo->tabbed
814 result = item.subinfo->gapIndex(_pos, nestingEnabled,
820 item_rect = itemRect(i);
825 if (item_rect.isNull()) {
826 result.append(last + 1);
831 Q_ASSERT(!item_rect.isNull());
833 QInternal::DockPosition dock_pos
834 = dockPosHelper(item_rect, _pos, o, nestingEnabled, tabMode);
837 case QInternal::LeftDock:
838 if (o == Qt::Horizontal)
839 result << item_index;
841 result << item_index << 0;
844 case QInternal::RightDock:
845 if (o == Qt::Horizontal)
846 result << item_index + 1;
848 result << item_index << 1;
850 case QInternal::TopDock:
851 if (o == Qt::Horizontal)
852 result << item_index << 0;
854 result << item_index;
856 case QInternal::BottomDock:
857 if (o == Qt::Horizontal)
858 result << item_index << 1;
860 result << item_index + 1;
862 case QInternal::DockCount:
863 result << (-item_index - 1) << 0;
878 int old_size = ls.size;
879 ls.size = qMax(ls.size - delta, ls.minimumSize);
880 return old_size - ls.size;
887 int old_size = ls.size;
888 ls.size = qMin(ls.size + delta, ls.maximumSize);
889 return ls.size - old_size;
896 for (
int i = 0; i < list.size(); ++i) {
908 for (
int i = 0; i<=index; ++i) {
912 if (ls.maximumSize == QLAYOUTSIZE_MAX) {
913 growlimit = QLAYOUTSIZE_MAX;
916 growlimit += ls.maximumSize - ls.size;
918 if (delta > growlimit)
922 for (
int i = index + 1; d < delta && i < list.size(); ++i)
923 d += shrink(list[i], delta - d);
926 for (
int i = index; d < delta && i >= 0; --i)
927 d += grow(list[i], delta - d);
928 }
else if (delta < 0) {
930 for (
int i = index + 1; i < list.size(); ++i) {
934 if (ls.maximumSize == QLAYOUTSIZE_MAX) {
935 growlimit = QLAYOUTSIZE_MAX;
938 growlimit += ls.maximumSize - ls.size;
940 if (-delta > growlimit)
944 for (
int i = index; d < -delta && i >= 0; --i)
945 d += shrink(list[i], -delta - d);
948 for (
int i = index + 1; d < -delta && i < list.size(); ++i)
949 d += grow(list[i], -delta - d);
954 for (
int i = 0; i < list.size(); ++i) {
957 ls.pos = pos + (first ? 0 : sep);
970int QDockAreaLayoutInfo::separatorMove(
int index,
int delta)
976 QList<QLayoutStruct> list(item_list.size());
977 for (
int i = 0; i < list.size(); ++i) {
978 const QDockAreaLayoutItem &item = item_list.at(i);
979 QLayoutStruct &ls = list[i];
980 Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
984 const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
987 ls.size = item.size + separatorSpace;
988 ls.minimumSize = pick(o, item.minimumSize()) + separatorSpace;
989 ls.maximumSize = pick(o, item.maximumSize()) + separatorSpace;
995 delta = separatorMoveHelper(list, index, delta, 0 );
997 for (
int i = 0; i < list.size(); ++i) {
998 QDockAreaLayoutItem &item = item_list[i];
1001 QLayoutStruct &ls = list[i];
1002 const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
1003 item.size = ls.size - separatorSpace;
1005 if (item.subinfo !=
nullptr) {
1006 item.subinfo->rect = itemRect(i);
1007 item.subinfo->fitItems();
1014void QDockAreaLayoutInfo::unnest(
int index)
1016 QDockAreaLayoutItem &item = item_list[index];
1017 if (item.subinfo ==
nullptr)
1019 if (item.subinfo->item_list.size() > 1)
1022 if (item.subinfo->item_list.size() == 0) {
1023 item_list.removeAt(index);
1024 }
else if (item.subinfo->item_list.size() == 1) {
1025 QDockAreaLayoutItem &child = item.subinfo->item_list.first();
1026 if (child.widgetItem !=
nullptr) {
1027 item.widgetItem = child.widgetItem;
1028 delete item.subinfo;
1029 item.subinfo =
nullptr;
1030 }
else if (child.subinfo !=
nullptr) {
1031 QDockAreaLayoutInfo *tmp = item.subinfo;
1032 item.subinfo = child.subinfo;
1033 child.subinfo =
nullptr;
1034 tmp->item_list.clear();
1040void QDockAreaLayoutInfo::remove(
const QList<
int> &path)
1042 Q_ASSERT(!path.isEmpty());
1044 if (path.size() > 1) {
1045 const int index = path.first();
1046 QDockAreaLayoutItem &item = item_list[index];
1047 Q_ASSERT(item.subinfo !=
nullptr);
1048 item.subinfo->remove(path.mid(1));
1051 int index = path.first();
1052 item_list.removeAt(index);
1056void QDockAreaLayoutInfo::remove(QWidget *widget)
1058 const QList<
int> path = indexOf(widget);
1064QLayoutItem *QDockAreaLayoutInfo::plug(
const QList<
int> &path)
1066 Q_ASSERT(!path.isEmpty());
1068 int index = path.first();
1072 if (path.size() > 1) {
1073 QDockAreaLayoutItem &item = item_list[index];
1074 Q_ASSERT(item.subinfo !=
nullptr);
1075 return item.subinfo->plug(path.mid(1));
1078 QDockAreaLayoutItem &item = item_list[index];
1080 Q_ASSERT(item.widgetItem !=
nullptr);
1081 Q_ASSERT(item.flags & QDockAreaLayoutItem::GapItem);
1082 item.flags &= ~QDockAreaLayoutItem::GapItem;
1083 return item.widgetItem;
1086QLayoutItem *QDockAreaLayoutInfo::unplug(
const QList<
int> &path)
1088 Q_ASSERT(!path.isEmpty());
1090 const int index = path.first();
1091 if (path.size() > 1) {
1092 QDockAreaLayoutItem &item = item_list[index];
1093 Q_ASSERT(item.subinfo !=
nullptr);
1094 return item.subinfo->unplug(path.mid(1));
1097 QDockAreaLayoutItem &item = item_list[index];
1098 int prev =
this->prev(index);
1099 int next =
this->next(index);
1101 Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
1102 item.flags |= QDockAreaLayoutItem::GapItem;
1104#if QT_CONFIG(tabbar)
1109 if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
1113 if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1117 return item.widgetItem;
1120#if QT_CONFIG(tabbar)
1122quintptr QDockAreaLayoutInfo::currentTabId()
const
1124 if (!tabbed || tabBar ==
nullptr)
1127 int index = tabBar->currentIndex();
1131 return qvariant_cast<quintptr>(tabBar->tabData(index));
1134void QDockAreaLayoutInfo::setCurrentTab(QWidget *widget)
1136 setCurrentTabId(
reinterpret_cast<quintptr>(widget));
1139void QDockAreaLayoutInfo::setCurrentTabId(quintptr id)
1141 if (!tabbed || tabBar ==
nullptr)
1144 for (
int i = 0; i < tabBar->count(); ++i) {
1145 if (qvariant_cast<quintptr>(tabBar->tabData(i)) == id) {
1146 tabBar->setCurrentIndex(i);
1156 int titleHeight = 0;
1158 QDockWidgetLayout *layout
1159 = qobject_cast<QDockWidgetLayout*>(widget->layout());
1160 if (layout && layout->nativeWindowDeco())
1161 titleHeight = layout->titleHeight();
1163 QRect result = widget->geometry();
1164 result.adjust(0, -titleHeight, 0, 0);
1168bool QDockAreaLayoutInfo::hasGapItem(
const QList<
int> &path)
const
1176 const int index = path.constFirst();
1177 if (index < 0 || index >= item_list.count())
1180 return item_list[index].flags & QDockAreaLayoutItem::GapItem;
1183bool QDockAreaLayoutInfo::insertGap(
const QList<
int> &path, QLayoutItem *dockWidgetItem)
1185 Q_ASSERT(!path.isEmpty());
1187 bool insert_tabbed =
false;
1188 int index = path.first();
1190 insert_tabbed =
true;
1194 if (path.size() > 1) {
1195 QDockAreaLayoutItem &item = item_list[index];
1197 if (item.subinfo ==
nullptr
1198#if QT_CONFIG(tabbar)
1199 || (item.subinfo->tabbed && !insert_tabbed)
1205 QDockAreaLayoutInfo *subinfo = item.subinfo;
1206 QLayoutItem *widgetItem = item.widgetItem;
1207 QPlaceHolderItem *placeHolderItem = item.placeHolderItem;
1208 QRect r = subinfo ==
nullptr ? widgetItem ? dockedGeometry(widgetItem->widget()) : placeHolderItem->topLevelRect : subinfo->rect;
1210 Qt::Orientation opposite = o == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal;
1211#if !QT_CONFIG(tabbar)
1212 const int tabBarShape = 0;
1214 QDockAreaLayoutInfo *new_info
1215 =
new QDockAreaLayoutInfo(sep, dockPos, opposite, tabBarShape, mainWindow);
1218 item.subinfo = new_info;
1219 item.widgetItem =
nullptr;
1220 item.placeHolderItem =
nullptr;
1222 QDockAreaLayoutItem new_item
1223 = widgetItem ==
nullptr
1224 ? QDockAreaLayoutItem(subinfo)
1225 : widgetItem ? QDockAreaLayoutItem(widgetItem) : QDockAreaLayoutItem(placeHolderItem);
1226 new_item.size = pick(opposite, r.size());
1227 new_item.pos = pick(opposite, r.topLeft());
1228 new_info->item_list.append(new_item);
1229#if QT_CONFIG(tabbar)
1230 if (insert_tabbed) {
1231 new_info->tabbed =
true;
1236 return item.subinfo->insertGap(path.mid(1), dockWidgetItem);
1240 QDockAreaLayoutItem gap_item;
1241 gap_item.flags |= QDockAreaLayoutItem::GapItem;
1242 gap_item.widgetItem = dockWidgetItem;
1244#if QT_CONFIG(tabbar)
1248 int prev =
this->prev(index);
1249 int next =
this->next(index - 1);
1255 case QInternal::LeftDock:
1256 case QInternal::RightDock:
1257 if (o == Qt::Vertical) {
1259 space = pick(Qt::Vertical, rect.size());
1261 space = pick(Qt::Horizontal, dockWidgetItem->widget()->size());
1264 case QInternal::TopDock:
1265 case QInternal::BottomDock:
1267 if (o == Qt::Horizontal) {
1269 space = pick(Qt::Horizontal, rect.size());
1271 space = pick(Qt::Vertical, dockWidgetItem->widget()->size());
1276 for (
int i = 0; i < item_list.size(); ++i) {
1277 const QDockAreaLayoutItem &item = item_list.at(i);
1280 Q_ASSERT_X(!(item.flags & QDockAreaLayoutItem::GapItem),
1281 "QDockAreaLayoutInfo::insertGap",
"inserting two gaps after each other");
1282 space += item.size - pick(o, item.minimumSize());
1283 qCDebug(lcQpaDockWidgets) <<
"Item space:" << item.flags <<
this;
1294 QRect r = dockedGeometry(dockWidgetItem->widget());
1295 gap_size = pick(o, r.size());
1296 if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem))
1298 if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1301 if (gap_size + sep_size > space)
1302 gap_size = pick(o, gap_item.minimumSize());
1303 gap_item.size = gap_size + sep_size;
1307 item_list.insert(index, gap_item);
1308 qCDebug(lcQpaDockWidgets) <<
"Insert gap after:" << index <<
this;
1313QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(QWidget *widget)
1315 for (
int i = 0; i < item_list.size(); ++i) {
1316 const QDockAreaLayoutItem &item = item_list.at(i);
1320#if QT_CONFIG(tabbar)
1321 if (tabbed && widget == tabBar)
1325 if (item.widgetItem !=
nullptr && item.widgetItem->widget() == widget)
1328 if (item.subinfo !=
nullptr) {
1329 if (QDockAreaLayoutInfo *result = item.subinfo->info(widget))
1337QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(
const QList<
int> &path)
1339 int index = path.first();
1342 if (index >= item_list.size())
1344 if (path.size() == 1 || item_list[index].subinfo ==
nullptr)
1346 return item_list[index].subinfo->info(path.mid(1));
1349QRect QDockAreaLayoutInfo::itemRect(
int index,
bool isGap)
const
1351 const QDockAreaLayoutItem &item = item_list.at(index);
1356 if (isGap && !(item.flags & QDockAreaLayoutItem::GapItem))
1361#if QT_CONFIG(tabbar)
1363 if (isGap || tabId(item) == currentTabId())
1364 result = tabContentRect();
1369 int size = item.size;
1372 int prev =
this->prev(index);
1373 int next =
this->next(index);
1374 if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
1378 if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1384 rperp(o, p) = perp(o, rect.topLeft());
1387 rperp(o, s) = perp(o, rect.size());
1388 result = QRect(p, s);
1394QRect QDockAreaLayoutInfo::itemRect(
const QList<
int> &path)
const
1396 Q_ASSERT(!path.isEmpty());
1398 const int index = path.first();
1399 if (path.size() > 1) {
1400 const QDockAreaLayoutItem &item = item_list.at(index);
1401 Q_ASSERT(item.subinfo !=
nullptr);
1402 return item.subinfo->itemRect(path.mid(1));
1405 return itemRect(index);
1408QRect QDockAreaLayoutInfo::separatorRect(
int index)
const
1410#if QT_CONFIG(tabbar)
1415 const QDockAreaLayoutItem &item = item_list.at(index);
1419 QPoint pos = rect.topLeft();
1420 rpick(o, pos) = item.pos + item.size;
1421 QSize s = rect.size();
1424 return QRect(pos, s);
1427QRect QDockAreaLayoutInfo::separatorRect(
const QList<
int> &path)
const
1429 Q_ASSERT(!path.isEmpty());
1431 const int index = path.first();
1432 if (path.size() > 1) {
1433 const QDockAreaLayoutItem &item = item_list.at(index);
1434 Q_ASSERT(item.subinfo !=
nullptr);
1435 return item.subinfo->separatorRect(path.mid(1));
1437 return separatorRect(index);
1440QList<
int> QDockAreaLayoutInfo::findSeparator(
const QPoint &_pos)
const
1442#if QT_CONFIG(tabbar)
1444 return QList<
int>();
1447 int pos = pick(o, _pos);
1449 for (
int i = 0; i < item_list.size(); ++i) {
1450 const QDockAreaLayoutItem &item = item_list.at(i);
1451 if (item.skip() || (item.flags & QDockAreaLayoutItem::GapItem))
1454 if (item.pos + item.size > pos) {
1455 if (item.subinfo !=
nullptr) {
1456 QList<
int> result = item.subinfo->findSeparator(_pos);
1457 if (!result.isEmpty()) {
1461 return QList<
int>();
1466 int next =
this->next(i);
1467 if (next == -1 || (item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1470 QRect sepRect = separatorRect(i);
1471 if (!sepRect.isNull() && *sep == 1)
1472 sepRect.adjust(-2, -2, 2, 2);
1474 if (sepRect.contains(_pos) && !item.hasFixedSize(o)) {
1475 return QList<
int>() << i;
1480 return QList<
int>();
1483QList<
int> QDockAreaLayoutInfo::indexOfPlaceHolder(
const QString &objectName)
const
1485 for (
int i = 0; i < item_list.size(); ++i) {
1486 const QDockAreaLayoutItem &item = item_list.at(i);
1488 if (item.subinfo !=
nullptr) {
1489 QList<
int> result = item.subinfo->indexOfPlaceHolder(objectName);
1490 if (!result.isEmpty()) {
1497 if (item.placeHolderItem !=
nullptr && item.placeHolderItem->objectName == objectName) {
1504 return QList<
int>();
1507QList<
int> QDockAreaLayoutInfo::indexOf(
const QWidget *widget)
const
1509 for (
int i = 0; i < item_list.size(); ++i) {
1510 const QDockAreaLayoutItem &item = item_list.at(i);
1512 if (item.placeHolderItem !=
nullptr)
1515 if (item.subinfo !=
nullptr) {
1516 QList<
int> result = item.subinfo->indexOf(widget);
1517 if (!result.isEmpty()) {
1524 if (!(item.flags & QDockAreaLayoutItem::GapItem) && item.widgetItem && item.widgetItem->widget() == widget) {
1531 return QList<
int>();
1534std::unique_ptr<QLayoutItem> QDockAreaLayoutInfo::takeWidgetItem(QWidget *widget)
1536 std::unique_ptr<QLayoutItem> widgetItem;
1537 if (
const auto path = indexOf(widget); !path.isEmpty())
1538 widgetItem.reset(item(path).widgetItem);
1542QMainWindowLayout *QDockAreaLayoutInfo::mainWindowLayout()
const
1544 QMainWindowLayout *result = qt_mainwindow_layout(mainWindow);
1545 Q_ASSERT(result !=
nullptr);
1549bool QDockAreaLayoutInfo::hasFixedSize()
const
1551 return perp(o, minimumSize()) == perp(o, maximumSize());
1555
1556
1557QDockWidget *QDockAreaLayoutInfo::apply(QWidgetAnimator::AnimationRule rule)
1559 QWidgetAnimator &widgetAnimator = mainWindowLayout()->widgetAnimator;
1561#if QT_CONFIG(tabbar)
1564 QSize tbh = tabBarSizeHint();
1566 if (!tbh.isNull()) {
1567 switch (tabBarShape) {
1568 case QTabBar::RoundedNorth:
1569 case QTabBar::TriangularNorth:
1570 tab_rect = QRect(rect.left(), rect.top(), rect.width(), tbh.height());
1572 case QTabBar::RoundedSouth:
1573 case QTabBar::TriangularSouth:
1574 tab_rect = QRect(rect.left(), rect.bottom() - tbh.height() + 1,
1575 rect.width(), tbh.height());
1577 case QTabBar::RoundedEast:
1578 case QTabBar::TriangularEast:
1579 tab_rect = QRect(rect.right() - tbh.width() + 1, rect.top(),
1580 tbh.width(), rect.height());
1582 case QTabBar::RoundedWest:
1583 case QTabBar::TriangularWest:
1584 tab_rect = QRect(rect.left(), rect.top(),
1585 tbh.width(), rect.height());
1592 widgetAnimator.animate(tabBar, tab_rect, rule);
1596 QDockWidget *activated =
nullptr;
1598 for (
int i = 0; i < item_list.size(); ++i) {
1599 QDockAreaLayoutItem &item = item_list[i];
1601 if (item.flags & QDockAreaLayoutItem::GapItem)
1604 if (item.subinfo !=
nullptr) {
1605 item.subinfo->apply(rule);
1612 Q_ASSERT(item.widgetItem);
1613 QRect r = itemRect(i);
1614 QWidget *w = item.widgetItem->widget();
1616 QRect geo = w->geometry();
1617 widgetAnimator.animate(w, r, rule);
1618 if (!w->isHidden() && w->window()->isVisible()) {
1619 QDockWidget *dw = qobject_cast<QDockWidget*>(w);
1620 if (!r.isValid() && geo.right() >= 0 && geo.bottom() >= 0) {
1622 emit dw->visibilityChanged(
false);
1623 }
else if (r.isValid()
1624 && (geo.right() < 0 || geo.bottom() < 0)) {
1625 emit dw->visibilityChanged(
true);
1630#if QT_CONFIG(tabbar)
1632 updateSeparatorWidgets();
1638static void paintSep(QPainter *p, QWidget *w,
const QRect &r, Qt::Orientation o,
bool mouse_over)
1640 QStyleOption opt(0);
1641 opt.state = QStyle::State_None;
1643 opt.state |= QStyle::State_Enabled;
1644 if (o != Qt::Horizontal)
1645 opt.state |= QStyle::State_Horizontal;
1647 opt.state |= QStyle::State_MouseOver;
1649 opt.palette = w->palette();
1651 w->style()->drawPrimitive(QStyle::PE_IndicatorDockWidgetResizeHandle, &opt, p, w);
1654QRegion QDockAreaLayoutInfo::separatorRegion()
const
1660#if QT_CONFIG(tabbar)
1665 for (
int i = 0; i < item_list.size(); ++i) {
1666 const QDockAreaLayoutItem &item = item_list.at(i);
1671 int next =
this->next(i);
1674 result |= item.subinfo->separatorRegion();
1678 result |= separatorRect(i);
1684void QDockAreaLayoutInfo::paintSeparators(QPainter *p, QWidget *widget,
1685 const QRegion &clip,
1686 const QPoint &mouse)
const
1690#if QT_CONFIG(tabbar)
1695 for (
int i = 0; i < item_list.size(); ++i) {
1696 const QDockAreaLayoutItem &item = item_list.at(i);
1701 int next =
this->next(i);
1702 if ((item.flags & QDockAreaLayoutItem::GapItem)
1703 || (next != -1 && (item_list.at(next).flags & QDockAreaLayoutItem::GapItem)))
1707 if (clip.contains(item.subinfo->rect))
1708 item.subinfo->paintSeparators(p, widget, clip, mouse);
1713 QRect r = separatorRect(i);
1714 if (clip.contains(r) && !item.hasFixedSize(o))
1715 paintSep(p, widget, r, o, r.contains(mouse));
1719int QDockAreaLayoutInfo::next(
int index)
const
1721 for (
int i = index + 1; i < item_list.size(); ++i) {
1722 if (!item_list.at(i).skip())
1728int QDockAreaLayoutInfo::prev(
int index)
const
1730 for (
int i = index - 1; i >= 0; --i) {
1731 if (!item_list.at(i).skip())
1737#if QT_CONFIG(tabbar)
1738void QDockAreaLayoutInfo::tab(
int index, QLayoutItem *dockWidgetItem)
1741 item_list.append(QDockAreaLayoutItem(dockWidgetItem));
1743 setCurrentTab(dockWidgetItem->widget());
1745 QDockAreaLayoutInfo *new_info
1746 =
new QDockAreaLayoutInfo(sep, dockPos, o, tabBarShape, mainWindow);
1747 item_list[index].subinfo = new_info;
1748 new_info->item_list.append(QDockAreaLayoutItem(item_list.at(index).widgetItem));
1749 item_list[index].widgetItem =
nullptr;
1750 new_info->item_list.append(QDockAreaLayoutItem(dockWidgetItem));
1751 new_info->tabbed =
true;
1752 new_info->updateTabBar();
1753 new_info->setCurrentTab(dockWidgetItem->widget());
1758void QDockAreaLayoutInfo::split(
int index, Qt::Orientation orientation,
1759 QLayoutItem *dockWidgetItem)
1761 if (orientation == o) {
1762 item_list.insert(index + 1, QDockAreaLayoutItem(dockWidgetItem));
1764#if !QT_CONFIG(tabbar)
1765 const int tabBarShape = 0;
1767 QDockAreaLayoutInfo *new_info
1768 =
new QDockAreaLayoutInfo(sep, dockPos, orientation, tabBarShape, mainWindow);
1769 item_list[index].subinfo = new_info;
1770 new_info->item_list.append(QDockAreaLayoutItem(item_list.at(index).widgetItem));
1771 item_list[index].widgetItem =
nullptr;
1772 new_info->item_list.append(QDockAreaLayoutItem(dockWidgetItem));
1776QDockAreaLayoutItem &QDockAreaLayoutInfo::item(
const QList<
int> &path)
1778 Q_ASSERT(!path.isEmpty());
1779 const int index = path.first();
1780 if (path.size() > 1) {
1781 const QDockAreaLayoutItem &item = item_list[index];
1782 Q_ASSERT(item.subinfo !=
nullptr);
1783 return item.subinfo->item(path.mid(1));
1785 return item_list[index];
1788QLayoutItem *QDockAreaLayoutInfo::itemAt(
int *x,
int index)
const
1790 for (
int i = 0; i < item_list.size(); ++i) {
1791 const QDockAreaLayoutItem &item = item_list.at(i);
1792 if (item.placeHolderItem !=
nullptr)
1795 if (QLayoutItem *ret = item.subinfo->itemAt(x, index))
1797 }
else if (item.widgetItem) {
1798 if ((*x)++ == index)
1799 return item.widgetItem;
1805QLayoutItem *QDockAreaLayoutInfo::takeAt(
int *x,
int index)
1807 for (
int i = 0; i < item_list.size(); ++i) {
1808 QDockAreaLayoutItem &item = item_list[i];
1809 if (item.placeHolderItem !=
nullptr)
1811 else if (item.subinfo) {
1812 if (QLayoutItem *ret = item.subinfo->takeAt(x, index)) {
1816 }
else if (item.widgetItem) {
1817 if ((*x)++ == index) {
1818 QWidget *widget = item.widgetItem->widget();
1819 if (widget->isWidgetType())
1820 item.placeHolderItem =
new QPlaceHolderItem(widget);
1822 qCDebug(lcQpaDockWidgets) << widget <<
"is in destruction. No gap created.";
1823 QLayoutItem *ret = item.widgetItem;
1824 item.widgetItem =
nullptr;
1825 if (item.size != -1)
1826 item.flags |= QDockAreaLayoutItem::KeepSize;
1835void QDockAreaLayoutInfo::add(QWidget *widget)
1838 if (!indexOf(widget).isEmpty())
1841 if (
auto *dockWidget = qobject_cast<QDockWidget *>(widget)) {
1842 item_list.append(QDockAreaLayoutItem(
new QDockWidgetItem(dockWidget)));
1846 if (
auto *groupWindow = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
1847 item_list.append(QDockAreaLayoutItem(
new QDockWidgetGroupWindowItem(groupWindow)));
1851 qFatal(
"Coding error. Add supports only QDockWidget and QDockWidgetGroupWindow");
1854void QDockAreaLayoutInfo::deleteAllLayoutItems()
1856 for (
int i = 0; i < item_list.size(); ++i) {
1857 QDockAreaLayoutItem &item= item_list[i];
1859 item.subinfo->deleteAllLayoutItems();
1861 delete item.widgetItem;
1862 item.widgetItem =
nullptr;
1867void QDockAreaLayoutInfo::saveState(QDataStream &stream)
const
1870 for (qsizetype i = 0; i < item_list.size(); ++i) {
1871 const QDockAreaLayoutItem &item = item_list.at(i);
1872 if (item.widgetItem && qobject_cast<QDockWidgetGroupWindow *>(item.widgetItem->widget())) {
1878#if QT_CONFIG(tabbar)
1880 stream << StateMarkers::Tab;
1883 quintptr id = currentTabId();
1885 for (
int i = 0; i < item_list.size(); ++i) {
1886 if (tabId(item_list.at(i)) == id) {
1895 stream << StateMarkers::Sequence;
1898 stream <<
static_cast<uchar>(o) <<
static_cast<
int>(cnt);
1900 for (
int i = 0; i < item_list.size(); ++i) {
1901 const QDockAreaLayoutItem &item = item_list.at(i);
1902 if (item.widgetItem !=
nullptr) {
1903 QWidget *w = item.widgetItem->widget();
1904 if (qobject_cast<QDockWidgetGroupWindow *>(w)) {
1905 qCDebug(lcQpaDockWidgets) <<
"Ignoring dock widget group window" << w;
1908 stream << StateMarkers::Widget;
1909 QString name = w->objectName();
1910 if (Q_UNLIKELY(name.isEmpty())) {
1911 qWarning() <<
"QMainWindow::saveState(): 'objectName' not set for"
1912 << w << qUtf16Printable(w->windowTitle());
1918 flags.setFlag(StateFlag::Visible);
1920 flags.setFlag(StateFlag::Floating);
1921 if (qobject_cast<QDockWidgetGroupWindow *>(w->parent()))
1922 flags.setFlag(StateFlag::FloatingTabs);
1923 if (
auto *dw = qobject_cast<QDockWidget *>(w)) {
1924 const auto priv =
static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(dw));
1925 flags.setFlag(StateFlag::Closed, priv->closed);
1927 stream <<
static_cast<uchar>(flags.toInt());
1929 qCDebug(lcQpaDockWidgets) <<
"Saving state for dock widget:" << w->objectName() << flags;
1930 if (w->isWindow()) {
1931 const QRect geometry = w->geometry();
1932 stream << geometry.x() << geometry.y() << geometry.width() << geometry.height();
1934 stream << item.pos << item.size << pick(o, item.minimumSize())
1935 << pick(o, item.maximumSize());
1937 }
else if (item.placeHolderItem !=
nullptr) {
1938 stream << StateMarkers::Widget;
1939 stream << item.placeHolderItem->objectName;
1941 if (!item.placeHolderItem->hidden)
1942 flags.setFlag(StateFlag::Visible);
1943 if (item.placeHolderItem->window)
1944 flags.setFlag(StateFlag::Floating);
1945 qCDebug(lcQpaDockWidgets) <<
"Saving state for placeholder item:" << item << flags;
1946 stream <<
static_cast<uchar>(flags.toInt());
1947 if (item.placeHolderItem->window) {
1948 QRect r = item.placeHolderItem->topLevelRect;
1949 stream << r.x() << r.y() << r.width() << r.height();
1951 stream << item.pos << item.size << (
int)0 << (
int)0;
1953 }
else if (item.subinfo !=
nullptr) {
1954 stream << StateMarkers::Sequence;
1955 stream << item.pos << item.size << pick(o, item.minimumSize()) << pick(o, item.maximumSize());
1956 item.subinfo->saveState(stream);
1964 case QInternal::LeftDock:
return Qt::LeftDockWidgetArea;
1965 case QInternal::RightDock:
return Qt::RightDockWidgetArea;
1966 case QInternal::TopDock:
return Qt::TopDockWidgetArea;
1967 case QInternal::BottomDock:
return Qt::BottomDockWidgetArea;
1970 return Qt::NoDockWidgetArea;
1973bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> &widgets,
1974 QInternal::CallMode callMode,
int depth)
1978 constexpr int maxDepth = 100;
1979 if (depth >= maxDepth)
1982 const bool testing = callMode == QInternal::Testing;
1983 const QLatin1StringView debugCallMode = testing ? QLatin1StringView(
"(testing)")
1984 : QLatin1StringView(
"(restoring)");
1985 QMainWindowLayoutState::StateMarkers marker;
1987 if (marker != StateMarkers::Tab && marker != StateMarkers::Sequence)
1990#if QT_CONFIG(tabbar)
1991 tabbed = marker == StateMarkers::Tab;
1999 stream >> orientation;
2000 o =
static_cast<Qt::Orientation>(orientation);
2005 for (
int i = 0; i < cnt; ++i) {
2006 QMainWindowLayoutState::StateMarkers nextMarker;
2007 stream >> nextMarker;
2008 if (nextMarker == StateMarkers::Widget) {
2011 stream >> name >> f;
2012 StateFlags flags(f);
2013 if (name.isEmpty()) {
2015 stream >> dummy >> dummy >> dummy >> dummy;
2019 QDockWidget *widget =
nullptr;
2020 for (qsizetype j = 0; j < widgets.size(); ++j) {
2021 if (widgets.at(j)->objectName() == name) {
2022 widget = widgets.takeAt(j);
2027 if (widget ==
nullptr) {
2028 QPlaceHolderItem *placeHolder =
new QPlaceHolderItem;
2029 QDockAreaLayoutItem item(placeHolder);
2031 placeHolder->window = flags.testFlag(StateFlag::Floating);
2032 placeHolder->hidden = !flags.testFlag(StateFlag::Visible);
2033 if (placeHolder->window) {
2035 stream >> x >> y >> w >> h;
2036 placeHolder->topLevelRect = QRect(x, y, w, h);
2039 stream >> item.pos >> item.size >> dummy >> dummy;
2041 if (item.size != -1)
2042 item.flags |= QDockAreaLayoutItem::KeepSize;
2043 placeHolder->objectName = std::move(name);
2044 qCDebug(lcQpaDockWidgets) <<
"Restoring placeholder" << item << debugCallMode << flags;
2046 item_list.append(item);
2048 if (flags.testFlag(StateFlag::FloatingTabs))
2049 qCDebug(lcQpaDockWidgets) <<
"Found floating tab:" << name << flags << debugCallMode;
2050 QDockAreaLayoutItem item(
new QDockWidgetItem(widget));
2051 if (flags.testFlag(StateFlag::Floating)) {
2054 widget->setFloating(
true);
2058 stream >> x >> y >> w >> h;
2061 widget->setGeometry(QDockAreaLayout::constrainedRect(QRect(x, y, w, h), widget));
2062 widget->setVisible(flags.testFlag(StateFlag::Visible));
2063 item_list.append(item);
2067 stream >> item.pos >> item.size >> dummy >> dummy;
2069 item_list.append(item);
2070 if (flags.testFlag(StateFlag::Closed)) {
2073 widget->setFloating(
false);
2074 widget->setVisible(flags.testFlag(StateFlag::Visible));
2076 emit widget->dockLocationChanged(toDockWidgetArea(dockPos));
2079 qCDebug(lcQpaDockWidgets) <<
"Restoring QDockWidget" << item << flags << debugCallMode;
2082 delete item.widgetItem;
2083 item.widgetItem =
nullptr;
2086 }
else if (nextMarker == StateMarkers::Sequence) {
2088#if !QT_CONFIG(tabbar)
2089 const int tabBarShape = 0;
2091 QDockAreaLayoutItem item(
new QDockAreaLayoutInfo(sep, dockPos, o,
2092 tabBarShape, mainWindow));
2093 stream >> item.pos >> item.size >> dummy >> dummy;
2094 qCDebug(lcQpaDockWidgets) <<
"Restoring separator item" << item << debugCallMode;
2097 item_list.append(item);
2100 QDockAreaLayoutItem &lastItem = testing ? item : item_list.last();
2102 if (!lastItem.subinfo->restoreState(stream, widgets, callMode, depth + 1))
2110#if QT_CONFIG(tabbar)
2111 if (!testing && tabbed && index >= 0 && index < item_list.size()) {
2113 setCurrentTabId(tabId(item_list.at(index)));
2115 if (!testing && *sep == 1)
2116 updateSeparatorWidgets();
2122#if QT_CONFIG(tabbar)
2124static void raiseSeparatorWidget(QWidget *separatorWidget)
2126 Q_ASSERT(separatorWidget);
2128#if QT_CONFIG(toolbar)
2131 Q_ASSERT(separatorWidget->parent());
2132 const auto toolBars = separatorWidget->parent()->findChildren<QToolBar*>(Qt::FindDirectChildrenOnly);
2133 for (
auto *toolBar : toolBars) {
2134 if (
auto *toolBarLayout = qobject_cast<QToolBarLayout*>(toolBar->layout())) {
2135 if (toolBarLayout->expanded) {
2136 separatorWidget->stackUnder(toolBar);
2143 separatorWidget->raise();
2147void QDockAreaLayoutInfo::updateSeparatorWidgets()
const
2150 separatorWidgets.clear();
2155 for (
int i = 0; i < item_list.size(); ++i) {
2156 const QDockAreaLayoutItem &item = item_list.at(i);
2161 int next =
this->next(i);
2162 if ((item.flags & QDockAreaLayoutItem::GapItem)
2163 || (next != -1 && (item_list.at(next).flags & QDockAreaLayoutItem::GapItem)))
2167 item.subinfo->updateSeparatorWidgets();
2174 if (j < separatorWidgets.size()) {
2175 sepWidget = separatorWidgets.at(j);
2177 qWarning(
"QDockAreaLayoutInfo::updateSeparatorWidgets: null separator widget");
2178 sepWidget = mainWindowLayout()->getSeparatorWidget();
2179 separatorWidgets[j] = sepWidget;
2182 sepWidget = mainWindowLayout()->getSeparatorWidget();
2183 separatorWidgets.append(sepWidget);
2187 Q_ASSERT(sepWidget);
2188 raiseSeparatorWidget(sepWidget);
2190 QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
2191 sepWidget->setGeometry(sepRect);
2192 sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
2196 for (
int k = j; k < separatorWidgets.size(); ++k) {
2197 separatorWidgets[k]->hide();
2199 separatorWidgets.resize(j);
2203
2204
2205
2206
2207void QDockAreaLayoutInfo::reparentWidgets(QWidget *parent)
2210 tabBar->setParent(parent);
2212 for (
int i = 0; i < item_list.size(); ++i) {
2213 const QDockAreaLayoutItem &item = item_list.at(i);
2214 if (item.flags & QDockAreaLayoutItem::GapItem)
2217 item.subinfo->reparentWidgets(parent);
2218 if (item.widgetItem) {
2219 QWidget *w = item.widgetItem->widget();
2220 if (qobject_cast<QDockWidgetGroupWindow *>(w))
2222 if (w->parent() != parent) {
2223 bool hidden = w->isHidden();
2224 w->setParent(parent, w->windowFlags());
2233bool QDockAreaLayoutInfo::updateTabBar()
const
2238 QDockAreaLayoutInfo *that =
const_cast<QDockAreaLayoutInfo*>(
this);
2240 if (that->tabBar ==
nullptr) {
2241 that->tabBar = mainWindowLayout()->getTabBar();
2242 that->tabBar->setShape(
static_cast<QTabBar::Shape>(tabBarShape));
2243 that->tabBar->setDrawBase(
true);
2246 const QSignalBlocker blocker(tabBar);
2249 const quintptr oldCurrentId = currentTabId();
2252 for (
int i = 0; i < item_list.size(); ++i) {
2253 const QDockAreaLayoutItem &item = item_list.at(i);
2256 if (item.flags & QDockAreaLayoutItem::GapItem) {
2260 if (item.widgetItem ==
nullptr)
2263 QDockWidget *dw = qobject_cast<QDockWidget*>(item.widgetItem->widget());
2264 QString title = dw->d_func()->fixedWindowTitle;
2265 quintptr id = tabId(item);
2266 const QIcon windowIcon = dw->testAttribute(Qt::WA_SetWindowIcon) ? dw->windowIcon()
2268 if (tab_idx == tabBar->count()) {
2269 tabBar->insertTab(tab_idx, windowIcon, title);
2270#if QT_CONFIG(tooltip)
2271 tabBar->setTabToolTip(tab_idx, title);
2273 tabBar->setTabData(tab_idx, id);
2274 }
else if (qvariant_cast<quintptr>(tabBar->tabData(tab_idx)) != id) {
2275 if (tab_idx + 1 < tabBar->count()
2276 && qvariant_cast<quintptr>(tabBar->tabData(tab_idx + 1)) == id)
2277 tabBar->removeTab(tab_idx);
2279 tabBar->insertTab(tab_idx, windowIcon, title);
2280#if QT_CONFIG(tooltip)
2281 tabBar->setTabToolTip(tab_idx, title);
2283 tabBar->setTabData(tab_idx, id);
2287 if (title != tabBar->tabText(tab_idx)) {
2288 tabBar->setTabText(tab_idx, title);
2289#if QT_CONFIG(tooltip)
2290 tabBar->setTabToolTip(tab_idx, title);
2297 while (tab_idx < tabBar->count()) {
2298 tabBar->removeTab(tab_idx);
2301 if (oldCurrentId > 0 && currentTabId() != oldCurrentId)
2302 that->setCurrentTabId(oldCurrentId);
2304 if (QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(tabBar->parent()))
2305 dwgw->adjustFlags();
2308 return ( (gap ? 1 : 0) + tabBar->count()) > 1;
2311void QDockAreaLayoutInfo::setTabBarShape(
int shape)
2313 if (shape == tabBarShape)
2315 tabBarShape = shape;
2316 if (tabBar !=
nullptr)
2317 tabBar->setShape(
static_cast<QTabBar::Shape>(shape));
2319 for (
int i = 0; i < item_list.size(); ++i) {
2320 QDockAreaLayoutItem &item = item_list[i];
2321 if (item.subinfo !=
nullptr)
2322 item.subinfo->setTabBarShape(shape);
2326QSize QDockAreaLayoutInfo::tabBarMinimumSize()
const
2328 if (!updateTabBar())
2331 return tabBar->minimumSizeHint();
2334QSize QDockAreaLayoutInfo::tabBarSizeHint()
const
2336 if (!updateTabBar())
2339 return tabBar->sizeHint();
2342QSet<QTabBar*> QDockAreaLayoutInfo::usedTabBars()
const
2344 QSet<QTabBar*> result;
2348 result.insert(tabBar);
2351 for (
int i = 0; i < item_list.size(); ++i) {
2352 const QDockAreaLayoutItem &item = item_list.at(i);
2353 if (item.subinfo !=
nullptr)
2354 result += item.subinfo->usedTabBars();
2362QSet<QWidget*> QDockAreaLayoutInfo::usedSeparatorWidgets()
const
2364 QSet<QWidget*> result;
2365 const int numSeparatorWidgets = separatorWidgets.size();
2366 result.reserve(numSeparatorWidgets);
2368 for (
int i = 0; i < numSeparatorWidgets; ++i)
2369 result << separatorWidgets.at(i);
2371 for (
int i = 0; i < item_list.size(); ++i) {
2372 const QDockAreaLayoutItem &item = item_list.at(i);
2373 if (item.subinfo !=
nullptr)
2374 result += item.subinfo->usedSeparatorWidgets();
2380QRect QDockAreaLayoutInfo::tabContentRect()
const
2385 QRect result = rect;
2386 QSize tbh = tabBarSizeHint();
2388 if (!tbh.isNull()) {
2389 switch (tabBarShape) {
2390 case QTabBar::RoundedNorth:
2391 case QTabBar::TriangularNorth:
2392 result.adjust(0, tbh.height(), 0, 0);
2394 case QTabBar::RoundedSouth:
2395 case QTabBar::TriangularSouth:
2396 result.adjust(0, 0, 0, -tbh.height());
2398 case QTabBar::RoundedEast:
2399 case QTabBar::TriangularEast:
2400 result.adjust(0, 0, -tbh.width(), 0);
2402 case QTabBar::RoundedWest:
2403 case QTabBar::TriangularWest:
2404 result.adjust(tbh.width(), 0, 0, 0);
2414int QDockAreaLayoutInfo::tabIndexToListIndex(
int tabIndex)
const
2416 Q_ASSERT(tabbed && tabBar);
2417 quintptr data = qvariant_cast<quintptr>(tabBar->tabData(tabIndex));
2418 for (
int i = 0; i < item_list.size(); ++i) {
2419 if (tabId(item_list.at(i)) == data)
2425void QDockAreaLayoutInfo::moveTab(
int from,
int to)
2427 item_list.move(tabIndexToListIndex(from), tabIndexToListIndex(to));
2432
2433
2435QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : fallbackToSizeHints(
true)
2438 sep = win->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent,
nullptr, win);
2439#if QT_CONFIG(tabbar)
2440 const int tabShape = QTabBar::RoundedSouth;
2442 const int tabShape = 0;
2444 docks[QInternal::LeftDock]
2445 = QDockAreaLayoutInfo(&sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
2446 docks[QInternal::RightDock]
2447 = QDockAreaLayoutInfo(&sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
2448 docks[QInternal::TopDock]
2449 = QDockAreaLayoutInfo(&sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
2450 docks[QInternal::BottomDock]
2451 = QDockAreaLayoutInfo(&sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
2452 centralWidgetItem =
nullptr;
2455 corners[Qt::TopLeftCorner] = Qt::TopDockWidgetArea;
2456 corners[Qt::TopRightCorner] = Qt::TopDockWidgetArea;
2457 corners[Qt::BottomLeftCorner] = Qt::BottomDockWidgetArea;
2458 corners[Qt::BottomRightCorner] = Qt::BottomDockWidgetArea;
2461bool QDockAreaLayout::isValid()
const
2463 return rect.isValid();
2466void QDockAreaLayout::saveState(QDataStream &stream)
const
2468 stream << StateMarkers::DockWidget;
2470 for (
const auto &dock : docks) {
2471 if (!dock.item_list.isEmpty())
2475 for (std::size_t i = 0; i < docks.size(); ++i) {
2476 if (docks[i].item_list.isEmpty())
2478 stream <<
int(i) << docks[i].rect.size();
2479 docks[i].saveState(stream);
2482 stream << centralWidgetRect.size();
2484 for (
const auto &corner : corners)
2485 stream <<
static_cast<
int>(corner);
2488bool QDockAreaLayout::restoreState(QDataStream &stream,
const QList<QDockWidget*> &_dockwidgets, QInternal::CallMode callMode)
2490 QList<QDockWidget*> dockwidgets = _dockwidgets;
2491 const bool testing = callMode == QInternal::Testing;
2494 static const int dockCount =
int(docks.size());
2495 if (cnt < 0 || cnt > dockCount) {
2496 qWarning() <<
"Invalid data stream. Dock count" << cnt <<
"is out of bound. Maximum:" << dockCount;
2497 stream.setStatus(QDataStream::Status::ReadCorruptData);
2500 for (
int i = 0; i < cnt; ++i) {
2503 if (pos < 0 || pos >= dockCount) {
2504 qWarning() <<
"Invalid data stream. Dock position" << pos <<
"is out of bound. Maximum:" << dockCount - 1;
2505 stream.setStatus(QDataStream::Status::ReadCorruptData);
2512 docks[pos].rect = QRect(QPoint(0, 0), size);
2514 if (!docks[pos].restoreState(stream, dockwidgets, callMode)) {
2515 stream.setStatus(QDataStream::ReadCorruptData);
2522 centralWidgetRect = QRect(QPoint(0, 0), size);
2524 bool ok = stream.status() == QDataStream::Ok;
2527 QDockAreaLayoutCorners cornerData;
2528 for (
auto &val : cornerData)
2531 if (stream.status() == QDataStream::Ok)
2532 corners = std::move(cornerData);
2535 fallbackToSizeHints =
false;
2541QList<
int> QDockAreaLayout::indexOfPlaceHolder(
const QString &objectName)
const
2543 for (std::size_t i = 0; i < docks.size(); ++i) {
2544 QList<
int> result = docks[i].indexOfPlaceHolder(objectName);
2545 if (!result.isEmpty()) {
2546 result.prepend(
int(i));
2550 return QList<
int>();
2553QList<
int> QDockAreaLayout::indexOf(
const QWidget *dockWidget)
const
2555 for (std::size_t i = 0; i < docks.size(); ++i) {
2556 QList<
int> result = docks[i].indexOf(dockWidget);
2557 if (!result.isEmpty()) {
2558 result.prepend(
int(i));
2562 return QList<
int>();
2565QList<
int> QDockAreaLayout::gapIndex(
const QPoint &pos,
bool disallowTabs)
const
2567 QMainWindow::DockOptions opts = mainWindow->dockOptions();
2568 bool nestingEnabled = opts & QMainWindow::AllowNestedDocks;
2569 QDockAreaLayoutInfo::TabMode tabMode = QDockAreaLayoutInfo::NoTabs;
2570#if QT_CONFIG(tabbar)
2571 if (!disallowTabs) {
2572 if (opts & QMainWindow::AllowTabbedDocks || opts & QMainWindow::VerticalTabs)
2573 tabMode = QDockAreaLayoutInfo::AllowTabs;
2574 if (opts & QMainWindow::ForceTabbedDocks)
2575 tabMode = QDockAreaLayoutInfo::ForceTabs;
2577 if (tabMode == QDockAreaLayoutInfo::ForceTabs)
2578 nestingEnabled =
false;
2583 for (std::size_t i = 0; i < docks.size(); ++i) {
2584 const QDockAreaLayoutInfo &info = docks[i];
2586 if (!info.isEmpty() && info.rect.contains(pos)) {
2587 QList<
int> result = info.gapIndex(pos, nestingEnabled, tabMode);
2588 if (!result.isEmpty())
2589 result.prepend(
int(i));
2594 for (std::size_t i = 0; i < docks.size(); ++i) {
2595 const QDockAreaLayoutInfo &info = docks[i];
2597 if (info.isEmpty()) {
2598 const QRect r = gapRect(
static_cast<QInternal::DockPosition>(i));
2599 if (r.contains(pos)) {
2600 if (opts & QMainWindow::ForceTabbedDocks && !info.item_list.isEmpty()) {
2603 return {
int(i), -1, 0};
2611 return QList<
int>();
2614QRect QDockAreaLayout::gapRect(QInternal::DockPosition dockPos)
const
2616 Q_ASSERT_X(mainWindow,
"QDockAreaLayout::gapRect",
"Called without valid mainWindow pointer.");
2619 const QSize gapSize = (mainWindow->size()/2).boundedTo(QSize(EmptyDropAreaSize, EmptyDropAreaSize));
2623 if (mainWindow->height() < (2 * sep)) {
2624 qCWarning(lcQpaDockWidgets,
2625 "QDockAreaLayout::gapRect: Main window height %i is too small. Docking will not be possible.",
2626 mainWindow->height());
2629 if (mainWindow->width() < (2 * sep)) {
2630 qCWarning(lcQpaDockWidgets,
2631 "QDockAreaLayout::gapRect: Main window width %i is too small. Docking will not be possible.",
2632 mainWindow->width());
2637 case QInternal::LeftDock:
2638 return QRect(rect.left(), rect.top(), gapSize.width(), rect.height());
2639 case QInternal::RightDock:
2640 return QRect(rect.right() - gapSize.width(), rect.top(), gapSize.width(), rect.height());
2641 case QInternal::TopDock:
2642 return QRect(rect.left(), rect.top(), rect.width(), gapSize.height());
2643 case QInternal::BottomDock:
2644 return QRect(rect.left(), rect.bottom() - gapSize.height(), rect.width(), gapSize.height());
2645 case QInternal::DockCount:
2651QList<
int> QDockAreaLayout::findSeparator(
const QPoint &pos)
const
2654 for (std::size_t i = 0; i < docks.size(); ++i) {
2655 const QDockAreaLayoutInfo &info = docks[i];
2658 QRect rect = separatorRect(
int(i));
2659 if (!rect.isNull() && sep == 1)
2660 rect.adjust(-2, -2, 2, 2);
2661 if (rect.contains(pos) && !info.hasFixedSize()) {
2664 }
else if (info.rect.contains(pos)) {
2665 result = docks[i].findSeparator(pos);
2666 if (!result.isEmpty()) {
2667 result.prepend(
int(i));
2676QDockAreaLayoutInfo *QDockAreaLayout::info(QWidget *widget)
2678 for (
auto &dock : docks) {
2679 if (QDockAreaLayoutInfo *result = dock.info(widget))
2686QDockAreaLayoutInfo *QDockAreaLayout::info(
const QList<
int> &path)
2688 Q_ASSERT(!path.isEmpty());
2689 const int index = path.first();
2690 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2692 if (path.size() == 1)
2693 return &docks[index];
2695 return docks[index].info(path.mid(1));
2698const QDockAreaLayoutInfo *QDockAreaLayout::info(
const QList<
int> &path)
const
2700 return const_cast<QDockAreaLayout*>(
this)->info(path);
2703QDockAreaLayoutItem &QDockAreaLayout::item(
const QList<
int> &path)
2705 Q_ASSERT(!path.isEmpty());
2706 const int index = path.first();
2707 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2708 return docks[index].item(path.mid(1));
2711QRect QDockAreaLayout::itemRect(
const QList<
int> &path)
const
2713 Q_ASSERT(!path.isEmpty());
2714 const int index = path.first();
2715 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2716 return docks[index].itemRect(path.mid(1));
2719QRect QDockAreaLayout::separatorRect(
int index)
const
2721 const QDockAreaLayoutInfo &dock = docks[index];
2724 QRect r = dock.rect;
2726 case QInternal::LeftDock:
2727 return QRect(r.right() + 1, r.top(), sep, r.height());
2728 case QInternal::RightDock:
2729 return QRect(r.left() - sep, r.top(), sep, r.height());
2730 case QInternal::TopDock:
2731 return QRect(r.left(), r.bottom() + 1, r.width(), sep);
2732 case QInternal::BottomDock:
2733 return QRect(r.left(), r.top() - sep, r.width(), sep);
2740QRect QDockAreaLayout::separatorRect(
const QList<
int> &path)
const
2742 Q_ASSERT(!path.isEmpty());
2744 const int index = path.first();
2745 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2747 if (path.size() == 1)
2748 return separatorRect(index);
2750 return docks[index].separatorRect(path.mid(1));
2753bool QDockAreaLayout::insertGap(
const QList<
int> &path, QLayoutItem *dockWidgetItem)
2755 Q_ASSERT(!path.isEmpty());
2756 const int index = path.first();
2757 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2758 return docks[index].insertGap(path.mid(1), dockWidgetItem);
2761QLayoutItem *QDockAreaLayout::plug(
const QList<
int> &path)
2763#if QT_CONFIG(tabbar)
2764 Q_ASSERT(!path.isEmpty());
2765 const int index = path.first();
2766 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2767 QLayoutItem *item = docks[index].plug(path.mid(1));
2768 docks[index].reparentWidgets(mainWindow);
2775QLayoutItem *QDockAreaLayout::unplug(
const QList<
int> &path)
2777 Q_ASSERT(!path.isEmpty());
2778 const int index = path.first();
2779 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2780 return docks[index].unplug(path.mid(1));
2783void QDockAreaLayout::remove(
const QList<
int> &path)
2785 Q_ASSERT(!path.isEmpty());
2786 const int index = path.first();
2787 Q_ASSERT(index >= 0 && index <
int(docks.size()));
2788 docks[index].remove(path.mid(1));
2791void QDockAreaLayout::removePlaceHolder(
const QString &name)
2793 QList<
int> index = indexOfPlaceHolder(name);
2794 if (!index.isEmpty())
2797 mainWindow->findChildren<QDockWidgetGroupWindow *>(Qt::FindDirectChildrenOnly);
2798 for (QDockWidgetGroupWindow *dwgw : groups) {
2799 index = dwgw->layoutInfo()->indexOfPlaceHolder(name);
2800 if (!index.isEmpty()) {
2801 dwgw->layoutInfo()->remove(index);
2802 dwgw->destroyOrHideIfEmpty();
2807static inline int qMax(
int i1,
int i2,
int i3) {
return qMax(i1, qMax(i2, i3)); }
2809void QDockAreaLayout::getGrid(QList<QLayoutStruct> *_ver_struct_list,
2810 QList<QLayoutStruct> *_hor_struct_list)
2812 QSize center_hint(0, 0);
2813 QSize center_min(0, 0);
2814 QSize center_max(0, 0);
2815 const bool have_central = centralWidgetItem !=
nullptr && !centralWidgetItem->isEmpty();
2817 center_hint = centralWidgetRect.size();
2818 if (!center_hint.isValid())
2819 center_hint = centralWidgetItem->sizeHint();
2820 center_min = centralWidgetItem->minimumSize();
2821 center_max = centralWidgetItem->maximumSize();
2824 QRect center_rect = rect;
2825 if (!docks[QInternal::LeftDock].isEmpty())
2826 center_rect.setLeft(rect.left() + docks[QInternal::LeftDock].rect.width() + sep);
2827 if (!docks[QInternal::TopDock].isEmpty())
2828 center_rect.setTop(rect.top() + docks[QInternal::TopDock].rect.height() + sep);
2829 if (!docks[QInternal::RightDock].isEmpty())
2830 center_rect.setRight(rect.right() - docks[QInternal::RightDock].rect.width() - sep);
2831 if (!docks[QInternal::BottomDock].isEmpty())
2832 center_rect.setBottom(rect.bottom() - docks[QInternal::BottomDock].rect.height() - sep);
2834 QSize left_hint = docks[QInternal::LeftDock].size();
2835 if (left_hint.isNull() || fallbackToSizeHints)
2836 left_hint = docks[QInternal::LeftDock].sizeHint();
2837 QSize left_min = docks[QInternal::LeftDock].minimumSize();
2838 QSize left_max = docks[QInternal::LeftDock].maximumSize();
2839 left_hint = left_hint.boundedTo(left_max).expandedTo(left_min);
2841 QSize right_hint = docks[QInternal::RightDock].size();
2842 if (right_hint.isNull() || fallbackToSizeHints)
2843 right_hint = docks[QInternal::RightDock].sizeHint();
2844 QSize right_min = docks[QInternal::RightDock].minimumSize();
2845 QSize right_max = docks[QInternal::RightDock].maximumSize();
2846 right_hint = right_hint.boundedTo(right_max).expandedTo(right_min);
2848 QSize top_hint = docks[QInternal::TopDock].size();
2849 if (top_hint.isNull() || fallbackToSizeHints)
2850 top_hint = docks[QInternal::TopDock].sizeHint();
2851 QSize top_min = docks[QInternal::TopDock].minimumSize();
2852 QSize top_max = docks[QInternal::TopDock].maximumSize();
2853 top_hint = top_hint.boundedTo(top_max).expandedTo(top_min);
2855 QSize bottom_hint = docks[QInternal::BottomDock].size();
2856 if (bottom_hint.isNull() || fallbackToSizeHints)
2857 bottom_hint = docks[QInternal::BottomDock].sizeHint();
2858 QSize bottom_min = docks[QInternal::BottomDock].minimumSize();
2859 QSize bottom_max = docks[QInternal::BottomDock].maximumSize();
2860 bottom_hint = bottom_hint.boundedTo(bottom_max).expandedTo(bottom_min);
2862 if (_ver_struct_list !=
nullptr) {
2863 QList<QLayoutStruct> &ver_struct_list = *_ver_struct_list;
2864 ver_struct_list.resize(3);
2867 ver_struct_list[0].init();
2868 ver_struct_list[0].stretch = 0;
2869 ver_struct_list[0].sizeHint = top_hint.height();
2870 ver_struct_list[0].minimumSize = top_min.height();
2871 ver_struct_list[0].maximumSize = top_max.height();
2872 ver_struct_list[0].expansive =
false;
2873 ver_struct_list[0].empty = docks[QInternal::TopDock].isEmpty();
2874 ver_struct_list[0].pos = docks[QInternal::TopDock].rect.top();
2875 ver_struct_list[0].size = docks[QInternal::TopDock].rect.height();
2878 ver_struct_list[1].init();
2879 ver_struct_list[1].stretch = center_hint.height();
2881 bool tl_significant = corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
2882 || docks[QInternal::TopDock].isEmpty();
2883 bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
2884 || docks[QInternal::BottomDock].isEmpty();
2885 bool tr_significant = corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
2886 || docks[QInternal::TopDock].isEmpty();
2887 bool br_significant = corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
2888 || docks[QInternal::BottomDock].isEmpty();
2890 int left = (tl_significant && bl_significant) ? left_hint.height() : 0;
2891 int right = (tr_significant && br_significant) ? right_hint.height() : 0;
2892 ver_struct_list[1].sizeHint = qMax(left, center_hint.height(), right);
2894 left = (tl_significant && bl_significant) ? left_min.height() : 0;
2895 right = (tr_significant && br_significant) ? right_min.height() : 0;
2896 ver_struct_list[1].minimumSize = qMax(left, center_min.height(), right);
2897 ver_struct_list[1].maximumSize = center_max.height();
2898 ver_struct_list[1].expansive = have_central;
2899 ver_struct_list[1].empty = docks[QInternal::LeftDock].isEmpty()
2901 && docks[QInternal::RightDock].isEmpty();
2902 ver_struct_list[1].pos = center_rect.top();
2903 ver_struct_list[1].size = center_rect.height();
2906 ver_struct_list[2].init();
2907 ver_struct_list[2].stretch = 0;
2908 ver_struct_list[2].sizeHint = bottom_hint.height();
2909 ver_struct_list[2].minimumSize = bottom_min.height();
2910 ver_struct_list[2].maximumSize = bottom_max.height();
2911 ver_struct_list[2].expansive =
false;
2912 ver_struct_list[2].empty = docks[QInternal::BottomDock].isEmpty();
2913 ver_struct_list[2].pos = docks[QInternal::BottomDock].rect.top();
2914 ver_struct_list[2].size = docks[QInternal::BottomDock].rect.height();
2916 for (
int i = 0; i < 3; ++i) {
2917 ver_struct_list[i].sizeHint
2918 = qMax(ver_struct_list[i].sizeHint, ver_struct_list[i].minimumSize);
2920 if (have_central && ver_struct_list[0].empty && ver_struct_list[2].empty)
2921 ver_struct_list[1].maximumSize = QWIDGETSIZE_MAX;
2924 if (_hor_struct_list !=
nullptr) {
2925 QList<QLayoutStruct> &hor_struct_list = *_hor_struct_list;
2926 hor_struct_list.resize(3);
2929 hor_struct_list[0].init();
2930 hor_struct_list[0].stretch = 0;
2931 hor_struct_list[0].sizeHint = left_hint.width();
2932 hor_struct_list[0].minimumSize = left_min.width();
2933 hor_struct_list[0].maximumSize = left_max.width();
2934 hor_struct_list[0].expansive =
false;
2935 hor_struct_list[0].empty = docks[QInternal::LeftDock].isEmpty();
2936 hor_struct_list[0].pos = docks[QInternal::LeftDock].rect.left();
2937 hor_struct_list[0].size = docks[QInternal::LeftDock].rect.width();
2940 hor_struct_list[1].init();
2941 hor_struct_list[1].stretch = center_hint.width();
2943 bool tl_significant = corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
2944 || docks[QInternal::LeftDock].isEmpty();
2945 bool tr_significant = corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
2946 || docks[QInternal::RightDock].isEmpty();
2947 bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
2948 || docks[QInternal::LeftDock].isEmpty();
2949 bool br_significant = corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
2950 || docks[QInternal::RightDock].isEmpty();
2952 int top = (tl_significant && tr_significant) ? top_hint.width() : 0;
2953 int bottom = (bl_significant && br_significant) ? bottom_hint.width() : 0;
2954 hor_struct_list[1].sizeHint = qMax(top, center_hint.width(), bottom);
2956 top = (tl_significant && tr_significant) ? top_min.width() : 0;
2957 bottom = (bl_significant && br_significant) ? bottom_min.width() : 0;
2958 hor_struct_list[1].minimumSize = qMax(top, center_min.width(), bottom);
2960 hor_struct_list[1].maximumSize = center_max.width();
2961 hor_struct_list[1].expansive = have_central;
2962 hor_struct_list[1].empty = !have_central;
2963 hor_struct_list[1].pos = center_rect.left();
2964 hor_struct_list[1].size = center_rect.width();
2967 hor_struct_list[2].init();
2968 hor_struct_list[2].stretch = 0;
2969 hor_struct_list[2].sizeHint = right_hint.width();
2970 hor_struct_list[2].minimumSize = right_min.width();
2971 hor_struct_list[2].maximumSize = right_max.width();
2972 hor_struct_list[2].expansive =
false;
2973 hor_struct_list[2].empty = docks[QInternal::RightDock].isEmpty();
2974 hor_struct_list[2].pos = docks[QInternal::RightDock].rect.left();
2975 hor_struct_list[2].size = docks[QInternal::RightDock].rect.width();
2977 for (
int i = 0; i < 3; ++i) {
2978 hor_struct_list[i].sizeHint
2979 = qMax(hor_struct_list[i].sizeHint, hor_struct_list[i].minimumSize);
2981 if (have_central && hor_struct_list[0].empty && hor_struct_list[2].empty)
2982 hor_struct_list[1].maximumSize = QWIDGETSIZE_MAX;
2987void QDockAreaLayout::setGrid(QList<QLayoutStruct> *ver_struct_list,
2988 QList<QLayoutStruct> *hor_struct_list)
2993 if (!docks[QInternal::TopDock].isEmpty()) {
2994 QRect r = docks[QInternal::TopDock].rect;
2995 if (hor_struct_list !=
nullptr) {
2996 r.setLeft(corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
2997 || docks[QInternal::LeftDock].isEmpty()
2998 ? rect.left() : hor_struct_list->at(1).pos);
2999 r.setRight(corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
3000 || docks[QInternal::RightDock].isEmpty()
3001 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
3003 if (ver_struct_list !=
nullptr) {
3004 r.setTop(rect.top());
3005 r.setBottom(ver_struct_list->at(1).pos - sep - 1);
3007 docks[QInternal::TopDock].rect = r;
3008 docks[QInternal::TopDock].fitItems();
3013 if (!docks[QInternal::BottomDock].isEmpty()) {
3014 QRect r = docks[QInternal::BottomDock].rect;
3015 if (hor_struct_list !=
nullptr) {
3016 r.setLeft(corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
3017 || docks[QInternal::LeftDock].isEmpty()
3018 ? rect.left() : hor_struct_list->at(1).pos);
3019 r.setRight(corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
3020 || docks[QInternal::RightDock].isEmpty()
3021 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
3023 if (ver_struct_list !=
nullptr) {
3024 r.setTop(ver_struct_list->at(2).pos);
3025 r.setBottom(rect.bottom());
3027 docks[QInternal::BottomDock].rect = r;
3028 docks[QInternal::BottomDock].fitItems();
3033 if (!docks[QInternal::LeftDock].isEmpty()) {
3034 QRect r = docks[QInternal::LeftDock].rect;
3035 if (hor_struct_list !=
nullptr) {
3036 r.setLeft(rect.left());
3037 r.setRight(hor_struct_list->at(1).pos - sep - 1);
3039 if (ver_struct_list !=
nullptr) {
3040 r.setTop(corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
3041 || docks[QInternal::TopDock].isEmpty()
3042 ? rect.top() : ver_struct_list->at(1).pos);
3043 r.setBottom(corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
3044 || docks[QInternal::BottomDock].isEmpty()
3045 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
3047 docks[QInternal::LeftDock].rect = r;
3048 docks[QInternal::LeftDock].fitItems();
3053 if (!docks[QInternal::RightDock].isEmpty()) {
3054 QRect r = docks[QInternal::RightDock].rect;
3055 if (hor_struct_list !=
nullptr) {
3056 r.setLeft(hor_struct_list->at(2).pos);
3057 r.setRight(rect.right());
3059 if (ver_struct_list !=
nullptr) {
3060 r.setTop(corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
3061 || docks[QInternal::TopDock].isEmpty()
3062 ? rect.top() : ver_struct_list->at(1).pos);
3063 r.setBottom(corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
3064 || docks[QInternal::BottomDock].isEmpty()
3065 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
3067 docks[QInternal::RightDock].rect = r;
3068 docks[QInternal::RightDock].fitItems();
3073 if (hor_struct_list !=
nullptr) {
3074 centralWidgetRect.setLeft(hor_struct_list->at(1).pos);
3075 centralWidgetRect.setWidth(hor_struct_list->at(1).size);
3077 if (ver_struct_list !=
nullptr) {
3078 centralWidgetRect.setTop(ver_struct_list->at(1).pos);
3079 centralWidgetRect.setHeight(ver_struct_list->at(1).size);
3083void QDockAreaLayout::fitLayout()
3085 QList<QLayoutStruct> ver_struct_list(3);
3086 QList<QLayoutStruct> hor_struct_list(3);
3087 getGrid(&ver_struct_list, &hor_struct_list);
3089 qGeomCalc(ver_struct_list, 0, 3, rect.top(), rect.height(), sep);
3090 qGeomCalc(hor_struct_list, 0, 3, rect.left(), rect.width(), sep);
3092 setGrid(&ver_struct_list, &hor_struct_list);
3095void QDockAreaLayout::clear()
3097 for (
auto &dock : docks)
3101 centralWidgetRect = QRect();
3104template<
typename SizePMF,
typename CenterPMF>
3105QSize QDockAreaLayout::size_helper(SizePMF sizeFn, CenterPMF centerFn)
const
3112 if (centralWidgetItem !=
nullptr) {
3113 left_sep = docks[QInternal::LeftDock].isEmpty() ? 0 : sep;
3114 right_sep = docks[QInternal::RightDock].isEmpty() ? 0 : sep;
3115 top_sep = docks[QInternal::TopDock].isEmpty() ? 0 : sep;
3116 bottom_sep = docks[QInternal::BottomDock].isEmpty() ? 0 : sep;
3119 const QSize left = (docks[QInternal::LeftDock].*sizeFn)() + QSize(left_sep, 0);
3120 const QSize right = (docks[QInternal::RightDock].*sizeFn)() + QSize(right_sep, 0);
3121 const QSize top = (docks[QInternal::TopDock].*sizeFn)() + QSize(0, top_sep);
3122 const QSize bottom = (docks[QInternal::BottomDock].*sizeFn)() + QSize(0, bottom_sep);
3123 const QSize center = centralWidgetItem ==
nullptr
3124 ? QSize(0, 0) : (centralWidgetItem->*centerFn)();
3126 int row1 = top.width();
3127 int row2 = left.width() + center.width() + right.width();
3128 int row3 = bottom.width();
3129 int col1 = left.height();
3130 int col2 = top.height() + center.height() + bottom.height();
3131 int col3 = right.height();
3133 if (corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea)
3134 row1 += left.width();
3136 col1 += top.height();
3138 if (corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea)
3139 row1 += right.width();
3141 col3 += top.height();
3143 if (corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea)
3144 row3 += left.width();
3146 col1 += bottom.height();
3148 if (corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea)
3149 row3 += right.width();
3151 col3 += bottom.height();
3153 return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
3156QSize QDockAreaLayout::sizeHint()
const
3158 return size_helper(&QDockAreaLayoutInfo::sizeHint, &QLayoutItem::sizeHint);
3161QSize QDockAreaLayout::minimumSize()
const
3163 return size_helper(&QDockAreaLayoutInfo::minimumSize, &QLayoutItem::minimumSize);
3167
3168
3169
3170
3171QSize QDockAreaLayout::minimumStableSize()
const
3173 return size_helper(&QDockAreaLayoutInfo::size, &QLayoutItem::minimumSize);
3177
3178
3179
3180
3181
3182QRect QDockAreaLayout::constrainedRect(QRect rect, QWidget* widget)
3184 QScreen *screen =
nullptr;
3185 if (QGuiApplication::primaryScreen()->virtualSiblings().size() > 1)
3186 screen = QGuiApplication::screenAt(rect.topLeft());
3188 screen = widget->screen();
3190 const QRect screenRect = screen->geometry();
3191 if (screenRect.isValid()) {
3192 rect.setWidth(qMin(rect.width(), screenRect.width()));
3193 rect.setHeight(qMin(rect.height(), screenRect.height()));
3194 rect.moveLeft(qMax(rect.left(), screenRect.left()));
3195 rect.moveTop(qMax(rect.top(), screenRect.top()));
3196 rect.moveRight(qMin(rect.right(), screenRect.right()));
3197 rect.moveBottom(qMin(rect.bottom(), screenRect.bottom()));
3203bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
3205 QDockAreaLayoutItem *item =
nullptr;
3207 mainWindow->findChildren<QDockWidgetGroupWindow *>(Qt::FindDirectChildrenOnly);
3208 for (QDockWidgetGroupWindow *dwgw : groups) {
3209 QList<
int> index = dwgw->layoutInfo()->indexOfPlaceHolder(dockWidget->objectName());
3210 if (!index.isEmpty()) {
3211 dockWidget->setParent(dwgw);
3212 item =
const_cast<QDockAreaLayoutItem *>(&dwgw->layoutInfo()->item(index));
3217 QList<
int> index = indexOfPlaceHolder(dockWidget->objectName());
3218 if (index.isEmpty())
3220 item =
const_cast<QDockAreaLayoutItem *>(&
this->item(index));
3223 QPlaceHolderItem *placeHolder = item->placeHolderItem;
3224 Q_ASSERT(placeHolder !=
nullptr);
3226 item->widgetItem =
new QDockWidgetItem(dockWidget);
3228 if (placeHolder->window) {
3229 const QRect r = constrainedRect(placeHolder->topLevelRect, dockWidget);
3230 dockWidget->d_func()->setWindowState(QDockWidgetPrivate::WindowStates(
3231 {QDockWidgetPrivate::WindowState::Floating,
3232 QDockWidgetPrivate::WindowState::Unplug}), r);
3234 dockWidget->setVisible(!placeHolder->hidden);
3236 item->placeHolderItem =
nullptr;
3242void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *dockWidget,
3243 Qt::Orientation orientation)
3245 QLayoutItem *dockWidgetItem =
new QDockWidgetItem(dockWidget);
3246 Q_ASSERT(size_t(pos) < docks.size());
3247 QDockAreaLayoutInfo &info = docks[pos];
3248 if (orientation == info.o || info.item_list.size() <= 1) {
3251 info.o = orientation;
3253 QDockAreaLayoutItem new_item(dockWidgetItem);
3254 info.item_list.append(new_item);
3255#if QT_CONFIG(tabbar)
3256 if (info.tabbed && !new_item.skip()) {
3257 info.updateTabBar();
3258 info.setCurrentTabId(tabId(new_item));
3262#if QT_CONFIG(tabbar)
3263 int tbshape = info.tabBarShape;
3267 QDockAreaLayoutInfo new_info(&sep, pos, orientation, tbshape, mainWindow);
3268 new_info.item_list.append(QDockAreaLayoutItem(
new QDockAreaLayoutInfo(info)));
3269 new_info.item_list.append(QDockAreaLayoutItem(dockWidgetItem));
3273 removePlaceHolder(dockWidget->objectName());
3276#if QT_CONFIG(tabbar)
3277void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
3279 const QList<
int> path = indexOf(first);
3283 QDockAreaLayoutInfo *info =
this->info(path);
3284 Q_ASSERT(info !=
nullptr);
3285 info->tab(path.last(),
new QDockWidgetItem(second));
3287 removePlaceHolder(second->objectName());
3291void QDockAreaLayout::resizeDocks(
const QList<QDockWidget *> &docks,
3292 const QList<
int> &sizes, Qt::Orientation o)
3294 if (Q_UNLIKELY(docks.size() != sizes.size())) {
3295 qWarning(
"QMainWidget::resizeDocks: size of the lists are not the same");
3298 const int count = docks.size();
3299 fallbackToSizeHints =
false;
3300 for (
int i = 0; i < count; ++i) {
3301 QList<
int> path = indexOf(docks[i]);
3302 if (Q_UNLIKELY(path.isEmpty())) {
3303 qWarning(
"QMainWidget::resizeDocks: one QDockWidget is not part of the layout");
3306 int size = sizes[i];
3307 if (Q_UNLIKELY(size <= 0)) {
3308 qWarning(
"QMainWidget::resizeDocks: all sizes need to be larger than 0");
3312 while (path.size() > 1) {
3313 QDockAreaLayoutInfo *info =
this->info(path);
3314#if QT_CONFIG(tabbar)
3315 if (!info->tabbed && info->o == o) {
3316 info->item_list[path.constLast()].size = size;
3318 for (
const QDockAreaLayoutItem &item : std::as_const(info->item_list)) {
3322 totalSize += item.size == -1 ? pick(o, item.sizeHint()) : item.size;
3331 const int dockNum = path.constFirst();
3332 Q_ASSERT(std::size_t(dockNum) <
this->docks.size());
3333 QRect &r =
this->docks[dockNum].rect;
3340void QDockAreaLayout::splitDockWidget(QDockWidget *after,
3341 QDockWidget *dockWidget,
3342 Qt::Orientation orientation)
3344 const QList<
int> path = indexOf(after);
3348 QDockAreaLayoutInfo *info =
this->info(path);
3349 Q_ASSERT(info !=
nullptr);
3350 info->split(path.last(), orientation,
new QDockWidgetItem(dockWidget));
3352 removePlaceHolder(dockWidget->objectName());
3355void QDockAreaLayout::apply(QWidgetAnimator::AnimationRule rule)
3357 QWidgetAnimator &widgetAnimator = qt_mainwindow_layout(mainWindow)->widgetAnimator;
3359 for (
auto &dock : docks)
3361 if (centralWidgetItem !=
nullptr && !centralWidgetItem->isEmpty()) {
3362 widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect,
3365#if QT_CONFIG(tabbar)
3367 updateSeparatorWidgets();
3371void QDockAreaLayout::paintSeparators(QPainter *p, QWidget *widget,
3372 const QRegion &clip,
3373 const QPoint &mouse)
const
3375 for (
int i = 0; i < QInternal::DockCount; ++i) {
3376 const QDockAreaLayoutInfo &dock = docks[i];
3379 QRect r = separatorRect(i);
3380 if (clip.contains(r) && !dock.hasFixedSize()) {
3381 Qt::Orientation opposite = dock.o == Qt::Horizontal
3382 ? Qt::Vertical : Qt::Horizontal;
3383 paintSep(p, widget, r, opposite, r.contains(mouse));
3385 if (clip.contains(dock.rect))
3386 dock.paintSeparators(p, widget, clip, mouse);
3390QRegion QDockAreaLayout::separatorRegion()
const
3394 for (
int i = 0; i < QInternal::DockCount; ++i) {
3395 const QDockAreaLayoutInfo &dock = docks[i];
3398 result |= separatorRect(i);
3399 result |= dock.separatorRegion();
3405int QDockAreaLayout::separatorMove(
const QList<
int> &separator,
const QPoint &origin,
3409 const auto dockPosition =
static_cast<QInternal::DockPosition>(separator.last());
3410 const bool isHorizontal =
3411 dockPosition == QInternal::LeftDock || dockPosition == QInternal::RightDock;
3412 const bool isLeftOrTop = dockPosition == QInternal::LeftDock || dockPosition == QInternal::TopDock;
3413 const bool separatorIsWithinDock = separator.size() > 1;
3415 if (separatorIsWithinDock) {
3419 QDockAreaLayoutInfo *info =
this->info(separator);
3420 delta = pick(info->o, dest - origin);
3422 delta = info->separatorMove(dockPosition, delta);
3423 info->apply(QWidgetAnimator::AnimationRule::Stop);
3433 QList<QLayoutStruct> list;
3436 getGrid(
nullptr, &list);
3438 getGrid(&list,
nullptr);
3440 const int sep_index = isLeftOrTop ? 0 : 1;
3441 const Qt::Orientation o = isHorizontal ? Qt::Horizontal : Qt::Vertical;
3443 delta = pick(o, dest - origin);
3444 delta = separatorMoveHelper(list, sep_index, delta, sep);
3446 fallbackToSizeHints =
false;
3449 setGrid(
nullptr, &list);
3451 setGrid(&list,
nullptr);
3453 apply(QWidgetAnimator::AnimationRule::Stop);
3458int QDockAreaLayoutInfo::separatorMove(
const QList<
int> &separator,
const QPoint &origin,
3462 int index = separator.last();
3463 QDockAreaLayoutInfo *info =
this->info(separator);
3464 delta = pick(info->o, dest - origin);
3466 delta = info->separatorMove(index, delta);
3467 info->apply(QWidgetAnimator::AnimationRule::Stop);
3471#if QT_CONFIG(tabbar)
3474void QDockAreaLayout::updateSeparatorWidgets()
const
3478 for (
int i = 0; i < QInternal::DockCount; ++i) {
3479 const QDockAreaLayoutInfo &dock = docks[i];
3484 if (j < separatorWidgets.size()) {
3485 sepWidget = separatorWidgets.at(j);
3487 qWarning(
"QDockAreaLayout::updateSeparatorWidgets: null separator widget");
3488 sepWidget = qt_mainwindow_layout(mainWindow)->getSeparatorWidget();
3489 separatorWidgets[j] = sepWidget;
3492 sepWidget = qt_mainwindow_layout(mainWindow)->getSeparatorWidget();
3493 separatorWidgets.append(sepWidget);
3497 Q_ASSERT(sepWidget);
3498 raiseSeparatorWidget(sepWidget);
3500 QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
3501 sepWidget->setGeometry(sepRect);
3502 sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
3505 for (
int i = j; i < separatorWidgets.size(); ++i)
3506 separatorWidgets.at(i)->hide();
3508 separatorWidgets.resize(j);
3512QLayoutItem *QDockAreaLayout::itemAt(
int *x,
int index)
const
3514 Q_ASSERT(x !=
nullptr);
3516 for (
const auto &dock : docks) {
3517 if (QLayoutItem *ret = dock.itemAt(x, index))
3521 if (centralWidgetItem && (*x)++ == index)
3522 return centralWidgetItem;
3527QLayoutItem *QDockAreaLayout::takeAt(
int *x,
int index)
3529 Q_ASSERT(x !=
nullptr);
3531 for (
auto &dock : docks) {
3532 if (QLayoutItem *ret = dock.takeAt(x, index))
3536 if (centralWidgetItem && (*x)++ == index) {
3537 QLayoutItem *ret = centralWidgetItem;
3538 centralWidgetItem =
nullptr;
3545void QDockAreaLayout::deleteAllLayoutItems()
3547 for (
auto &dock : docks)
3548 dock.deleteAllLayoutItems();
3551#if QT_CONFIG(tabbar)
3552QSet<QTabBar*> QDockAreaLayout::usedTabBars()
const
3554 QSet<QTabBar*> result;
3555 for (
const auto &dock : docks)
3556 result += dock.usedTabBars();
3561QSet<QWidget*> QDockAreaLayout::usedSeparatorWidgets()
const
3563 QSet<QWidget*> result;
3564 const int numSeparators = separatorWidgets.size();
3565 result.reserve(numSeparators);
3566 for (
int i = 0; i < numSeparators; ++i)
3567 result << separatorWidgets.at(i);
3568 for (
const auto &dock : docks)
3569 result += dock.usedSeparatorWidgets();
3574QRect QDockAreaLayout::gapRect(
const QList<
int> &path)
const
3576 const QDockAreaLayoutInfo *info =
this->info(path);
3577 if (info ==
nullptr)
3579 int index = path.last();
3580 if (index < 0 || index >= info->item_list.size())
3582 return info->itemRect(index,
true);
3585void QDockAreaLayout::keepSize(QDockWidget *w)
3587 QList<
int> path = indexOf(w);
3590 QDockAreaLayoutItem &item =
this->item(path);
3591 if (item.size != -1)
3592 item.flags |= QDockAreaLayoutItem::KeepSize;
3595void QDockAreaLayout::styleChangedEvent()
3597 sep = mainWindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent,
nullptr, mainWindow);
Combined button and popup list for selecting options.
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)
Q_DECLARE_FLAGS(StateFlags, StateFlag)
static int separatorMoveHelper(QList< QLayoutStruct > &list, int index, int delta, int sep)
static QInternal::DockPosition dockPosHelper(const QRect &rect, const QPoint &_pos, Qt::Orientation o, bool nestingEnabled, QDockAreaLayoutInfo::TabMode tabMode)
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)