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 flags.setFlag(StateFlag::Closed, !dw->toggleViewAction()->isChecked());
1925 stream <<
static_cast<uchar>(flags.toInt());
1927 qCDebug(lcQpaDockWidgets) <<
"Saving state for dock widget:" << w->objectName() << flags;
1928 if (w->isWindow()) {
1929 const QRect geometry = w->geometry();
1930 stream << geometry.x() << geometry.y() << geometry.width() << geometry.height();
1932 stream << item.pos << item.size << pick(o, item.minimumSize())
1933 << pick(o, item.maximumSize());
1935 }
else if (item.placeHolderItem !=
nullptr) {
1936 stream << StateMarkers::Widget;
1937 stream << item.placeHolderItem->objectName;
1939 if (!item.placeHolderItem->hidden)
1940 flags.setFlag(StateFlag::Visible);
1941 if (item.placeHolderItem->window)
1942 flags.setFlag(StateFlag::Floating);
1943 qCDebug(lcQpaDockWidgets) <<
"Saving state for placeholder item:" << item << flags;
1944 stream <<
static_cast<uchar>(flags.toInt());
1945 if (item.placeHolderItem->window) {
1946 QRect r = item.placeHolderItem->topLevelRect;
1947 stream << r.x() << r.y() << r.width() << r.height();
1949 stream << item.pos << item.size << (
int)0 << (
int)0;
1951 }
else if (item.subinfo !=
nullptr) {
1952 stream << StateMarkers::Sequence;
1953 stream << item.pos << item.size << pick(o, item.minimumSize()) << pick(o, item.maximumSize());
1954 item.subinfo->saveState(stream);
1962 case QInternal::LeftDock:
return Qt::LeftDockWidgetArea;
1963 case QInternal::RightDock:
return Qt::RightDockWidgetArea;
1964 case QInternal::TopDock:
return Qt::TopDockWidgetArea;
1965 case QInternal::BottomDock:
return Qt::BottomDockWidgetArea;
1968 return Qt::NoDockWidgetArea;
1971bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> &widgets, QInternal::CallMode callMode)
1973 const bool testing = callMode == QInternal::Testing;
1974 const QLatin1StringView debugCallMode = testing ? QLatin1StringView(
"(testing)")
1975 : QLatin1StringView(
"(restoring)");
1976 QMainWindowLayoutState::StateMarkers marker;
1978 if (marker != StateMarkers::Tab && marker != StateMarkers::Sequence)
1981#if QT_CONFIG(tabbar)
1982 tabbed = marker == StateMarkers::Tab;
1990 stream >> orientation;
1991 o =
static_cast<Qt::Orientation>(orientation);
1996 for (
int i = 0; i < cnt; ++i) {
1997 QMainWindowLayoutState::StateMarkers nextMarker;
1998 stream >> nextMarker;
1999 if (nextMarker == StateMarkers::Widget) {
2002 stream >> name >> f;
2003 StateFlags flags(f);
2004 if (name.isEmpty()) {
2006 stream >> dummy >> dummy >> dummy >> dummy;
2010 QDockWidget *widget =
nullptr;
2011 for (qsizetype j = 0; j < widgets.size(); ++j) {
2012 if (widgets.at(j)->objectName() == name) {
2013 widget = widgets.takeAt(j);
2018 if (widget ==
nullptr) {
2019 QPlaceHolderItem *placeHolder =
new QPlaceHolderItem;
2020 QDockAreaLayoutItem item(placeHolder);
2022 placeHolder->window = flags.testFlag(StateFlag::Floating);
2023 placeHolder->hidden = !flags.testFlag(StateFlag::Visible);
2024 if (placeHolder->window) {
2026 stream >> x >> y >> w >> h;
2027 placeHolder->topLevelRect = QRect(x, y, w, h);
2030 stream >> item.pos >> item.size >> dummy >> dummy;
2032 if (item.size != -1)
2033 item.flags |= QDockAreaLayoutItem::KeepSize;
2034 placeHolder->objectName = std::move(name);
2035 qCDebug(lcQpaDockWidgets) <<
"Restoring placeholder" << item << debugCallMode << flags;
2037 item_list.append(item);
2039 if (flags.testFlag(StateFlag::FloatingTabs))
2040 qCDebug(lcQpaDockWidgets) <<
"Found floating tab:" << name << flags << debugCallMode;
2041 QDockAreaLayoutItem item(
new QDockWidgetItem(widget));
2042 if (flags.testFlag(StateFlag::Floating)) {
2045 widget->setFloating(
true);
2049 stream >> x >> y >> w >> h;
2052 widget->setGeometry(QDockAreaLayout::constrainedRect(QRect(x, y, w, h), widget));
2053 widget->setVisible(flags.testFlag(StateFlag::Visible));
2054 item_list.append(item);
2058 stream >> item.pos >> item.size >> dummy >> dummy;
2060 item_list.append(item);
2061 if (flags.testFlag(StateFlag::Closed)) {
2064 widget->setFloating(
false);
2065 widget->setVisible(flags.setFlag(StateFlag::Visible));
2067 emit widget->dockLocationChanged(toDockWidgetArea(dockPos));
2070 qCDebug(lcQpaDockWidgets) <<
"Restoring QDockWidget" << item << flags << debugCallMode;
2073 delete item.widgetItem;
2074 item.widgetItem =
nullptr;
2077 }
else if (nextMarker == StateMarkers::Sequence) {
2079#if !QT_CONFIG(tabbar)
2080 const int tabBarShape = 0;
2082 QDockAreaLayoutItem item(
new QDockAreaLayoutInfo(sep, dockPos, o,
2083 tabBarShape, mainWindow));
2084 stream >> item.pos >> item.size >> dummy >> dummy;
2085 qCDebug(lcQpaDockWidgets) <<
"Restoring separator item" << item << debugCallMode;
2088 item_list.append(item);
2091 QDockAreaLayoutItem &lastItem = testing ? item : item_list.last();
2093 if (!lastItem.subinfo->restoreState(stream, widgets, callMode))
2101#if QT_CONFIG(tabbar)
2102 if (!testing && tabbed && index >= 0 && index < item_list.size()) {
2104 setCurrentTabId(tabId(item_list.at(index)));
2106 if (!testing && *sep == 1)
2107 updateSeparatorWidgets();
2113#if QT_CONFIG(tabbar)
2115static void raiseSeparatorWidget(QWidget *separatorWidget)
2117 Q_ASSERT(separatorWidget);
2119#if QT_CONFIG(toolbar)
2122 Q_ASSERT(separatorWidget->parent());
2123 const auto toolBars = separatorWidget->parent()->findChildren<QToolBar*>(Qt::FindDirectChildrenOnly);
2124 for (
auto *toolBar : toolBars) {
2125 if (
auto *toolBarLayout = qobject_cast<QToolBarLayout*>(toolBar->layout())) {
2126 if (toolBarLayout->expanded) {
2127 separatorWidget->stackUnder(toolBar);
2134 separatorWidget->raise();
2138void QDockAreaLayoutInfo::updateSeparatorWidgets()
const
2141 separatorWidgets.clear();
2146 for (
int i = 0; i < item_list.size(); ++i) {
2147 const QDockAreaLayoutItem &item = item_list.at(i);
2152 int next =
this->next(i);
2153 if ((item.flags & QDockAreaLayoutItem::GapItem)
2154 || (next != -1 && (item_list.at(next).flags & QDockAreaLayoutItem::GapItem)))
2158 item.subinfo->updateSeparatorWidgets();
2165 if (j < separatorWidgets.size()) {
2166 sepWidget = separatorWidgets.at(j);
2168 qWarning(
"QDockAreaLayoutInfo::updateSeparatorWidgets: null separator widget");
2169 sepWidget = mainWindowLayout()->getSeparatorWidget();
2170 separatorWidgets[j] = sepWidget;
2173 sepWidget = mainWindowLayout()->getSeparatorWidget();
2174 separatorWidgets.append(sepWidget);
2178 Q_ASSERT(sepWidget);
2179 raiseSeparatorWidget(sepWidget);
2181 QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
2182 sepWidget->setGeometry(sepRect);
2183 sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
2187 for (
int k = j; k < separatorWidgets.size(); ++k) {
2188 separatorWidgets[k]->hide();
2190 separatorWidgets.resize(j);
2194
2195
2196
2197
2198void QDockAreaLayoutInfo::reparentWidgets(QWidget *parent)
2201 tabBar->setParent(parent);
2203 for (
int i = 0; i < item_list.size(); ++i) {
2204 const QDockAreaLayoutItem &item = item_list.at(i);
2205 if (item.flags & QDockAreaLayoutItem::GapItem)
2208 item.subinfo->reparentWidgets(parent);
2209 if (item.widgetItem) {
2210 QWidget *w = item.widgetItem->widget();
2211 if (qobject_cast<QDockWidgetGroupWindow *>(w))
2213 if (w->parent() != parent) {
2214 bool hidden = w->isHidden();
2215 w->setParent(parent, w->windowFlags());
2224bool QDockAreaLayoutInfo::updateTabBar()
const
2229 QDockAreaLayoutInfo *that =
const_cast<QDockAreaLayoutInfo*>(
this);
2231 if (that->tabBar ==
nullptr) {
2232 that->tabBar = mainWindowLayout()->getTabBar();
2233 that->tabBar->setShape(
static_cast<QTabBar::Shape>(tabBarShape));
2234 that->tabBar->setDrawBase(
true);
2237 const QSignalBlocker blocker(tabBar);
2240 const quintptr oldCurrentId = currentTabId();
2243 for (
int i = 0; i < item_list.size(); ++i) {
2244 const QDockAreaLayoutItem &item = item_list.at(i);
2247 if (item.flags & QDockAreaLayoutItem::GapItem) {
2251 if (item.widgetItem ==
nullptr)
2254 QDockWidget *dw = qobject_cast<QDockWidget*>(item.widgetItem->widget());
2255 QString title = dw->d_func()->fixedWindowTitle;
2256 quintptr id = tabId(item);
2257 const QIcon windowIcon = dw->testAttribute(Qt::WA_SetWindowIcon) ? dw->windowIcon()
2259 if (tab_idx == tabBar->count()) {
2260 tabBar->insertTab(tab_idx, windowIcon, title);
2261#if QT_CONFIG(tooltip)
2262 tabBar->setTabToolTip(tab_idx, title);
2264 tabBar->setTabData(tab_idx, id);
2265 }
else if (qvariant_cast<quintptr>(tabBar->tabData(tab_idx)) != id) {
2266 if (tab_idx + 1 < tabBar->count()
2267 && qvariant_cast<quintptr>(tabBar->tabData(tab_idx + 1)) == id)
2268 tabBar->removeTab(tab_idx);
2270 tabBar->insertTab(tab_idx, windowIcon, title);
2271#if QT_CONFIG(tooltip)
2272 tabBar->setTabToolTip(tab_idx, title);
2274 tabBar->setTabData(tab_idx, id);
2278 if (title != tabBar->tabText(tab_idx)) {
2279 tabBar->setTabText(tab_idx, title);
2280#if QT_CONFIG(tooltip)
2281 tabBar->setTabToolTip(tab_idx, title);
2288 while (tab_idx < tabBar->count()) {
2289 tabBar->removeTab(tab_idx);
2292 if (oldCurrentId > 0 && currentTabId() != oldCurrentId)
2293 that->setCurrentTabId(oldCurrentId);
2295 if (QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(tabBar->parent()))
2296 dwgw->adjustFlags();
2299 return ( (gap ? 1 : 0) + tabBar->count()) > 1;
2302void QDockAreaLayoutInfo::setTabBarShape(
int shape)
2304 if (shape == tabBarShape)
2306 tabBarShape = shape;
2307 if (tabBar !=
nullptr)
2308 tabBar->setShape(
static_cast<QTabBar::Shape>(shape));
2310 for (
int i = 0; i < item_list.size(); ++i) {
2311 QDockAreaLayoutItem &item = item_list[i];
2312 if (item.subinfo !=
nullptr)
2313 item.subinfo->setTabBarShape(shape);
2317QSize QDockAreaLayoutInfo::tabBarMinimumSize()
const
2319 if (!updateTabBar())
2322 return tabBar->minimumSizeHint();
2325QSize QDockAreaLayoutInfo::tabBarSizeHint()
const
2327 if (!updateTabBar())
2330 return tabBar->sizeHint();
2333QSet<QTabBar*> QDockAreaLayoutInfo::usedTabBars()
const
2335 QSet<QTabBar*> result;
2339 result.insert(tabBar);
2342 for (
int i = 0; i < item_list.size(); ++i) {
2343 const QDockAreaLayoutItem &item = item_list.at(i);
2344 if (item.subinfo !=
nullptr)
2345 result += item.subinfo->usedTabBars();
2353QSet<QWidget*> QDockAreaLayoutInfo::usedSeparatorWidgets()
const
2355 QSet<QWidget*> result;
2356 const int numSeparatorWidgets = separatorWidgets.size();
2357 result.reserve(numSeparatorWidgets);
2359 for (
int i = 0; i < numSeparatorWidgets; ++i)
2360 result << separatorWidgets.at(i);
2362 for (
int i = 0; i < item_list.size(); ++i) {
2363 const QDockAreaLayoutItem &item = item_list.at(i);
2364 if (item.subinfo !=
nullptr)
2365 result += item.subinfo->usedSeparatorWidgets();
2371QRect QDockAreaLayoutInfo::tabContentRect()
const
2376 QRect result = rect;
2377 QSize tbh = tabBarSizeHint();
2379 if (!tbh.isNull()) {
2380 switch (tabBarShape) {
2381 case QTabBar::RoundedNorth:
2382 case QTabBar::TriangularNorth:
2383 result.adjust(0, tbh.height(), 0, 0);
2385 case QTabBar::RoundedSouth:
2386 case QTabBar::TriangularSouth:
2387 result.adjust(0, 0, 0, -tbh.height());
2389 case QTabBar::RoundedEast:
2390 case QTabBar::TriangularEast:
2391 result.adjust(0, 0, -tbh.width(), 0);
2393 case QTabBar::RoundedWest:
2394 case QTabBar::TriangularWest:
2395 result.adjust(tbh.width(), 0, 0, 0);
2405int QDockAreaLayoutInfo::tabIndexToListIndex(
int tabIndex)
const
2407 Q_ASSERT(tabbed && tabBar);
2408 quintptr data = qvariant_cast<quintptr>(tabBar->tabData(tabIndex));
2409 for (
int i = 0; i < item_list.size(); ++i) {
2410 if (tabId(item_list.at(i)) == data)
2416void QDockAreaLayoutInfo::moveTab(
int from,
int to)
2418 item_list.move(tabIndexToListIndex(from), tabIndexToListIndex(to));
2423
2424
2426QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : fallbackToSizeHints(
true)
2429 sep = win->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent,
nullptr, win);
2430#if QT_CONFIG(tabbar)
2431 const int tabShape = QTabBar::RoundedSouth;
2433 const int tabShape = 0;
2435 docks[QInternal::LeftDock]
2436 = QDockAreaLayoutInfo(&sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
2437 docks[QInternal::RightDock]
2438 = QDockAreaLayoutInfo(&sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
2439 docks[QInternal::TopDock]
2440 = QDockAreaLayoutInfo(&sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
2441 docks[QInternal::BottomDock]
2442 = QDockAreaLayoutInfo(&sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
2443 centralWidgetItem =
nullptr;
2446 corners[Qt::TopLeftCorner] = Qt::TopDockWidgetArea;
2447 corners[Qt::TopRightCorner] = Qt::TopDockWidgetArea;
2448 corners[Qt::BottomLeftCorner] = Qt::BottomDockWidgetArea;
2449 corners[Qt::BottomRightCorner] = Qt::BottomDockWidgetArea;
2452bool QDockAreaLayout::isValid()
const
2454 return rect.isValid();
2457void QDockAreaLayout::saveState(QDataStream &stream)
const
2459 stream << StateMarkers::DockWidget;
2461 for (
int i = 0; i < QInternal::DockCount; ++i) {
2462 if (!docks[i].item_list.isEmpty())
2466 for (
int i = 0; i < QInternal::DockCount; ++i) {
2467 if (docks[i].item_list.isEmpty())
2469 stream << i << docks[i].rect.size();
2470 docks[i].saveState(stream);
2473 stream << centralWidgetRect.size();
2475 for (
int i = 0; i < 4; ++i)
2476 stream <<
static_cast<
int>(corners[i]);
2479bool QDockAreaLayout::restoreState(QDataStream &stream,
const QList<QDockWidget*> &_dockwidgets, QInternal::CallMode callMode)
2481 QList<QDockWidget*> dockwidgets = _dockwidgets;
2482 const bool testing = callMode == QInternal::Testing;
2485 for (
int i = 0; i < cnt; ++i) {
2491 docks[pos].rect = QRect(QPoint(0, 0), size);
2493 if (!docks[pos].restoreState(stream, dockwidgets, callMode)) {
2494 stream.setStatus(QDataStream::ReadCorruptData);
2501 centralWidgetRect = QRect(QPoint(0, 0), size);
2503 bool ok = stream.status() == QDataStream::Ok;
2507 for (
int i = 0; i < 4; ++i)
2508 stream >> cornerData[i];
2509 if (stream.status() == QDataStream::Ok) {
2510 for (
int i = 0; i < 4; ++i)
2511 corners[i] =
static_cast<Qt::DockWidgetArea>(cornerData[i]);
2515 fallbackToSizeHints =
false;
2521QList<
int> QDockAreaLayout::indexOfPlaceHolder(
const QString &objectName)
const
2523 for (
int i = 0; i < QInternal::DockCount; ++i) {
2524 QList<
int> result = docks[i].indexOfPlaceHolder(objectName);
2525 if (!result.isEmpty()) {
2530 return QList<
int>();
2533QList<
int> QDockAreaLayout::indexOf(
const QWidget *dockWidget)
const
2535 for (
int i = 0; i < QInternal::DockCount; ++i) {
2536 QList<
int> result = docks[i].indexOf(dockWidget);
2537 if (!result.isEmpty()) {
2542 return QList<
int>();
2545QList<
int> QDockAreaLayout::gapIndex(
const QPoint &pos,
bool disallowTabs)
const
2547 QMainWindow::DockOptions opts = mainWindow->dockOptions();
2548 bool nestingEnabled = opts & QMainWindow::AllowNestedDocks;
2549 QDockAreaLayoutInfo::TabMode tabMode = QDockAreaLayoutInfo::NoTabs;
2550#if QT_CONFIG(tabbar)
2551 if (!disallowTabs) {
2552 if (opts & QMainWindow::AllowTabbedDocks || opts & QMainWindow::VerticalTabs)
2553 tabMode = QDockAreaLayoutInfo::AllowTabs;
2554 if (opts & QMainWindow::ForceTabbedDocks)
2555 tabMode = QDockAreaLayoutInfo::ForceTabs;
2557 if (tabMode == QDockAreaLayoutInfo::ForceTabs)
2558 nestingEnabled =
false;
2563 for (
int i = 0; i < QInternal::DockCount; ++i) {
2564 const QDockAreaLayoutInfo &info = docks[i];
2566 if (!info.isEmpty() && info.rect.contains(pos)) {
2568 = docks[i].gapIndex(pos, nestingEnabled, tabMode);
2569 if (!result.isEmpty())
2575 for (
int i = 0; i < QInternal::DockCount; ++i) {
2576 const QDockAreaLayoutInfo &info = docks[i];
2578 if (info.isEmpty()) {
2579 const QRect r = gapRect(
static_cast<QInternal::DockPosition>(i));
2580 if (r.contains(pos)) {
2581 if (opts & QMainWindow::ForceTabbedDocks && !info.item_list.isEmpty()) {
2584 return QList<
int>() << i << -1 << 0;
2586 return QList<
int>() << i << 0;
2592 return QList<
int>();
2595QRect QDockAreaLayout::gapRect(QInternal::DockPosition dockPos)
const
2597 Q_ASSERT_X(mainWindow,
"QDockAreaLayout::gapRect",
"Called without valid mainWindow pointer.");
2600 const QSize gapSize = (mainWindow->size()/2).boundedTo(QSize(EmptyDropAreaSize, EmptyDropAreaSize));
2604 if (mainWindow->height() < (2 * sep)) {
2605 qCWarning(lcQpaDockWidgets,
2606 "QDockAreaLayout::gapRect: Main window height %i is too small. Docking will not be possible.",
2607 mainWindow->height());
2610 if (mainWindow->width() < (2 * sep)) {
2611 qCWarning(lcQpaDockWidgets,
2612 "QDockAreaLayout::gapRect: Main window width %i is too small. Docking will not be possible.",
2613 mainWindow->width());
2618 case QInternal::LeftDock:
2619 return QRect(rect.left(), rect.top(), gapSize.width(), rect.height());
2620 case QInternal::RightDock:
2621 return QRect(rect.right() - gapSize.width(), rect.top(), gapSize.width(), rect.height());
2622 case QInternal::TopDock:
2623 return QRect(rect.left(), rect.top(), rect.width(), gapSize.height());
2624 case QInternal::BottomDock:
2625 return QRect(rect.left(), rect.bottom() - gapSize.height(), rect.width(), gapSize.height());
2626 case QInternal::DockCount:
2632QList<
int> QDockAreaLayout::findSeparator(
const QPoint &pos)
const
2635 for (
int i = 0; i < QInternal::DockCount; ++i) {
2636 const QDockAreaLayoutInfo &info = docks[i];
2639 QRect rect = separatorRect(i);
2640 if (!rect.isNull() && sep == 1)
2641 rect.adjust(-2, -2, 2, 2);
2642 if (rect.contains(pos) && !info.hasFixedSize()) {
2645 }
else if (info.rect.contains(pos)) {
2646 result = docks[i].findSeparator(pos);
2647 if (!result.isEmpty()) {
2657QDockAreaLayoutInfo *QDockAreaLayout::info(QWidget *widget)
2659 for (
int i = 0; i < QInternal::DockCount; ++i) {
2660 if (QDockAreaLayoutInfo *result = docks[i].info(widget))
2667QDockAreaLayoutInfo *QDockAreaLayout::info(
const QList<
int> &path)
2669 Q_ASSERT(!path.isEmpty());
2670 const int index = path.first();
2671 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2673 if (path.size() == 1)
2674 return &docks[index];
2676 return docks[index].info(path.mid(1));
2679const QDockAreaLayoutInfo *QDockAreaLayout::info(
const QList<
int> &path)
const
2681 return const_cast<QDockAreaLayout*>(
this)->info(path);
2684QDockAreaLayoutItem &QDockAreaLayout::item(
const QList<
int> &path)
2686 Q_ASSERT(!path.isEmpty());
2687 const int index = path.first();
2688 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2689 return docks[index].item(path.mid(1));
2692QRect QDockAreaLayout::itemRect(
const QList<
int> &path)
const
2694 Q_ASSERT(!path.isEmpty());
2695 const int index = path.first();
2696 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2697 return docks[index].itemRect(path.mid(1));
2700QRect QDockAreaLayout::separatorRect(
int index)
const
2702 const QDockAreaLayoutInfo &dock = docks[index];
2705 QRect r = dock.rect;
2707 case QInternal::LeftDock:
2708 return QRect(r.right() + 1, r.top(), sep, r.height());
2709 case QInternal::RightDock:
2710 return QRect(r.left() - sep, r.top(), sep, r.height());
2711 case QInternal::TopDock:
2712 return QRect(r.left(), r.bottom() + 1, r.width(), sep);
2713 case QInternal::BottomDock:
2714 return QRect(r.left(), r.top() - sep, r.width(), sep);
2721QRect QDockAreaLayout::separatorRect(
const QList<
int> &path)
const
2723 Q_ASSERT(!path.isEmpty());
2725 const int index = path.first();
2726 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2728 if (path.size() == 1)
2729 return separatorRect(index);
2731 return docks[index].separatorRect(path.mid(1));
2734bool QDockAreaLayout::insertGap(
const QList<
int> &path, QLayoutItem *dockWidgetItem)
2736 Q_ASSERT(!path.isEmpty());
2737 const int index = path.first();
2738 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2739 return docks[index].insertGap(path.mid(1), dockWidgetItem);
2742QLayoutItem *QDockAreaLayout::plug(
const QList<
int> &path)
2744#if QT_CONFIG(tabbar)
2745 Q_ASSERT(!path.isEmpty());
2746 const int index = path.first();
2747 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2748 QLayoutItem *item = docks[index].plug(path.mid(1));
2749 docks[index].reparentWidgets(mainWindow);
2756QLayoutItem *QDockAreaLayout::unplug(
const QList<
int> &path)
2758 Q_ASSERT(!path.isEmpty());
2759 const int index = path.first();
2760 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2761 return docks[index].unplug(path.mid(1));
2764void QDockAreaLayout::remove(
const QList<
int> &path)
2766 Q_ASSERT(!path.isEmpty());
2767 const int index = path.first();
2768 Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2769 docks[index].remove(path.mid(1));
2772void QDockAreaLayout::removePlaceHolder(
const QString &name)
2774 QList<
int> index = indexOfPlaceHolder(name);
2775 if (!index.isEmpty())
2778 mainWindow->findChildren<QDockWidgetGroupWindow *>(Qt::FindDirectChildrenOnly);
2779 for (QDockWidgetGroupWindow *dwgw : groups) {
2780 index = dwgw->layoutInfo()->indexOfPlaceHolder(name);
2781 if (!index.isEmpty()) {
2782 dwgw->layoutInfo()->remove(index);
2783 dwgw->destroyOrHideIfEmpty();
2788static inline int qMax(
int i1,
int i2,
int i3) {
return qMax(i1, qMax(i2, i3)); }
2790void QDockAreaLayout::getGrid(QList<QLayoutStruct> *_ver_struct_list,
2791 QList<QLayoutStruct> *_hor_struct_list)
2793 QSize center_hint(0, 0);
2794 QSize center_min(0, 0);
2795 QSize center_max(0, 0);
2796 const bool have_central = centralWidgetItem !=
nullptr && !centralWidgetItem->isEmpty();
2798 center_hint = centralWidgetRect.size();
2799 if (!center_hint.isValid())
2800 center_hint = centralWidgetItem->sizeHint();
2801 center_min = centralWidgetItem->minimumSize();
2802 center_max = centralWidgetItem->maximumSize();
2805 QRect center_rect = rect;
2806 if (!docks[QInternal::LeftDock].isEmpty())
2807 center_rect.setLeft(rect.left() + docks[QInternal::LeftDock].rect.width() + sep);
2808 if (!docks[QInternal::TopDock].isEmpty())
2809 center_rect.setTop(rect.top() + docks[QInternal::TopDock].rect.height() + sep);
2810 if (!docks[QInternal::RightDock].isEmpty())
2811 center_rect.setRight(rect.right() - docks[QInternal::RightDock].rect.width() - sep);
2812 if (!docks[QInternal::BottomDock].isEmpty())
2813 center_rect.setBottom(rect.bottom() - docks[QInternal::BottomDock].rect.height() - sep);
2815 QSize left_hint = docks[QInternal::LeftDock].size();
2816 if (left_hint.isNull() || fallbackToSizeHints)
2817 left_hint = docks[QInternal::LeftDock].sizeHint();
2818 QSize left_min = docks[QInternal::LeftDock].minimumSize();
2819 QSize left_max = docks[QInternal::LeftDock].maximumSize();
2820 left_hint = left_hint.boundedTo(left_max).expandedTo(left_min);
2822 QSize right_hint = docks[QInternal::RightDock].size();
2823 if (right_hint.isNull() || fallbackToSizeHints)
2824 right_hint = docks[QInternal::RightDock].sizeHint();
2825 QSize right_min = docks[QInternal::RightDock].minimumSize();
2826 QSize right_max = docks[QInternal::RightDock].maximumSize();
2827 right_hint = right_hint.boundedTo(right_max).expandedTo(right_min);
2829 QSize top_hint = docks[QInternal::TopDock].size();
2830 if (top_hint.isNull() || fallbackToSizeHints)
2831 top_hint = docks[QInternal::TopDock].sizeHint();
2832 QSize top_min = docks[QInternal::TopDock].minimumSize();
2833 QSize top_max = docks[QInternal::TopDock].maximumSize();
2834 top_hint = top_hint.boundedTo(top_max).expandedTo(top_min);
2836 QSize bottom_hint = docks[QInternal::BottomDock].size();
2837 if (bottom_hint.isNull() || fallbackToSizeHints)
2838 bottom_hint = docks[QInternal::BottomDock].sizeHint();
2839 QSize bottom_min = docks[QInternal::BottomDock].minimumSize();
2840 QSize bottom_max = docks[QInternal::BottomDock].maximumSize();
2841 bottom_hint = bottom_hint.boundedTo(bottom_max).expandedTo(bottom_min);
2843 if (_ver_struct_list !=
nullptr) {
2844 QList<QLayoutStruct> &ver_struct_list = *_ver_struct_list;
2845 ver_struct_list.resize(3);
2848 ver_struct_list[0].init();
2849 ver_struct_list[0].stretch = 0;
2850 ver_struct_list[0].sizeHint = top_hint.height();
2851 ver_struct_list[0].minimumSize = top_min.height();
2852 ver_struct_list[0].maximumSize = top_max.height();
2853 ver_struct_list[0].expansive =
false;
2854 ver_struct_list[0].empty = docks[QInternal::TopDock].isEmpty();
2855 ver_struct_list[0].pos = docks[QInternal::TopDock].rect.top();
2856 ver_struct_list[0].size = docks[QInternal::TopDock].rect.height();
2859 ver_struct_list[1].init();
2860 ver_struct_list[1].stretch = center_hint.height();
2862 bool tl_significant = corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
2863 || docks[QInternal::TopDock].isEmpty();
2864 bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
2865 || docks[QInternal::BottomDock].isEmpty();
2866 bool tr_significant = corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
2867 || docks[QInternal::TopDock].isEmpty();
2868 bool br_significant = corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
2869 || docks[QInternal::BottomDock].isEmpty();
2871 int left = (tl_significant && bl_significant) ? left_hint.height() : 0;
2872 int right = (tr_significant && br_significant) ? right_hint.height() : 0;
2873 ver_struct_list[1].sizeHint = qMax(left, center_hint.height(), right);
2875 left = (tl_significant && bl_significant) ? left_min.height() : 0;
2876 right = (tr_significant && br_significant) ? right_min.height() : 0;
2877 ver_struct_list[1].minimumSize = qMax(left, center_min.height(), right);
2878 ver_struct_list[1].maximumSize = center_max.height();
2879 ver_struct_list[1].expansive = have_central;
2880 ver_struct_list[1].empty = docks[QInternal::LeftDock].isEmpty()
2882 && docks[QInternal::RightDock].isEmpty();
2883 ver_struct_list[1].pos = center_rect.top();
2884 ver_struct_list[1].size = center_rect.height();
2887 ver_struct_list[2].init();
2888 ver_struct_list[2].stretch = 0;
2889 ver_struct_list[2].sizeHint = bottom_hint.height();
2890 ver_struct_list[2].minimumSize = bottom_min.height();
2891 ver_struct_list[2].maximumSize = bottom_max.height();
2892 ver_struct_list[2].expansive =
false;
2893 ver_struct_list[2].empty = docks[QInternal::BottomDock].isEmpty();
2894 ver_struct_list[2].pos = docks[QInternal::BottomDock].rect.top();
2895 ver_struct_list[2].size = docks[QInternal::BottomDock].rect.height();
2897 for (
int i = 0; i < 3; ++i) {
2898 ver_struct_list[i].sizeHint
2899 = qMax(ver_struct_list[i].sizeHint, ver_struct_list[i].minimumSize);
2901 if (have_central && ver_struct_list[0].empty && ver_struct_list[2].empty)
2902 ver_struct_list[1].maximumSize = QWIDGETSIZE_MAX;
2905 if (_hor_struct_list !=
nullptr) {
2906 QList<QLayoutStruct> &hor_struct_list = *_hor_struct_list;
2907 hor_struct_list.resize(3);
2910 hor_struct_list[0].init();
2911 hor_struct_list[0].stretch = 0;
2912 hor_struct_list[0].sizeHint = left_hint.width();
2913 hor_struct_list[0].minimumSize = left_min.width();
2914 hor_struct_list[0].maximumSize = left_max.width();
2915 hor_struct_list[0].expansive =
false;
2916 hor_struct_list[0].empty = docks[QInternal::LeftDock].isEmpty();
2917 hor_struct_list[0].pos = docks[QInternal::LeftDock].rect.left();
2918 hor_struct_list[0].size = docks[QInternal::LeftDock].rect.width();
2921 hor_struct_list[1].init();
2922 hor_struct_list[1].stretch = center_hint.width();
2924 bool tl_significant = corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
2925 || docks[QInternal::LeftDock].isEmpty();
2926 bool tr_significant = corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
2927 || docks[QInternal::RightDock].isEmpty();
2928 bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
2929 || docks[QInternal::LeftDock].isEmpty();
2930 bool br_significant = corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
2931 || docks[QInternal::RightDock].isEmpty();
2933 int top = (tl_significant && tr_significant) ? top_hint.width() : 0;
2934 int bottom = (bl_significant && br_significant) ? bottom_hint.width() : 0;
2935 hor_struct_list[1].sizeHint = qMax(top, center_hint.width(), bottom);
2937 top = (tl_significant && tr_significant) ? top_min.width() : 0;
2938 bottom = (bl_significant && br_significant) ? bottom_min.width() : 0;
2939 hor_struct_list[1].minimumSize = qMax(top, center_min.width(), bottom);
2941 hor_struct_list[1].maximumSize = center_max.width();
2942 hor_struct_list[1].expansive = have_central;
2943 hor_struct_list[1].empty = !have_central;
2944 hor_struct_list[1].pos = center_rect.left();
2945 hor_struct_list[1].size = center_rect.width();
2948 hor_struct_list[2].init();
2949 hor_struct_list[2].stretch = 0;
2950 hor_struct_list[2].sizeHint = right_hint.width();
2951 hor_struct_list[2].minimumSize = right_min.width();
2952 hor_struct_list[2].maximumSize = right_max.width();
2953 hor_struct_list[2].expansive =
false;
2954 hor_struct_list[2].empty = docks[QInternal::RightDock].isEmpty();
2955 hor_struct_list[2].pos = docks[QInternal::RightDock].rect.left();
2956 hor_struct_list[2].size = docks[QInternal::RightDock].rect.width();
2958 for (
int i = 0; i < 3; ++i) {
2959 hor_struct_list[i].sizeHint
2960 = qMax(hor_struct_list[i].sizeHint, hor_struct_list[i].minimumSize);
2962 if (have_central && hor_struct_list[0].empty && hor_struct_list[2].empty)
2963 hor_struct_list[1].maximumSize = QWIDGETSIZE_MAX;
2968void QDockAreaLayout::setGrid(QList<QLayoutStruct> *ver_struct_list,
2969 QList<QLayoutStruct> *hor_struct_list)
2974 if (!docks[QInternal::TopDock].isEmpty()) {
2975 QRect r = docks[QInternal::TopDock].rect;
2976 if (hor_struct_list !=
nullptr) {
2977 r.setLeft(corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
2978 || docks[QInternal::LeftDock].isEmpty()
2979 ? rect.left() : hor_struct_list->at(1).pos);
2980 r.setRight(corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
2981 || docks[QInternal::RightDock].isEmpty()
2982 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
2984 if (ver_struct_list !=
nullptr) {
2985 r.setTop(rect.top());
2986 r.setBottom(ver_struct_list->at(1).pos - sep - 1);
2988 docks[QInternal::TopDock].rect = r;
2989 docks[QInternal::TopDock].fitItems();
2994 if (!docks[QInternal::BottomDock].isEmpty()) {
2995 QRect r = docks[QInternal::BottomDock].rect;
2996 if (hor_struct_list !=
nullptr) {
2997 r.setLeft(corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
2998 || docks[QInternal::LeftDock].isEmpty()
2999 ? rect.left() : hor_struct_list->at(1).pos);
3000 r.setRight(corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
3001 || docks[QInternal::RightDock].isEmpty()
3002 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
3004 if (ver_struct_list !=
nullptr) {
3005 r.setTop(ver_struct_list->at(2).pos);
3006 r.setBottom(rect.bottom());
3008 docks[QInternal::BottomDock].rect = r;
3009 docks[QInternal::BottomDock].fitItems();
3014 if (!docks[QInternal::LeftDock].isEmpty()) {
3015 QRect r = docks[QInternal::LeftDock].rect;
3016 if (hor_struct_list !=
nullptr) {
3017 r.setLeft(rect.left());
3018 r.setRight(hor_struct_list->at(1).pos - sep - 1);
3020 if (ver_struct_list !=
nullptr) {
3021 r.setTop(corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
3022 || docks[QInternal::TopDock].isEmpty()
3023 ? rect.top() : ver_struct_list->at(1).pos);
3024 r.setBottom(corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
3025 || docks[QInternal::BottomDock].isEmpty()
3026 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
3028 docks[QInternal::LeftDock].rect = r;
3029 docks[QInternal::LeftDock].fitItems();
3034 if (!docks[QInternal::RightDock].isEmpty()) {
3035 QRect r = docks[QInternal::RightDock].rect;
3036 if (hor_struct_list !=
nullptr) {
3037 r.setLeft(hor_struct_list->at(2).pos);
3038 r.setRight(rect.right());
3040 if (ver_struct_list !=
nullptr) {
3041 r.setTop(corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
3042 || docks[QInternal::TopDock].isEmpty()
3043 ? rect.top() : ver_struct_list->at(1).pos);
3044 r.setBottom(corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
3045 || docks[QInternal::BottomDock].isEmpty()
3046 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
3048 docks[QInternal::RightDock].rect = r;
3049 docks[QInternal::RightDock].fitItems();
3054 if (hor_struct_list !=
nullptr) {
3055 centralWidgetRect.setLeft(hor_struct_list->at(1).pos);
3056 centralWidgetRect.setWidth(hor_struct_list->at(1).size);
3058 if (ver_struct_list !=
nullptr) {
3059 centralWidgetRect.setTop(ver_struct_list->at(1).pos);
3060 centralWidgetRect.setHeight(ver_struct_list->at(1).size);
3064void QDockAreaLayout::fitLayout()
3066 QList<QLayoutStruct> ver_struct_list(3);
3067 QList<QLayoutStruct> hor_struct_list(3);
3068 getGrid(&ver_struct_list, &hor_struct_list);
3070 qGeomCalc(ver_struct_list, 0, 3, rect.top(), rect.height(), sep);
3071 qGeomCalc(hor_struct_list, 0, 3, rect.left(), rect.width(), sep);
3073 setGrid(&ver_struct_list, &hor_struct_list);
3076void QDockAreaLayout::clear()
3078 for (
int i = 0; i < QInternal::DockCount; ++i)
3082 centralWidgetRect = QRect();
3085template<
typename SizePMF,
typename CenterPMF>
3086QSize QDockAreaLayout::size_helper(SizePMF sizeFn, CenterPMF centerFn)
const
3093 if (centralWidgetItem !=
nullptr) {
3094 left_sep = docks[QInternal::LeftDock].isEmpty() ? 0 : sep;
3095 right_sep = docks[QInternal::RightDock].isEmpty() ? 0 : sep;
3096 top_sep = docks[QInternal::TopDock].isEmpty() ? 0 : sep;
3097 bottom_sep = docks[QInternal::BottomDock].isEmpty() ? 0 : sep;
3100 const QSize left = (docks[QInternal::LeftDock].*sizeFn)() + QSize(left_sep, 0);
3101 const QSize right = (docks[QInternal::RightDock].*sizeFn)() + QSize(right_sep, 0);
3102 const QSize top = (docks[QInternal::TopDock].*sizeFn)() + QSize(0, top_sep);
3103 const QSize bottom = (docks[QInternal::BottomDock].*sizeFn)() + QSize(0, bottom_sep);
3104 const QSize center = centralWidgetItem ==
nullptr
3105 ? QSize(0, 0) : (centralWidgetItem->*centerFn)();
3107 int row1 = top.width();
3108 int row2 = left.width() + center.width() + right.width();
3109 int row3 = bottom.width();
3110 int col1 = left.height();
3111 int col2 = top.height() + center.height() + bottom.height();
3112 int col3 = right.height();
3114 if (corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea)
3115 row1 += left.width();
3117 col1 += top.height();
3119 if (corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea)
3120 row1 += right.width();
3122 col3 += top.height();
3124 if (corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea)
3125 row3 += left.width();
3127 col1 += bottom.height();
3129 if (corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea)
3130 row3 += right.width();
3132 col3 += bottom.height();
3134 return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
3137QSize QDockAreaLayout::sizeHint()
const
3139 return size_helper(&QDockAreaLayoutInfo::sizeHint, &QLayoutItem::sizeHint);
3142QSize QDockAreaLayout::minimumSize()
const
3144 return size_helper(&QDockAreaLayoutInfo::minimumSize, &QLayoutItem::minimumSize);
3148
3149
3150
3151
3152QSize QDockAreaLayout::minimumStableSize()
const
3154 return size_helper(&QDockAreaLayoutInfo::size, &QLayoutItem::minimumSize);
3158
3159
3160
3161
3162
3163QRect QDockAreaLayout::constrainedRect(QRect rect, QWidget* widget)
3165 QScreen *screen =
nullptr;
3166 if (QGuiApplication::primaryScreen()->virtualSiblings().size() > 1)
3167 screen = QGuiApplication::screenAt(rect.topLeft());
3169 screen = widget->screen();
3171 const QRect screenRect = screen->geometry();
3172 if (screenRect.isValid()) {
3173 rect.setWidth(qMin(rect.width(), screenRect.width()));
3174 rect.setHeight(qMin(rect.height(), screenRect.height()));
3175 rect.moveLeft(qMax(rect.left(), screenRect.left()));
3176 rect.moveTop(qMax(rect.top(), screenRect.top()));
3177 rect.moveRight(qMin(rect.right(), screenRect.right()));
3178 rect.moveBottom(qMin(rect.bottom(), screenRect.bottom()));
3184bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
3186 QDockAreaLayoutItem *item =
nullptr;
3188 mainWindow->findChildren<QDockWidgetGroupWindow *>(Qt::FindDirectChildrenOnly);
3189 for (QDockWidgetGroupWindow *dwgw : groups) {
3190 QList<
int> index = dwgw->layoutInfo()->indexOfPlaceHolder(dockWidget->objectName());
3191 if (!index.isEmpty()) {
3192 dockWidget->setParent(dwgw);
3193 item =
const_cast<QDockAreaLayoutItem *>(&dwgw->layoutInfo()->item(index));
3198 QList<
int> index = indexOfPlaceHolder(dockWidget->objectName());
3199 if (index.isEmpty())
3201 item =
const_cast<QDockAreaLayoutItem *>(&
this->item(index));
3204 QPlaceHolderItem *placeHolder = item->placeHolderItem;
3205 Q_ASSERT(placeHolder !=
nullptr);
3207 item->widgetItem =
new QDockWidgetItem(dockWidget);
3209 if (placeHolder->window) {
3210 const QRect r = constrainedRect(placeHolder->topLevelRect, dockWidget);
3211 dockWidget->d_func()->setWindowState(QDockWidgetPrivate::WindowStates(
3212 {QDockWidgetPrivate::WindowState::Floating,
3213 QDockWidgetPrivate::WindowState::Unplug}), r);
3215 dockWidget->setVisible(!placeHolder->hidden);
3217 item->placeHolderItem =
nullptr;
3223void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *dockWidget,
3224 Qt::Orientation orientation)
3226 QLayoutItem *dockWidgetItem =
new QDockWidgetItem(dockWidget);
3227 QDockAreaLayoutInfo &info = docks[pos];
3228 if (orientation == info.o || info.item_list.size() <= 1) {
3231 info.o = orientation;
3233 QDockAreaLayoutItem new_item(dockWidgetItem);
3234 info.item_list.append(new_item);
3235#if QT_CONFIG(tabbar)
3236 if (info.tabbed && !new_item.skip()) {
3237 info.updateTabBar();
3238 info.setCurrentTabId(tabId(new_item));
3242#if QT_CONFIG(tabbar)
3243 int tbshape = info.tabBarShape;
3247 QDockAreaLayoutInfo new_info(&sep, pos, orientation, tbshape, mainWindow);
3248 new_info.item_list.append(QDockAreaLayoutItem(
new QDockAreaLayoutInfo(info)));
3249 new_info.item_list.append(QDockAreaLayoutItem(dockWidgetItem));
3253 removePlaceHolder(dockWidget->objectName());
3256#if QT_CONFIG(tabbar)
3257void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
3259 const QList<
int> path = indexOf(first);
3263 QDockAreaLayoutInfo *info =
this->info(path);
3264 Q_ASSERT(info !=
nullptr);
3265 info->tab(path.last(),
new QDockWidgetItem(second));
3267 removePlaceHolder(second->objectName());
3271void QDockAreaLayout::resizeDocks(
const QList<QDockWidget *> &docks,
3272 const QList<
int> &sizes, Qt::Orientation o)
3274 if (Q_UNLIKELY(docks.size() != sizes.size())) {
3275 qWarning(
"QMainWidget::resizeDocks: size of the lists are not the same");
3278 int count = docks.size();
3279 fallbackToSizeHints =
false;
3280 for (
int i = 0; i < count; ++i) {
3281 QList<
int> path = indexOf(docks[i]);
3282 if (Q_UNLIKELY(path.isEmpty())) {
3283 qWarning(
"QMainWidget::resizeDocks: one QDockWidget is not part of the layout");
3286 int size = sizes[i];
3287 if (Q_UNLIKELY(size <= 0)) {
3288 qWarning(
"QMainWidget::resizeDocks: all sizes need to be larger than 0");
3292 while (path.size() > 1) {
3293 QDockAreaLayoutInfo *info =
this->info(path);
3294#if QT_CONFIG(tabbar)
3295 if (!info->tabbed && info->o == o) {
3296 info->item_list[path.constLast()].size = size;
3298 for (
const QDockAreaLayoutItem &item : std::as_const(info->item_list)) {
3302 totalSize += item.size == -1 ? pick(o, item.sizeHint()) : item.size;
3311 const int dockNum = path.constFirst();
3312 Q_ASSERT(dockNum < QInternal::DockCount);
3313 QRect &r =
this->docks[dockNum].rect;
3320void QDockAreaLayout::splitDockWidget(QDockWidget *after,
3321 QDockWidget *dockWidget,
3322 Qt::Orientation orientation)
3324 const QList<
int> path = indexOf(after);
3328 QDockAreaLayoutInfo *info =
this->info(path);
3329 Q_ASSERT(info !=
nullptr);
3330 info->split(path.last(), orientation,
new QDockWidgetItem(dockWidget));
3332 removePlaceHolder(dockWidget->objectName());
3335void QDockAreaLayout::apply(QWidgetAnimator::AnimationRule rule)
3337 QWidgetAnimator &widgetAnimator = qt_mainwindow_layout(mainWindow)->widgetAnimator;
3339 for (
int i = 0; i < QInternal::DockCount; ++i)
3340 docks[i].apply(rule);
3341 if (centralWidgetItem !=
nullptr && !centralWidgetItem->isEmpty()) {
3342 widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect,
3345#if QT_CONFIG(tabbar)
3347 updateSeparatorWidgets();
3351void QDockAreaLayout::paintSeparators(QPainter *p, QWidget *widget,
3352 const QRegion &clip,
3353 const QPoint &mouse)
const
3355 for (
int i = 0; i < QInternal::DockCount; ++i) {
3356 const QDockAreaLayoutInfo &dock = docks[i];
3359 QRect r = separatorRect(i);
3360 if (clip.contains(r) && !dock.hasFixedSize()) {
3361 Qt::Orientation opposite = dock.o == Qt::Horizontal
3362 ? Qt::Vertical : Qt::Horizontal;
3363 paintSep(p, widget, r, opposite, r.contains(mouse));
3365 if (clip.contains(dock.rect))
3366 dock.paintSeparators(p, widget, clip, mouse);
3370QRegion QDockAreaLayout::separatorRegion()
const
3374 for (
int i = 0; i < QInternal::DockCount; ++i) {
3375 const QDockAreaLayoutInfo &dock = docks[i];
3378 result |= separatorRect(i);
3379 result |= dock.separatorRegion();
3385int QDockAreaLayout::separatorMove(
const QList<
int> &separator,
const QPoint &origin,
3389 const auto dockPosition =
static_cast<QInternal::DockPosition>(separator.last());
3390 const bool isHorizontal =
3391 dockPosition == QInternal::LeftDock || dockPosition == QInternal::RightDock;
3392 const bool isLeftOrTop = dockPosition == QInternal::LeftDock || dockPosition == QInternal::TopDock;
3393 const bool separatorIsWithinDock = separator.size() > 1;
3395 if (separatorIsWithinDock) {
3399 QDockAreaLayoutInfo *info =
this->info(separator);
3400 delta = pick(info->o, dest - origin);
3402 delta = info->separatorMove(dockPosition, delta);
3403 info->apply(QWidgetAnimator::AnimationRule::Stop);
3413 QList<QLayoutStruct> list;
3416 getGrid(
nullptr, &list);
3418 getGrid(&list,
nullptr);
3420 const int sep_index = isLeftOrTop ? 0 : 1;
3421 const Qt::Orientation o = isHorizontal ? Qt::Horizontal : Qt::Vertical;
3423 delta = pick(o, dest - origin);
3424 delta = separatorMoveHelper(list, sep_index, delta, sep);
3426 fallbackToSizeHints =
false;
3429 setGrid(
nullptr, &list);
3431 setGrid(&list,
nullptr);
3433 apply(QWidgetAnimator::AnimationRule::Stop);
3438int QDockAreaLayoutInfo::separatorMove(
const QList<
int> &separator,
const QPoint &origin,
3442 int index = separator.last();
3443 QDockAreaLayoutInfo *info =
this->info(separator);
3444 delta = pick(info->o, dest - origin);
3446 delta = info->separatorMove(index, delta);
3447 info->apply(QWidgetAnimator::AnimationRule::Stop);
3451#if QT_CONFIG(tabbar)
3454void QDockAreaLayout::updateSeparatorWidgets()
const
3458 for (
int i = 0; i < QInternal::DockCount; ++i) {
3459 const QDockAreaLayoutInfo &dock = docks[i];
3464 if (j < separatorWidgets.size()) {
3465 sepWidget = separatorWidgets.at(j);
3467 qWarning(
"QDockAreaLayout::updateSeparatorWidgets: null separator widget");
3468 sepWidget = qt_mainwindow_layout(mainWindow)->getSeparatorWidget();
3469 separatorWidgets[j] = sepWidget;
3472 sepWidget = qt_mainwindow_layout(mainWindow)->getSeparatorWidget();
3473 separatorWidgets.append(sepWidget);
3477 Q_ASSERT(sepWidget);
3478 raiseSeparatorWidget(sepWidget);
3480 QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
3481 sepWidget->setGeometry(sepRect);
3482 sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
3485 for (
int i = j; i < separatorWidgets.size(); ++i)
3486 separatorWidgets.at(i)->hide();
3488 separatorWidgets.resize(j);
3492QLayoutItem *QDockAreaLayout::itemAt(
int *x,
int index)
const
3494 Q_ASSERT(x !=
nullptr);
3496 for (
int i = 0; i < QInternal::DockCount; ++i) {
3497 const QDockAreaLayoutInfo &dock = docks[i];
3498 if (QLayoutItem *ret = dock.itemAt(x, index))
3502 if (centralWidgetItem && (*x)++ == index)
3503 return centralWidgetItem;
3508QLayoutItem *QDockAreaLayout::takeAt(
int *x,
int index)
3510 Q_ASSERT(x !=
nullptr);
3512 for (
int i = 0; i < QInternal::DockCount; ++i) {
3513 QDockAreaLayoutInfo &dock = docks[i];
3514 if (QLayoutItem *ret = dock.takeAt(x, index))
3518 if (centralWidgetItem && (*x)++ == index) {
3519 QLayoutItem *ret = centralWidgetItem;
3520 centralWidgetItem =
nullptr;
3527void QDockAreaLayout::deleteAllLayoutItems()
3529 for (
int i = 0; i < QInternal::DockCount; ++i)
3530 docks[i].deleteAllLayoutItems();
3533#if QT_CONFIG(tabbar)
3534QSet<QTabBar*> QDockAreaLayout::usedTabBars()
const
3536 QSet<QTabBar*> result;
3537 for (
int i = 0; i < QInternal::DockCount; ++i) {
3538 const QDockAreaLayoutInfo &dock = docks[i];
3539 result += dock.usedTabBars();
3545QSet<QWidget*> QDockAreaLayout::usedSeparatorWidgets()
const
3547 QSet<QWidget*> result;
3548 const int numSeparators = separatorWidgets.size();
3549 result.reserve(numSeparators);
3550 for (
int i = 0; i < numSeparators; ++i)
3551 result << separatorWidgets.at(i);
3552 for (
int i = 0; i < QInternal::DockCount; ++i) {
3553 const QDockAreaLayoutInfo &dock = docks[i];
3554 result += dock.usedSeparatorWidgets();
3560QRect QDockAreaLayout::gapRect(
const QList<
int> &path)
const
3562 const QDockAreaLayoutInfo *info =
this->info(path);
3563 if (info ==
nullptr)
3565 int index = path.last();
3566 if (index < 0 || index >= info->item_list.size())
3568 return info->itemRect(index,
true);
3571void QDockAreaLayout::keepSize(QDockWidget *w)
3573 QList<
int> path = indexOf(w);
3576 QDockAreaLayoutItem &item =
this->item(path);
3577 if (item.size != -1)
3578 item.flags |= QDockAreaLayoutItem::KeepSize;
3581void QDockAreaLayout::styleChangedEvent()
3583 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)