8#if QT_CONFIG(dockwidget)
9#include "qdockarealayout_p.h"
10#include "qdockwidget.h"
11#include "qdockwidget_p.h"
14#include "qtoolbar_p.h"
16#include "qtoolbarlayout_p.h"
19#if QT_CONFIG(rubberband)
20#include "qrubberband.h"
26#include <qapplication.h>
27#if QT_CONFIG(draganddrop)
31#if QT_CONFIG(statusbar)
32#include <qstatusbar.h>
36#include <qstylepainter.h>
37#include <qvarlengtharray.h>
42#ifndef QT_NO_DEBUG_STREAM
44# include <qtextstream.h>
47#include <private/qmenu_p.h>
48#include <private/qapplication_p.h>
49#include <private/qlayoutengine_p.h>
50#include <private/qwidgetresizehandler_p.h>
52#include <QScopedValueRollback>
56using namespace Qt::StringLiterals;
57using StateMarkers = QMainWindowLayoutState::StateMarkers;
60using StateMarkers = QMainWindowLayoutState::StateMarkers;
64 return options.testFlag(QMainWindow::AnimatedDocks) ? QWidgetAnimator::AnimationRule::Run
65 : QWidgetAnimator::AnimationRule::Stop;
69
70
72#if QT_CONFIG(dockwidget) && !defined(QT_NO_DEBUG_STREAM)
74static void dumpLayout(QTextStream &qout,
const QDockAreaLayoutInfo &layout, QString indent);
76static void dumpLayout(QTextStream &qout,
const QDockAreaLayoutItem &item, QString indent)
78 qout << indent <<
"QDockAreaLayoutItem: "
79 <<
"pos: " << item.pos <<
" size:" << item.size
80 <<
" gap:" << (item.flags & QDockAreaLayoutItem::GapItem)
81 <<
" keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize) <<
'\n';
83 if (item.widgetItem !=
nullptr) {
84 qout << indent <<
"widget: "
85 << item.widgetItem->widget()->metaObject()->className()
86 <<
" \"" << item.widgetItem->widget()->windowTitle() <<
"\"\n";
87 }
else if (item.subinfo !=
nullptr) {
88 qout << indent <<
"subinfo:\n";
89 dumpLayout(qout, *item.subinfo, indent +
" "_L1);
90 }
else if (item.placeHolderItem !=
nullptr) {
91 QRect r = item.placeHolderItem->topLevelRect;
92 qout << indent <<
"placeHolder: "
93 <<
"pos: " << item.pos <<
" size:" << item.size
94 <<
" gap:" << (item.flags & QDockAreaLayoutItem::GapItem)
95 <<
" keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize)
96 <<
" objectName:" << item.placeHolderItem->objectName
97 <<
" hidden:" << item.placeHolderItem->hidden
98 <<
" window:" << item.placeHolderItem->window
99 <<
" rect:" << r.x() <<
',' << r.y() <<
' '
100 << r.width() <<
'x' << r.height() <<
'\n';
104static void dumpLayout(QTextStream &qout,
const QDockAreaLayoutInfo &layout, QString indent)
106 const QSize minSize = layout.minimumSize();
107 qout << indent <<
"QDockAreaLayoutInfo: "
108 << layout.rect.left() <<
','
109 << layout.rect.top() <<
' '
110 << layout.rect.width() <<
'x'
111 << layout.rect.height()
112 <<
" min size: " << minSize.width() <<
',' << minSize.height()
113 <<
" orient:" << layout.o
115 <<
" tabbed:" << layout.tabbed
116 <<
" tbshape:" << layout.tabBarShape
122 for (
int i = 0; i < layout.item_list.size(); ++i) {
123 qout << indent <<
"Item: " << i <<
'\n';
124 dumpLayout(qout, layout.item_list.at(i), indent +
" "_L1);
128static void dumpLayout(QTextStream &qout,
const QDockAreaLayout &layout)
130 qout <<
"QDockAreaLayout: "
131 << layout.rect.left() <<
','
132 << layout.rect.top() <<
' '
133 << layout.rect.width() <<
'x'
134 << layout.rect.height() <<
'\n';
136 qout <<
"TopDockArea:\n";
137 dumpLayout(qout, layout.docks[QInternal::TopDock],
" "_L1);
138 qout <<
"LeftDockArea:\n";
139 dumpLayout(qout, layout.docks[QInternal::LeftDock],
" "_L1);
140 qout <<
"RightDockArea:\n";
141 dumpLayout(qout, layout.docks[QInternal::RightDock],
" "_L1);
142 qout <<
"BottomDockArea:\n";
143 dumpLayout(qout, layout.docks[QInternal::BottomDock],
" "_L1);
146QDebug operator<<(QDebug debug,
const QDockAreaLayout &layout)
150 dumpLayout(str, layout);
155QDebug operator<<(QDebug debug,
const QMainWindowLayout *layout)
158 return std::move(debug) << layout->layoutState.dockAreaLayout;
159 return debug <<
"QMainWindowLayout(0x0)";
165static void dumpItemLists(
const QMainWindowLayout *layout,
const char *function,
const char *comment)
167 for (
int i = 0; i < QInternal::DockCount; ++i) {
168 const auto &list = layout->layoutState.dockAreaLayout.docks[i].item_list;
171 qDebug() << function << comment <<
"Dock" << i << list;
174#define DUMP(comment) dumpItemLists(this, __FUNCTION__, comment)
179#ifndef QT_NO_DEBUG_STREAM
180QDebug operator<<(QDebug debug, StateMarkers marker)
182#define CASE(val) case QMainWindowLayoutState::StateMarkers::val:
183 debug.noquote().nospace() << "StateMarkers::" << #val;
186 QDebugStateSaver saver(debug);
188 CASE(FloatingDockWidgetTab);
201 stream << uchar(marker);
202 qCDebug(lcQpaDockWidgets) <<
"Writing state marker" << marker;
210 marker =
static_cast<StateMarkers>(m);
211 qCDebug(lcQpaDockWidgets) <<
"Reading state marker" << marker;
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
249#if QT_CONFIG(dockwidget)
250class QDockWidgetGroupLayout :
public QLayout,
251 public QMainWindowLayoutSeparatorHelper<QDockWidgetGroupLayout>
253 QWidgetResizeHandler *resizer;
255 QDockWidgetGroupLayout(QDockWidgetGroupWindow* parent) : QLayout(parent) {
256 setSizeConstraint(QLayout::SetMinAndMaxSize);
257 resizer =
new QWidgetResizeHandler(parent);
259 ~QDockWidgetGroupLayout() {
260 layoutState.deleteAllLayoutItems();
263 void addItem(QLayoutItem*) override { Q_UNREACHABLE(); }
264 int count()
const override {
return 0; }
265 QLayoutItem* itemAt(
int index)
const override
268 return layoutState.itemAt(&x, index);
270 QLayoutItem* takeAt(
int index) override
273 QLayoutItem *ret = layoutState.takeAt(&x, index);
274 if (savedState.rect.isValid() && ret->widget()) {
276 QList<
int> path = savedState.indexOf(ret->widget());
278 savedState.remove(path);
280 path = layoutState.indexOf(ret->widget());
282 layoutState.remove(path);
286 QSize sizeHint()
const override
288 int fw = frameWidth();
289 return layoutState.sizeHint() + QSize(fw, fw);
291 QSize minimumSize()
const override
293 int fw = frameWidth();
294 return layoutState.minimumSize() + QSize(fw, fw);
296 QSize maximumSize()
const override
298 int fw = frameWidth();
299 return layoutState.maximumSize() + QSize(fw, fw);
301 void setGeometry(
const QRect&r) override
303 groupWindow()->destroyOrHideIfEmpty();
304 QDockAreaLayoutInfo *li = dockAreaLayoutInfo();
307 int fw = frameWidth();
309 li->reparentWidgets(parentWidget());
311 li->rect = r.adjusted(fw, fw, -fw, -fw);
313 li->apply(QWidgetAnimator::AnimationRule::Stop);
314 if (savedState.rect.isValid())
315 savedState.rect = li->rect;
316 resizer->setEnabled(!nativeWindowDeco());
319 QDockAreaLayoutInfo *dockAreaLayoutInfo() {
return &layoutState; }
321#if QT_CONFIG(toolbar)
322 QToolBarAreaLayout *toolBarAreaLayout()
328 bool nativeWindowDeco()
const
330 return groupWindow()->hasNativeDecos();
333 int frameWidth()
const
335 return nativeWindowDeco() ? 0 :
336 parentWidget()->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth,
nullptr, parentWidget());
339 QDockWidgetGroupWindow *groupWindow()
const
341 return static_cast<QDockWidgetGroupWindow *>(parent());
344 QDockAreaLayoutInfo layoutState;
345 QDockAreaLayoutInfo savedState;
348bool QDockWidgetGroupWindow::event(QEvent *e)
350 auto lay =
static_cast<QDockWidgetGroupLayout *>(layout());
351 if (lay && lay->windowEvent(e))
358 if (QDockWidget *dw = activeTabbedDockWidget()) {
367 if (QDockWidget *dw = activeTabbedDockWidget())
368 static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(dw))->moveEvent(
static_cast<QMoveEvent*>(e));
371 case QEvent::NonClientAreaMouseMove:
372 case QEvent::NonClientAreaMouseButtonPress:
373 case QEvent::NonClientAreaMouseButtonRelease:
374 case QEvent::NonClientAreaMouseButtonDblClick:
377 if (QDockWidget *dw = activeTabbedDockWidget())
378 static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(dw))->nonClientAreaMouseEvent(
static_cast<QMouseEvent*>(e));
381 case QEvent::ChildAdded:
382 if (qobject_cast<QDockWidget *>(
static_cast<QChildEvent*>(e)->child()))
385 case QEvent::LayoutRequest:
387 destroyOrHideIfEmpty();
390 updateCurrentGapRect();
396 return QWidget::event(e);
399void QDockWidgetGroupWindow::paintEvent(QPaintEvent *)
401 QDockWidgetGroupLayout *lay =
static_cast<QDockWidgetGroupLayout *>(layout());
402 bool nativeDeco = lay->nativeWindowDeco();
405 QStyleOptionFrame framOpt;
406 framOpt.initFrom(
this);
407 QStylePainter p(
this);
408 p.drawPrimitive(QStyle::PE_FrameDockWidget, framOpt);
412QDockAreaLayoutInfo *QDockWidgetGroupWindow::layoutInfo()
const
414 return static_cast<QDockWidgetGroupLayout *>(layout())->dockAreaLayoutInfo();
419
420
421
422
423const QDockAreaLayoutInfo *QDockWidgetGroupWindow::tabLayoutInfo()
const
425 const QDockAreaLayoutInfo *info = layoutInfo();
426 while (info && !info->tabbed) {
429 const QDockAreaLayoutInfo *next =
nullptr;
430 bool isSingle =
false;
431 for (
const auto &item : info->item_list) {
432 if (item.skip() || (item.flags & QDockAreaLayoutItem::GapItem))
434 if (next || isSingle)
438 else if (item.widgetItem)
449
450
451QDockWidget *QDockWidgetGroupWindow::activeTabbedDockWidget()
const
453 QDockWidget *dw =
nullptr;
454 const QDockAreaLayoutInfo *info = tabLayoutInfo();
457 if (info->tabBar && info->tabBar->currentIndex() >= 0) {
458 int i = info->tabIndexToListIndex(info->tabBar->currentIndex());
460 const QDockAreaLayoutItem &item = info->item_list.at(i);
462 dw = qobject_cast<QDockWidget *>(item.widgetItem->widget());
466 for (
int i = 0; !dw && i < info->item_list.size(); ++i) {
467 const QDockAreaLayoutItem &item = info->item_list.at(i);
470 if (!item.widgetItem)
472 dw = qobject_cast<QDockWidget *>(item.widgetItem->widget());
480
481
482
483void QDockWidgetGroupWindow::destroyOrHideIfEmpty()
485 const QDockAreaLayoutInfo *info = layoutInfo();
486 if (!info->isEmpty()) {
491 if (!info->item_list.isEmpty()) {
497 const auto dockWidgetsList = dockWidgets();
498 for (QDockWidget *dw : dockWidgetsList) {
499 const bool wasFloating = dw->isFloating();
500 const bool wasHidden = dw->isHidden();
501 dw->setParent(parentWidget());
502 qCDebug(lcQpaDockWidgets) <<
"Reparented:" << dw <<
"to" << parentWidget() <<
"by" <<
this;
504 dw->setFloating(
true);
507 QMainWindowLayout *ml =
508 qt_mainwindow_layout(
static_cast<QMainWindow *>(parentWidget()));
509 Qt::DockWidgetArea area = ml->dockWidgetArea(
this);
510 if (area == Qt::NoDockWidgetArea)
511 area = Qt::LeftDockWidgetArea;
512 static_cast<QMainWindow *>(parentWidget())->addDockWidget(area, dw);
513 qCDebug(lcQpaDockWidgets) <<
"Redocked to Mainwindow:" << area << dw <<
"by" <<
this;
518 Q_ASSERT(qobject_cast<QMainWindow *>(parentWidget()));
519 auto *mainWindow =
static_cast<QMainWindow *>(parentWidget());
520 QMainWindowLayout *mwLayout = qt_mainwindow_layout(mainWindow);
521 QDockAreaLayoutInfo &parentInfo = mwLayout->layoutState.dockAreaLayout.docks[layoutInfo()->dockPos];
522 std::unique_ptr<QLayoutItem> cleanup = parentInfo.takeWidgetItem(
this);
523 parentInfo.remove(
this);
528
529
530
531
532bool QDockWidgetGroupWindow::hasVisibleDockWidgets()
const
534 const auto &children = findChildren<QDockWidget *>(Qt::FindChildrenRecursively);
535 for (
auto child : children) {
540 if (!child->testAttribute(Qt::WA_WState_Hidden))
547
548
549void QDockWidgetGroupWindow::adjustFlags()
551 Qt::WindowFlags oldFlags = windowFlags();
552 Qt::WindowFlags flags = oldFlags;
555 QDockWidget *top = activeTabbedDockWidget();
557 QDockWidget *top =
nullptr;
561 ((oldFlags & ~Qt::FramelessWindowHint) | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
562 }
else if (
static_cast<QDockWidgetGroupLayout *>(layout())->nativeWindowDeco()) {
563 flags |= Qt::CustomizeWindowHint | Qt::WindowTitleHint;
564 flags.setFlag(Qt::WindowCloseButtonHint, top->features() & QDockWidget::DockWidgetClosable);
565 flags &= ~Qt::FramelessWindowHint;
567 flags &= ~(Qt::WindowCloseButtonHint | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
568 flags |= Qt::FramelessWindowHint;
571 if (oldFlags != flags) {
574 setWindowFlags(flags);
575 const bool gainedNativeDecos = (oldFlags & Qt::FramelessWindowHint) && !(flags & Qt::FramelessWindowHint);
576 const bool lostNativeDecos = !(oldFlags & Qt::FramelessWindowHint) && (flags & Qt::FramelessWindowHint);
580 if (lostNativeDecos) {
581 QRect newGeometry = geometry();
582 newGeometry.setTop(frameGeometry().top());
583 const int bottomFrame = geometry().top() - frameGeometry().top();
584 m_removedFrameSize = QSize((frameSize() - size()).width(), bottomFrame);
585 setGeometry(newGeometry);
586 }
else if (gainedNativeDecos && m_removedFrameSize.isValid()) {
587 QRect r = geometry();
588 r.adjust(-m_removedFrameSize.width() / 2, 0,
589 -m_removedFrameSize.width() / 2, -m_removedFrameSize.height());
591 m_removedFrameSize = QSize();
594 setVisible(hasVisibleDockWidgets());
597 QWidget *titleBarOf = top ? top : parentWidget();
598 setWindowTitle(titleBarOf->windowTitle());
599 setWindowIcon(titleBarOf->windowIcon());
602bool QDockWidgetGroupWindow::hasNativeDecos()
const
605 QDockWidget *dw = activeTabbedDockWidget();
609 if (!QDockWidgetLayout::wmSupportsNativeWindowDeco())
612 return dw->titleBarWidget() ==
nullptr;
619QT_WARNING_DISABLE_GCC(
"-Waggressive-loop-optimizations")
621
622
623
624
625
626
627bool QDockWidgetGroupWindow::hover(QLayoutItem *widgetItem,
const QPoint &mousePos)
629 QDockAreaLayoutInfo &savedState =
static_cast<QDockWidgetGroupLayout *>(layout())->savedState;
630 if (savedState.isEmpty())
631 savedState = *layoutInfo();
633 QMainWindow::DockOptions opts =
static_cast<QMainWindow *>(parentWidget())->dockOptions();
634 QDockAreaLayoutInfo newState = savedState;
635 bool nestingEnabled =
636 (opts & QMainWindow::AllowNestedDocks) && !(opts & QMainWindow::ForceTabbedDocks);
637 QDockAreaLayoutInfo::TabMode tabMode =
638#if !QT_CONFIG(tabbar)
639 QDockAreaLayoutInfo::NoTabs;
641 nestingEnabled ? QDockAreaLayoutInfo::AllowTabs : QDockAreaLayoutInfo::ForceTabs;
642 if (
auto group = qobject_cast<QDockWidgetGroupWindow *>(widgetItem->widget())) {
643 if (!group->tabLayoutInfo())
644 tabMode = QDockAreaLayoutInfo::NoTabs;
646 if (newState.tabbed) {
648 newState.item_list = { QDockAreaLayoutItem(
new QDockAreaLayoutInfo(newState)) };
649 newState.item_list.first().size = pick(savedState.o, savedState.rect.size());
650 newState.tabbed =
false;
651 newState.tabBar =
nullptr;
655 auto newGapPos = newState.gapIndex(mousePos, nestingEnabled, tabMode);
656 Q_ASSERT(!newGapPos.isEmpty());
660 if (newGapPos == currentGapPos || newState.hasGapItem(newGapPos))
663 currentGapPos = newGapPos;
664 newState.insertGap(currentGapPos, widgetItem);
666 *layoutInfo() = std::move(newState);
667 updateCurrentGapRect();
668 const auto rule = toAnimationRule(opts);
669 layoutInfo()->apply(rule);
674void QDockWidgetGroupWindow::updateCurrentGapRect()
676 if (!currentGapPos.isEmpty())
677 currentGapRect = layoutInfo()->info(currentGapPos)->itemRect(currentGapPos.last(),
true);
681
682
683void QDockWidgetGroupWindow::restore()
685 QDockAreaLayoutInfo &savedState =
static_cast<QDockWidgetGroupLayout *>(layout())->savedState;
686 if (!savedState.isEmpty()) {
687 *layoutInfo() = savedState;
688 savedState = QDockAreaLayoutInfo();
690 currentGapRect = QRect();
691 currentGapPos.clear();
693 layoutInfo()->fitItems();
694 const auto *mw =
static_cast<QMainWindow *>(parentWidget());
695 const auto rule = toAnimationRule(mw->dockOptions());
696 layoutInfo()->apply(rule);
700
701
702void QDockWidgetGroupWindow::apply()
704 static_cast<QDockWidgetGroupLayout *>(layout())->savedState.clear();
705 currentGapRect = QRect();
706 layoutInfo()->plug(currentGapPos);
707 currentGapPos.clear();
709 layoutInfo()->apply(QWidgetAnimator::AnimationRule::Stop);
712void QDockWidgetGroupWindow::childEvent(QChildEvent *event)
714 switch (event->type()) {
715 case QEvent::ChildRemoved:
716 if (
auto *dockWidget = qobject_cast<QDockWidget *>(event->child()))
717 dockWidget->removeEventFilter(
this);
718 destroyIfSingleItemLeft();
720 case QEvent::ChildAdded:
721 if (
auto *dockWidget = qobject_cast<QDockWidget *>(event->child())) {
722 dockWidget->installEventFilter(
this);
723 if (objectName().isEmpty())
724 setObjectName(dockWidget->objectName() + QLatin1String(
"_groupWindow"));
732bool QDockWidgetGroupWindow::eventFilter(QObject *obj, QEvent *event)
734 auto *dockWidget = qobject_cast<QDockWidget *>(obj);
736 return QWidget::eventFilter(obj, event);
738 switch (event->type()) {
742 reparentToMainWindow(dockWidget);
743 dockWidget->setFloating(
false);
749 if (dockWidget->isVisible())
756 return QWidget::eventFilter(obj, event);
759void QDockWidgetGroupWindow::destroyIfSingleItemLeft()
761 const auto &dockWidgets =
this->dockWidgets();
764 if (dockWidgets.count() != 1)
767 auto *lastDockWidget = dockWidgets.at(0);
772 if (layoutInfo()->indexOf(lastDockWidget).isEmpty())
775 Q_ASSERT(qobject_cast<QMainWindow *>(parentWidget()));
776 auto *mainWindow =
static_cast<QMainWindow *>(parentWidget());
777 QMainWindowLayout *mwLayout = qt_mainwindow_layout(mainWindow);
780 mwLayout->unplug(lastDockWidget, QDockWidgetPrivate::DragScope::Widget);
781 const QPoint position = pos();
785 reparentToMainWindow(lastDockWidget);
789 if (lastDockWidget->isFloating())
790 lastDockWidget->move(position);
793 layoutInfo()->item_list.clear();
795 destroyOrHideIfEmpty();
798void QDockWidgetGroupWindow::reparentToMainWindow(QDockWidget *dockWidget)
804 Q_ASSERT(qobject_cast<QMainWindow *>(parentWidget()));
805 auto *mainWindow =
static_cast<QMainWindow *>(parentWidget());
806 QMainWindowLayout *mwLayout = qt_mainwindow_layout(mainWindow);
808 mwLayout->widgetAnimator.abort(dockWidget);
815 mwLayout->savedState.clear();
816 QDockAreaLayoutInfo &parentInfo = mwLayout->layoutState.dockAreaLayout.docks[layoutInfo()->dockPos];
817 dockWidget->removeEventFilter(
this);
818 parentInfo.add(dockWidget);
819 layoutInfo()->remove(dockWidget);
820 const bool wasFloating = dockWidget->isFloating();
821 const bool wasVisible = dockWidget->isVisible();
822 dockWidget->setParent(mainWindow);
823 dockWidget->setFloating(wasFloating);
824 dockWidget->setVisible(wasVisible);
829
830
834QMainWindowLayoutState::QMainWindowLayoutState(QMainWindow *win)
836#if QT_CONFIG(toolbar)
837 toolBarAreaLayout(win),
839#if QT_CONFIG(dockwidget)
849QSize QMainWindowLayoutState::sizeHint()
const
854#if QT_CONFIG(dockwidget)
855 result = dockAreaLayout.sizeHint();
857 if (centralWidgetItem)
858 result = centralWidgetItem->sizeHint();
861#if QT_CONFIG(toolbar)
862 result = toolBarAreaLayout.sizeHint(result);
868QSize QMainWindowLayoutState::minimumSize()
const
872#if QT_CONFIG(dockwidget)
873 result = dockAreaLayout.minimumSize();
875 if (centralWidgetItem)
876 result = centralWidgetItem->minimumSize();
879#if QT_CONFIG(toolbar)
880 result = toolBarAreaLayout.minimumSize(result);
887
888
889
890
891bool QMainWindowLayoutState::fits()
const
893 Q_ASSERT(mainWindow);
897#if QT_CONFIG(dockwidget)
898 size = dockAreaLayout.minimumStableSize();
901#if QT_CONFIG(toolbar)
902 size.rwidth() += toolBarAreaLayout.docks[QInternal::LeftDock].rect.width();
903 size.rwidth() += toolBarAreaLayout.docks[QInternal::RightDock].rect.width();
904 size.rheight() += toolBarAreaLayout.docks[QInternal::TopDock].rect.height();
905 size.rheight() += toolBarAreaLayout.docks[QInternal::BottomDock].rect.height();
908 return size.width() <= mainWindow->width() && size.height() <= mainWindow->height();
911void QMainWindowLayoutState::apply(QWidgetAnimator::AnimationRule rule)
913#if QT_CONFIG(toolbar)
914 toolBarAreaLayout.apply(rule);
917#if QT_CONFIG(dockwidget)
919 dockAreaLayout.apply(rule);
921 if (centralWidgetItem) {
922 QMainWindowLayout *layout = qt_mainwindow_layout(mainWindow);
924 layout->widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect, rule);
929void QMainWindowLayoutState::fitLayout()
932#if !QT_CONFIG(toolbar)
935 toolBarAreaLayout.rect = rect;
936 r = toolBarAreaLayout.fitLayout();
939#if QT_CONFIG(dockwidget)
940 dockAreaLayout.rect = r;
941 dockAreaLayout.fitLayout();
943 centralWidgetRect = r;
947void QMainWindowLayoutState::deleteAllLayoutItems()
949#if QT_CONFIG(toolbar)
950 toolBarAreaLayout.deleteAllLayoutItems();
953#if QT_CONFIG(dockwidget)
954 dockAreaLayout.deleteAllLayoutItems();
958void QMainWindowLayoutState::deleteCentralWidgetItem()
960#if QT_CONFIG(dockwidget)
961 delete dockAreaLayout.centralWidgetItem;
962 dockAreaLayout.centralWidgetItem =
nullptr;
964 delete centralWidgetItem;
965 centralWidgetItem = 0;
969QLayoutItem *QMainWindowLayoutState::itemAt(
int index,
int *x)
const
971#if QT_CONFIG(toolbar)
972 if (QLayoutItem *ret = toolBarAreaLayout.itemAt(x, index))
976#if QT_CONFIG(dockwidget)
977 if (QLayoutItem *ret = dockAreaLayout.itemAt(x, index))
980 if (centralWidgetItem && (*x)++ == index)
981 return centralWidgetItem;
987QLayoutItem *QMainWindowLayoutState::takeAt(
int index,
int *x)
989#if QT_CONFIG(toolbar)
990 if (QLayoutItem *ret = toolBarAreaLayout.takeAt(x, index))
994#if QT_CONFIG(dockwidget)
995 if (QLayoutItem *ret = dockAreaLayout.takeAt(x, index))
998 if (centralWidgetItem && (*x)++ == index) {
999 QLayoutItem *ret = centralWidgetItem;
1000 centralWidgetItem =
nullptr;
1008QList<
int> QMainWindowLayoutState::indexOf(QWidget *widget)
const
1012#if QT_CONFIG(toolbar)
1014 if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
1015 result = toolBarAreaLayout.indexOf(toolBar);
1016 if (!result.isEmpty())
1022#if QT_CONFIG(dockwidget)
1024 if (qobject_cast<QDockWidget *>(widget) || qobject_cast<QDockWidgetGroupWindow *>(widget)) {
1025 result = dockAreaLayout.indexOf(widget);
1026 if (!result.isEmpty())
1035bool QMainWindowLayoutState::contains(QWidget *widget)
const
1037#if QT_CONFIG(dockwidget)
1038 if (dockAreaLayout.centralWidgetItem !=
nullptr && dockAreaLayout.centralWidgetItem->widget() == widget)
1040 if (!dockAreaLayout.indexOf(widget).isEmpty())
1043 if (centralWidgetItem && centralWidgetItem->widget() == widget)
1047#if QT_CONFIG(toolbar)
1048 if (!toolBarAreaLayout.indexOf(widget).isEmpty())
1054void QMainWindowLayoutState::setCentralWidget(QWidget *widget)
1056 QLayoutItem *item =
nullptr;
1058 deleteCentralWidgetItem();
1060 if (widget !=
nullptr)
1061 item =
new QWidgetItemV2(widget);
1063#if QT_CONFIG(dockwidget)
1064 dockAreaLayout.centralWidgetItem = item;
1066 centralWidgetItem = item;
1070QWidget *QMainWindowLayoutState::centralWidget()
const
1072 QLayoutItem *item =
nullptr;
1074#if QT_CONFIG(dockwidget)
1075 item = dockAreaLayout.centralWidgetItem;
1077 item = centralWidgetItem;
1080 if (item !=
nullptr)
1081 return item->widget();
1085QList<
int> QMainWindowLayoutState::gapIndex(QWidget *widget,
1086 const QPoint &pos)
const
1090#if QT_CONFIG(toolbar)
1092 if (qobject_cast<QToolBar*>(widget) !=
nullptr) {
1093 result = toolBarAreaLayout.gapIndex(pos);
1094 if (!result.isEmpty())
1100#if QT_CONFIG(dockwidget)
1102 if (qobject_cast<QDockWidget *>(widget) !=
nullptr
1103 || qobject_cast<QDockWidgetGroupWindow *>(widget)) {
1104 bool disallowTabs =
false;
1105#if QT_CONFIG(tabbar)
1106 if (
auto *group = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
1107 if (!group->tabLayoutInfo())
1108 disallowTabs =
true;
1111 result = dockAreaLayout.gapIndex(pos, disallowTabs);
1112 if (!result.isEmpty())
1121bool QMainWindowLayoutState::insertGap(
const QList<
int> &path, QLayoutItem *item)
1126 int i = path.first();
1128#if QT_CONFIG(toolbar)
1130 Q_ASSERT(qobject_cast<QToolBar*>(item->widget()) !=
nullptr);
1131 return toolBarAreaLayout.insertGap(path.mid(1), item);
1135#if QT_CONFIG(dockwidget)
1137 Q_ASSERT(qobject_cast<QDockWidget*>(item->widget()) || qobject_cast<QDockWidgetGroupWindow*>(item->widget()));
1138 return dockAreaLayout.insertGap(path.mid(1), item);
1145void QMainWindowLayoutState::remove(
const QList<
int> &path)
1147 int i = path.first();
1149#if QT_CONFIG(toolbar)
1151 toolBarAreaLayout.remove(path.mid(1));
1154#if QT_CONFIG(dockwidget)
1156 dockAreaLayout.remove(path.mid(1));
1160void QMainWindowLayoutState::remove(QLayoutItem *item)
1162#if QT_CONFIG(toolbar)
1163 toolBarAreaLayout.remove(item);
1166#if QT_CONFIG(dockwidget)
1168 if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(item->widget())) {
1169 QList<
int> path = dockAreaLayout.indexOf(dockWidget);
1170 if (!path.isEmpty())
1171 dockAreaLayout.remove(path);
1176void QMainWindowLayoutState::clear()
1178#if QT_CONFIG(toolbar)
1179 toolBarAreaLayout.clear();
1182#if QT_CONFIG(dockwidget)
1183 dockAreaLayout.clear();
1185 centralWidgetRect = QRect();
1191bool QMainWindowLayoutState::isValid()
const
1193 return rect.isValid();
1196QLayoutItem *QMainWindowLayoutState::item(
const QList<
int> &path)
1198 int i = path.first();
1200#if QT_CONFIG(toolbar)
1202 const QToolBarAreaLayoutItem *tbItem = toolBarAreaLayout.item(path.mid(1));
1204 return tbItem->widgetItem;
1208#if QT_CONFIG(dockwidget)
1210 return dockAreaLayout.item(path.mid(1)).widgetItem;
1216QRect QMainWindowLayoutState::itemRect(
const QList<
int> &path)
const
1218 int i = path.first();
1220#if QT_CONFIG(toolbar)
1222 return toolBarAreaLayout.itemRect(path.mid(1));
1225#if QT_CONFIG(dockwidget)
1227 return dockAreaLayout.itemRect(path.mid(1));
1233QRect QMainWindowLayoutState::gapRect(
const QList<
int> &path)
const
1235 int i = path.first();
1237#if QT_CONFIG(toolbar)
1239 return toolBarAreaLayout.itemRect(path.mid(1));
1242#if QT_CONFIG(dockwidget)
1244 return dockAreaLayout.gapRect(path.mid(1));
1250QLayoutItem *QMainWindowLayoutState::plug(
const QList<
int> &path)
1252 int i = path.first();
1254#if QT_CONFIG(toolbar)
1256 return toolBarAreaLayout.plug(path.mid(1));
1259#if QT_CONFIG(dockwidget)
1261 return dockAreaLayout.plug(path.mid(1));
1267QLayoutItem *QMainWindowLayoutState::unplug(
const QList<
int> &path, QMainWindowLayoutState *other)
1269 int i = path.first();
1271#if !QT_CONFIG(toolbar)
1275 return toolBarAreaLayout.unplug(path.mid(1), other ? &other->toolBarAreaLayout :
nullptr);
1278#if QT_CONFIG(dockwidget)
1280 return dockAreaLayout.unplug(path.mid(1));
1286void QMainWindowLayoutState::saveState(QDataStream &stream)
const
1288#if QT_CONFIG(dockwidget)
1289 dockAreaLayout.saveState(stream);
1290#if QT_CONFIG(tabbar)
1291 const QList<QDockWidgetGroupWindow *> floatingTabs =
1292 mainWindow->findChildren<QDockWidgetGroupWindow *>(Qt::FindDirectChildrenOnly);
1294 for (QDockWidgetGroupWindow *floating : floatingTabs) {
1295 if (floating->layoutInfo()->isEmpty())
1297 stream << StateMarkers::FloatingDockWidgetTab;
1298 stream << floating->geometry();
1299 floating->layoutInfo()->saveState(stream);
1303#if QT_CONFIG(toolbar)
1304 toolBarAreaLayout.saveState(stream);
1309bool QMainWindowLayoutState::checkFormat(QDataStream &stream)
1311 while (!stream.atEnd()) {
1312 StateMarkers marker;
1316#if QT_CONFIG(toolbar)
1317 case StateMarkers::ToolBar:
1318 case StateMarkers::ToolBarEx:
1320 const auto toolBars = mainWindow->findChildren<QToolBar*>();
1321 if (!toolBarAreaLayout.restoreState(stream, toolBars,
static_cast<uchar>(marker), QInternal::Testing))
1327#if QT_CONFIG(dockwidget)
1328 case StateMarkers::DockWidget:
1330 const auto dockWidgets = mainWindow->findChildren<QDockWidget *>(Qt::FindChildrenRecursively);
1331 if (!dockAreaLayout.restoreState(stream, dockWidgets, QInternal::Testing))
1335#if QT_CONFIG(tabbar)
1336 case StateMarkers::FloatingDockWidgetTab:
1340 QDockAreaLayoutInfo info;
1341 auto dockWidgets = mainWindow->findChildren<QDockWidget *>(Qt::FindChildrenRecursively);
1342 if (!info.restoreState(stream, dockWidgets, QInternal::Testing))
1358bool QMainWindowLayoutState::restoreState(QDataStream &_stream,
1359 const QMainWindowLayoutState &oldState)
1363 while(!_stream.atEnd()) {
1365 QByteArray ba(length,
'\0');
1366 length = _stream.readRawData(ba.data(), ba.size());
1371 QDataStream ds(copy);
1372 ds.setVersion(_stream.version());
1373 if (!checkFormat(ds))
1376 QDataStream stream(copy);
1377 stream.setVersion(_stream.version());
1379 while (!stream.atEnd()) {
1380 StateMarkers marker;
1384#if QT_CONFIG(dockwidget)
1385 case StateMarkers::DockWidget:
1387 const auto dockWidgets = mainWindow->findChildren<QDockWidget *>(Qt::FindChildrenRecursively);
1388 if (!dockAreaLayout.restoreState(stream, dockWidgets, QInternal::Live))
1391 for (
auto *w : dockWidgets) {
1392 const QList<
int> path = dockAreaLayout.indexOf(w);
1393 if (path.isEmpty()) {
1394 QList<
int> oldPath = oldState.dockAreaLayout.indexOf(w);
1395 if (oldPath.isEmpty())
1397 QDockAreaLayoutInfo *info = dockAreaLayout.info(oldPath);
1398 if (info ==
nullptr) {
1406#if QT_CONFIG(tabwidget)
1407 case StateMarkers::FloatingDockWidgetTab:
1409 auto dockWidgets = mainWindow->findChildren<QDockWidget *>(Qt::FindChildrenRecursively);
1411 for (
auto *dockWidget : std::as_const(dockWidgets)) {
1412 QPointer<QDockWidgetGroupWindow> gw = qobject_cast<QDockWidgetGroupWindow *>(dockWidget->parent());
1415 const bool visible = gw->isVisible();
1416 gw->reparentToMainWindow(dockWidget);
1417 dockWidget->setFloating(
true);
1418 dockWidget->setVisible(visible);
1421 const auto groupWindows = mainWindow->findChildren<QDockWidgetGroupWindow *>();
1422 for (
auto *gw : groupWindows)
1423 Q_ASSERT(gw->dockWidgets().isEmpty());
1426 QDockWidgetGroupWindow* floatingTab = qt_mainwindow_layout(mainWindow)->createTabbedDockWindow();
1427 *floatingTab->layoutInfo() = QDockAreaLayoutInfo(
1428 &dockAreaLayout.sep, QInternal::LeftDock,
1429 Qt::Horizontal, QTabBar::RoundedSouth, mainWindow);
1432 QDockAreaLayoutInfo *info = floatingTab->layoutInfo();
1433 if (!info->restoreState(stream, dockWidgets, QInternal::Live))
1435 geometry = QDockAreaLayout::constrainedRect(geometry, floatingTab);
1436 floatingTab->move(geometry.topLeft());
1437 floatingTab->resize(geometry.size());
1441 if (info->onlyHasPlaceholders())
1442 info->reparentWidgets(floatingTab);
1444 floatingTab->show();
1450#if QT_CONFIG(toolbar)
1451 case StateMarkers::ToolBar:
1452 case StateMarkers::ToolBarEx:
1454 const auto toolBars = mainWindow->findChildren<QToolBar*>();
1455 if (!toolBarAreaLayout.restoreState(stream, toolBars,
static_cast<uchar>(marker), QInternal::Live))
1458 for (
auto *bar : toolBars) {
1459 const QList<
int> path = toolBarAreaLayout.indexOf(bar);
1460 if (path.isEmpty()) {
1461 const QList<
int> oldPath = oldState.toolBarAreaLayout.indexOf(bar);
1462 if (oldPath.isEmpty())
1464 toolBarAreaLayout.docks[oldPath.at(0)].insertToolBar(
nullptr, bar);
1480
1481
1483#if QT_CONFIG(toolbar)
1485static constexpr Qt::ToolBarArea validateToolBarArea(Qt::ToolBarArea area)
1488 case Qt::LeftToolBarArea:
1489 case Qt::RightToolBarArea:
1490 case Qt::TopToolBarArea:
1491 case Qt::BottomToolBarArea:
1496 return Qt::TopToolBarArea;
1499static QInternal::DockPosition toDockPos(Qt::ToolBarArea area)
1502 case Qt::LeftToolBarArea:
return QInternal::LeftDock;
1503 case Qt::RightToolBarArea:
return QInternal::RightDock;
1504 case Qt::TopToolBarArea:
return QInternal::TopDock;
1505 case Qt::BottomToolBarArea:
return QInternal::BottomDock;
1510 return QInternal::DockCount;
1513static Qt::ToolBarArea toToolBarArea(QInternal::DockPosition pos)
1516 case QInternal::LeftDock:
return Qt::LeftToolBarArea;
1517 case QInternal::RightDock:
return Qt::RightToolBarArea;
1518 case QInternal::TopDock:
return Qt::TopToolBarArea;
1519 case QInternal::BottomDock:
return Qt::BottomToolBarArea;
1522 return Qt::NoToolBarArea;
1525static inline Qt::ToolBarArea toToolBarArea(
int pos)
1527 return toToolBarArea(
static_cast<QInternal::DockPosition>(pos));
1530void QMainWindowLayout::addToolBarBreak(Qt::ToolBarArea area)
1532 area = validateToolBarArea(area);
1534 layoutState.toolBarAreaLayout.addToolBarBreak(toDockPos(area));
1535 if (savedState.isValid())
1536 savedState.toolBarAreaLayout.addToolBarBreak(toDockPos(area));
1541void QMainWindowLayout::insertToolBarBreak(QToolBar *before)
1543 layoutState.toolBarAreaLayout.insertToolBarBreak(before);
1544 if (savedState.isValid())
1545 savedState.toolBarAreaLayout.insertToolBarBreak(before);
1549void QMainWindowLayout::removeToolBarBreak(QToolBar *before)
1551 layoutState.toolBarAreaLayout.removeToolBarBreak(before);
1552 if (savedState.isValid())
1553 savedState.toolBarAreaLayout.removeToolBarBreak(before);
1557void QMainWindowLayout::moveToolBar(QToolBar *toolbar,
int pos)
1559 layoutState.toolBarAreaLayout.moveToolBar(toolbar, pos);
1560 if (savedState.isValid())
1561 savedState.toolBarAreaLayout.moveToolBar(toolbar, pos);
1566
1567void QMainWindowLayout::removeToolBar(QToolBar *toolbar)
1570 QObject::disconnect(parentWidget(), SIGNAL(iconSizeChanged(QSize)),
1571 toolbar, SLOT(_q_updateIconSize(QSize)));
1572 QObject::disconnect(parentWidget(), SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
1573 toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
1575 removeWidget(toolbar);
1580
1581
1582
1583
1586
1587
1588void QMainWindowLayout::addToolBar(Qt::ToolBarArea area,
1592 area = validateToolBarArea(area);
1594 addChildWidget(toolbar);
1595 QLayoutItem *item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar);
1596 if (savedState.isValid() && item) {
1598 savedState.toolBarAreaLayout.insertItem(toDockPos(area), item);
1603 toolbar->d_func()->updateWindowFlags(
false );
1607
1608
1609void QMainWindowLayout::insertToolBar(QToolBar *before, QToolBar *toolbar)
1611 addChildWidget(toolbar);
1612 QLayoutItem *item = layoutState.toolBarAreaLayout.insertToolBar(before, toolbar);
1613 if (savedState.isValid() && item) {
1615 savedState.toolBarAreaLayout.insertItem(before, item);
1617 if (!currentGapPos.isEmpty() && currentGapPos.constFirst() == 0) {
1618 currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
1619 if (!currentGapPos.isEmpty()) {
1620 currentGapPos.prepend(0);
1621 currentGapRect = layoutState.itemRect(currentGapPos);
1627Qt::ToolBarArea QMainWindowLayout::toolBarArea(
const QToolBar *toolbar)
const
1629 QInternal::DockPosition pos = layoutState.toolBarAreaLayout.findToolBar(toolbar);
1631 case QInternal::LeftDock:
return Qt::LeftToolBarArea;
1632 case QInternal::RightDock:
return Qt::RightToolBarArea;
1633 case QInternal::TopDock:
return Qt::TopToolBarArea;
1634 case QInternal::BottomDock:
return Qt::BottomToolBarArea;
1637 return Qt::NoToolBarArea;
1640bool QMainWindowLayout::toolBarBreak(QToolBar *toolBar)
const
1642 return layoutState.toolBarAreaLayout.toolBarBreak(toolBar);
1645void QMainWindowLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar)
const
1647 option->toolBarArea = toolBarArea(toolBar);
1648 layoutState.toolBarAreaLayout.getStyleOptionInfo(option, toolBar);
1651void QMainWindowLayout::toggleToolBarsVisible()
1653 layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible;
1654 if (!layoutState.mainWindow->isMaximized()) {
1655 QPoint topLeft = parentWidget()->geometry().topLeft();
1656 QRect r = parentWidget()->geometry();
1657 r = layoutState.toolBarAreaLayout.rectHint(r);
1659 parentWidget()->setGeometry(r);
1668
1669
1671#if QT_CONFIG(dockwidget)
1673static QInternal::DockPosition toDockPos(Qt::DockWidgetArea area)
1676 case Qt::LeftDockWidgetArea:
return QInternal::LeftDock;
1677 case Qt::RightDockWidgetArea:
return QInternal::RightDock;
1678 case Qt::TopDockWidgetArea:
return QInternal::TopDock;
1679 case Qt::BottomDockWidgetArea:
return QInternal::BottomDock;
1684 return QInternal::DockCount;
1687inline static Qt::DockWidgetArea toDockWidgetArea(
int pos)
1689 return QDockWidgetPrivate::toDockWidgetArea(
static_cast<QInternal::DockPosition>(pos));
1694static bool isAreaAllowed(QWidget *widget,
const QList<
int> &path)
1696 Q_ASSERT_X((path.size() > 1),
"isAreaAllowed",
"invalid path size");
1697 const Qt::DockWidgetArea area = toDockWidgetArea(path[1]);
1700 if (QDockWidget *dw = qobject_cast<QDockWidget *>(widget)) {
1701 const bool allowed = dw->isAreaAllowed(area);
1703 qCDebug(lcQpaDockWidgets) <<
"No permission for single DockWidget" << widget <<
"to dock on" << area;
1708 if (QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
1709 const QList<QDockWidget *> children = dwgw->findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly);
1711 if (children.size() == 1) {
1713 const bool allowed = children.at(0)->isAreaAllowed(area);
1715 qCDebug(lcQpaDockWidgets) <<
"No permission for DockWidgetGroupWindow" << widget <<
"to dock on" << area;
1719 qCDebug(lcQpaDockWidgets) <<
"DockWidgetGroupWindow" << widget <<
"has" << children.size() <<
"children:";
1720 qCDebug(lcQpaDockWidgets) << children;
1721 qCDebug(lcQpaDockWidgets) <<
"DockWidgetGroupWindow" << widget <<
"can dock at" << area <<
"and anywhere else.";
1725 qCDebug(lcQpaDockWidgets) <<
"Docking requested for invalid widget type (coding error)." << widget << area;
1729void QMainWindowLayout::setCorner(Qt::Corner corner, Qt::DockWidgetArea area)
1731 if (layoutState.dockAreaLayout.corners[corner] == area)
1733 layoutState.dockAreaLayout.corners[corner] = area;
1734 if (savedState.isValid())
1735 savedState.dockAreaLayout.corners[corner] = area;
1739Qt::DockWidgetArea QMainWindowLayout::corner(Qt::Corner corner)
const
1741 return layoutState.dockAreaLayout.corners[corner];
1747QRect QMainWindowLayout::dockWidgetAreaRect(
const Qt::DockWidgetArea area, DockWidgetAreaSize size)
const
1749 const QInternal::DockPosition dockPosition = toDockPos(area);
1752 if (dockPosition == QInternal::DockCount) {
1753 qCDebug(lcQpaDockWidgets) <<
"QMainWindowLayout::dockWidgetAreaRect called with" << area;
1757 const QDockAreaLayout dl = layoutState.dockAreaLayout;
1760 return (size == Maximum) ? dl.gapRect(dockPosition) : dl.docks[dockPosition].rect;
1764
1765
1766
1767void QMainWindowLayout::addDockWidget(Qt::DockWidgetArea area,
1768 QDockWidget *dockwidget,
1769 Qt::Orientation orientation)
1771 addChildWidget(dockwidget);
1775 if (!movingSeparator.isEmpty())
1776 endSeparatorMove(movingSeparatorPos);
1778 layoutState.dockAreaLayout.addDockWidget(toDockPos(area), dockwidget, orientation);
1782bool QMainWindowLayout::restoreDockWidget(QDockWidget *dockwidget)
1784 addChildWidget(dockwidget);
1785 if (!layoutState.dockAreaLayout.restoreDockWidget(dockwidget))
1787 emit dockwidget->dockLocationChanged(dockWidgetArea(dockwidget));
1792#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
1793static QTabBar::Shape tabwidgetPositionToTabBarShape(QDockWidget *w)
1795 switch (
static_cast<QDockWidgetPrivate *>(qt_widget_private(w))->tabPosition) {
1796 case QTabWidget::North:
1797 return QTabBar::RoundedNorth;
1798 case QTabWidget::South:
1799 return QTabBar::RoundedSouth;
1800 case QTabWidget::West:
1801 return QTabBar::RoundedWest;
1802 case QTabWidget::East:
1803 return QTabBar::RoundedEast;
1805 Q_UNREACHABLE_RETURN(QTabBar::RoundedSouth);
1809#if QT_CONFIG(tabbar)
1810void QMainWindowLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
1816 if (layoutState.dockAreaLayout.indexOf(first).isEmpty()) {
1817 qCritical() <<
"Coding error: QDockWidget" << first
1818 <<
"tabbed before QMainWindow::addDockWidget()."
1819 <<
"Ignoring" <<
__FUNCTION__;
1824 if (layoutState.dockAreaLayout.indexOf(second).isEmpty()) {
1825 layoutState.mainWindow->addDockWidget(first->dockLocation(), second);
1826 qCDebug(lcQpaDockWidgets) <<
"QDockWidget" << second <<
"has been added to"
1827 << parent() <<
"at" << first->dockLocation();
1831 if (isDockWidgetTabbed(second)) {
1832 qCDebug(lcQpaDockWidgets) <<
"QDockWidget" << second
1833 <<
"is already tabbed. Ignoring" <<
__FUNCTION__;
1837 const auto oldLocationFirst = dockWidgetArea(first);
1838 if (first->isFloating()) {
1839 tabifyWhileFloating(first, second);
1841 applyRestoredState();
1842 addChildWidget(second);
1843 layoutState.dockAreaLayout.tabifyDockWidget(first, second);
1845 const auto newLocationFirst = dockWidgetArea(first);
1846 if (newLocationFirst != oldLocationFirst)
1847 emit second->dockLocationChanged(newLocationFirst);
1851void QMainWindowLayout::tabifyWhileFloating(QDockWidget *first, QDockWidget *second)
1853 Q_ASSERT(first->isFloating());
1854 Q_ASSERT(!isDockWidgetTabbed(first));
1855 Q_ASSERT(!isDockWidgetTabbed(second));
1858 second->setFloating(
true);
1860 QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow();
1861 floatingTabs->setGeometry(first->geometry());
1862 QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
1863 const QTabBar::Shape shape = tabwidgetPositionToTabBarShape(first);
1865 const QInternal::DockPosition dockPosition = toDockPos(dockWidgetArea(first));
1866 Q_ASSERT(dockPosition != QInternal::DockPosition::DockCount);
1867 *info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, dockPosition,
1868 Qt::Horizontal, shape,
1869 static_cast<QMainWindow *>(parentWidget()));
1870 info->tabBar = getTabBar();
1871 info->tabbed =
true;
1874 second->d_func()->plug(first->geometry());
1875 QDockAreaLayoutInfo &parentInfo = layoutState.dockAreaLayout.docks[dockPosition];
1876 parentInfo.add(floatingTabs);
1877 first->setParent(floatingTabs);
1878 second->setParent(floatingTabs);
1879 floatingTabs->show();
1880 floatingTabs->raise();
1883bool QMainWindowLayout::documentMode()
const
1885 return _documentMode;
1888void QMainWindowLayout::setDocumentMode(
bool enabled)
1890 if (_documentMode == enabled)
1893 _documentMode = enabled;
1896 for (QTabBar *bar : std::as_const(usedTabBars))
1897 bar->setDocumentMode(_documentMode);
1900void QMainWindowLayout::setVerticalTabsEnabled(
bool enabled)
1902 if (verticalTabsEnabled == enabled)
1905 verticalTabsEnabled = enabled;
1907 updateTabBarShapes();
1910#if QT_CONFIG(tabwidget)
1911QTabWidget::TabShape QMainWindowLayout::tabShape()
const
1916void QMainWindowLayout::setTabShape(QTabWidget::TabShape tabShape)
1918 if (_tabShape == tabShape)
1921 _tabShape = tabShape;
1923 updateTabBarShapes();
1926QTabWidget::TabPosition QMainWindowLayout::tabPosition(Qt::DockWidgetArea area)
const
1928 const QInternal::DockPosition dockPos = toDockPos(area);
1929 if (dockPos < QInternal::DockCount)
1930 return tabPositions[dockPos];
1931 qWarning(
"QMainWindowLayout::tabPosition called with out-of-bounds value '%d'",
int(area));
1932 return QTabWidget::North;
1935void QMainWindowLayout::setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition)
1937 static constexpr Qt::DockWidgetArea dockWidgetAreas[] = {
1938 Qt::TopDockWidgetArea,
1939 Qt::LeftDockWidgetArea,
1940 Qt::BottomDockWidgetArea,
1941 Qt::RightDockWidgetArea
1943 static constexpr QInternal::DockPosition dockPositions[] = {
1945 QInternal::LeftDock,
1946 QInternal::BottomDock,
1947 QInternal::RightDock
1950 for (
int i = 0; i < QInternal::DockCount; ++i)
1951 if (areas & dockWidgetAreas[i])
1952 tabPositions[dockPositions[i]] = tabPosition;
1954 updateTabBarShapes();
1957QTabBar::Shape _q_tb_tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position);
1960void QMainWindowLayout::showTabBars()
1962 const auto usedTabBarsCopy = usedTabBars;
1963 for (QTabBar *tab_bar : usedTabBarsCopy) {
1964 if (usedTabBars.contains(tab_bar))
1969void QMainWindowLayout::updateTabBarShapes()
1971#if QT_CONFIG(tabwidget)
1972 static constexpr QTabWidget::TabPosition vertical[] = {
1979 static constexpr QTabBar::Shape vertical[] = {
1980 QTabBar::RoundedWest,
1981 QTabBar::RoundedEast,
1982 QTabBar::RoundedNorth,
1983 QTabBar::RoundedSouth
1987 QDockAreaLayout &layout = layoutState.dockAreaLayout;
1989 for (
int i = 0; i < QInternal::DockCount; ++i) {
1990#if QT_CONFIG(tabwidget)
1991 QTabWidget::TabPosition pos = verticalTabsEnabled ? vertical[i] : tabPositions[i];
1992 QTabBar::Shape shape = _q_tb_tabBarShapeFrom(_tabShape, pos);
1994 QTabBar::Shape shape = verticalTabsEnabled ? vertical[i] : QTabBar::RoundedSouth;
1996 layout.docks[i].setTabBarShape(shape);
2001void QMainWindowLayout::splitDockWidget(QDockWidget *after,
2002 QDockWidget *dockwidget,
2003 Qt::Orientation orientation)
2005 applyRestoredState();
2006 addChildWidget(dockwidget);
2007 layoutState.dockAreaLayout.splitDockWidget(after, dockwidget, orientation);
2008 emit dockwidget->dockLocationChanged(dockWidgetArea(after));
2012Qt::DockWidgetArea QMainWindowLayout::dockWidgetArea(
const QWidget *widget)
const
2014 const QList<
int> pathToWidget = layoutState.dockAreaLayout.indexOf(widget);
2015 if (pathToWidget.isEmpty())
2016 return Qt::NoDockWidgetArea;
2017 return toDockWidgetArea(pathToWidget.first());
2020void QMainWindowLayout::keepSize(QDockWidget *w)
2022 layoutState.dockAreaLayout.keepSize(w);
2025#if QT_CONFIG(tabbar)
2028class QMainWindowTabBar :
public QTabBar
2031 QPointer<QMainWindow> mainWindow;
2032 QPointer<QDockWidget> draggingDock;
2034 QMainWindowTabBar(QMainWindow *parent);
2035 ~QMainWindowTabBar();
2036 QDockWidget *dockAt(
int index)
const;
2037 QList<QDockWidget *> dockWidgets()
const;
2038 bool contains(
const QDockWidget *dockWidget)
const;
2040 bool event(QEvent *e) override;
2041 void mouseReleaseEvent(QMouseEvent*) override;
2042 void mouseMoveEvent(QMouseEvent*) override;
2046QDebug operator<<(QDebug debug,
const QMainWindowTabBar *bar)
2049 return debug <<
"QMainWindowTabBar(0x0)";
2050 QDebugStateSaver saver(debug);
2051 debug.nospace().noquote() <<
"QMainWindowTabBar(" <<
static_cast<
const void *>(bar) <<
", ";
2052 debug.nospace().noquote() <<
"ParentWidget=(" << bar->parentWidget() <<
"), ";
2053 const auto dockWidgets = bar->dockWidgets();
2054 if (dockWidgets.isEmpty())
2055 debug.nospace().noquote() <<
"No QDockWidgets";
2057 debug.nospace().noquote() <<
"DockWidgets(" << dockWidgets <<
")";
2058 debug.nospace().noquote() <<
")";
2062QMainWindowTabBar *QMainWindowLayout::findTabBar(
const QDockWidget *dockWidget)
const
2064 for (
auto *bar : usedTabBars) {
2065 Q_ASSERT(qobject_cast<QMainWindowTabBar *>(bar));
2066 auto *tabBar =
static_cast<QMainWindowTabBar *>(bar);
2067 if (tabBar->contains(dockWidget))
2073QMainWindowTabBar::QMainWindowTabBar(QMainWindow *parent)
2074 : QTabBar(parent), mainWindow(parent)
2076 setExpanding(
false);
2079QList<QDockWidget *> QMainWindowTabBar::dockWidgets()
const
2081 QList<QDockWidget *> docks;
2082 for (
int i = 0; i < count(); ++i) {
2083 if (QDockWidget *dock = dockAt(i))
2089bool QMainWindowTabBar::contains(
const QDockWidget *dockWidget)
const
2091 for (
int i = 0; i < count(); ++i) {
2092 if (dockAt(i) == dockWidget)
2103QDockWidget *QMainWindowTabBar::dockAt(
int index)
const
2105 QMainWindowTabBar *that =
const_cast<QMainWindowTabBar *>(
this);
2106 QMainWindowLayout* mlayout = qt_mainwindow_layout(mainWindow);
2107 QDockAreaLayoutInfo *info = mlayout ? mlayout->dockInfo(that) :
nullptr;
2111 const int itemIndex = info->tabIndexToListIndex(index);
2112 if (itemIndex >= 0) {
2113 Q_ASSERT(itemIndex < info->item_list.count());
2114 const QDockAreaLayoutItem &item = info->item_list.at(itemIndex);
2115 return item.widgetItem ? qobject_cast<QDockWidget *>(item.widgetItem->widget()) :
nullptr;
2122
2123
2124
2125
2126
2127
2128
2129
2130static void moveToUnplugPosition(QPoint mouse, QDockWidget *dockWidget)
2132 Q_ASSERT(dockWidget);
2134 if (
auto *tbWidget = dockWidget->titleBarWidget()) {
2135 dockWidget->move(mouse - tbWidget->rect().center());
2139 const bool vertical = dockWidget->features().testFlag(QDockWidget::DockWidgetVerticalTitleBar);
2140 const int deltaX = vertical ? QApplication::startDragDistance() : dockWidget->width() / 2;
2141 const int deltaY = vertical ? dockWidget->height() / 2 : QApplication::startDragDistance();
2142 dockWidget->move(mouse - QPoint(deltaX, deltaY));
2145void QMainWindowTabBar::mouseMoveEvent(QMouseEvent *e)
2152 QTabBarPrivate *d =
static_cast<QTabBarPrivate*>(d_ptr.data());
2153 if (!draggingDock && (mainWindow->dockOptions() & QMainWindow::GroupedDragging)) {
2154 int offset = QApplication::startDragDistance() + 1;
2156 QRect r = rect().adjusted(-offset, -offset, offset, offset);
2157 if (d->dragInProgress && !r.contains(e->position().toPoint()) && d->validIndex(d->pressedIndex)) {
2158 draggingDock = dockAt(d->pressedIndex);
2162 d->moveTabFinished(d->pressedIndex);
2163 d->pressedIndex = -1;
2165 d->movingTab->setVisible(
false);
2166 d->dragStartPosition = QPoint();
2169 QDockWidgetPrivate *dockPriv =
static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(draggingDock));
2170 QDockWidgetLayout *dwlayout =
static_cast<QDockWidgetLayout *>(draggingDock->layout());
2171 dockPriv->initDrag(dwlayout->titleArea().center(),
true);
2172 dockPriv->startDrag(QDockWidgetPrivate::DragScope::Widget);
2173 if (dockPriv->state)
2174 dockPriv->state->ctrlDrag = e->modifiers() & Qt::ControlModifier;
2180 QDockWidgetPrivate *dockPriv =
static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(draggingDock));
2181 if (dockPriv->state && dockPriv->state->dragging) {
2183 moveToUnplugPosition(e->globalPosition().toPoint(), draggingDock);
2186 QTabBar::mouseMoveEvent(e);
2189QMainWindowTabBar::~QMainWindowTabBar()
2193 if (!qobject_cast<QMainWindow *>(mainWindow) || mainWindow == parentWidget())
2198 auto *mwLayout = qt_mainwindow_layout(mainWindow);
2201 mwLayout->usedTabBars.remove(
this);
2204void QMainWindowTabBar::mouseReleaseEvent(QMouseEvent *e)
2206 if (draggingDock && e->button() == Qt::LeftButton) {
2207 QDockWidgetPrivate *dockPriv =
static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(draggingDock));
2208 if (dockPriv->state && dockPriv->state->dragging)
2209 dockPriv->endDrag(QDockWidgetPrivate::EndDragMode::LocationChange);
2211 draggingDock =
nullptr;
2213 QTabBar::mouseReleaseEvent(e);
2216bool QMainWindowTabBar::event(QEvent *e)
2220 if (e->type() != QEvent::ToolTip)
2221 return QTabBar::event(e);
2222 QSize size =
this->size();
2223 QSize hint = sizeHint();
2224 if (shape() == QTabBar::RoundedWest || shape() == QTabBar::RoundedEast) {
2225 size = size.transposed();
2226 hint = hint.transposed();
2228 if (size.width() < hint.width())
2229 return QTabBar::event(e);
2234QList<QDockWidget *> QMainWindowLayout::tabifiedDockWidgets(
const QDockWidget *dockWidget)
const
2236 const auto *bar = findTabBar(dockWidget);
2240 QList<QDockWidget *> buddies = bar->dockWidgets();
2243 buddies.removeOne(dockWidget);
2247bool QMainWindowLayout::isDockWidgetTabbed(
const QDockWidget *dockWidget)
const
2252 const auto *bar = findTabBar(dockWidget);
2253 return bar && bar->count() > 1;
2256void QMainWindowLayout::unuseTabBar(QTabBar *bar)
2258 Q_ASSERT(qobject_cast<QMainWindowTabBar *>(bar));
2262QTabBar *QMainWindowLayout::getTabBar()
2264 if (!usedTabBars.isEmpty() && !isInRestoreState) {
2266
2267
2268
2269
2273 QTabBar *bar =
new QMainWindowTabBar(
static_cast<QMainWindow *>(parentWidget()));
2274 bar->setDrawBase(
true);
2275 bar->setElideMode(Qt::ElideRight);
2276 bar->setDocumentMode(_documentMode);
2277 bar->setMovable(
true);
2278 connect(bar, SIGNAL(currentChanged(
int)),
this, SLOT(tabChanged()));
2279 connect(bar, &QTabBar::tabMoved,
this, &QMainWindowLayout::tabMoved);
2281 usedTabBars.insert(bar);
2285QWidget *QMainWindowLayout::getSeparatorWidget()
2287 auto *separator =
new QWidget(parentWidget());
2288 separator->setAttribute(Qt::WA_MouseNoMask,
true);
2289 separator->setAutoFillBackground(
false);
2290 separator->setObjectName(
"qt_qmainwindow_extended_splitter"_L1);
2291 usedSeparatorWidgets.insert(separator);
2296
2297
2298
2299QDockAreaLayoutInfo *QMainWindowLayout::dockInfo(QWidget *widget)
2301 QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget);
2305 parent()->findChildren<QDockWidgetGroupWindow*>(Qt::FindDirectChildrenOnly);
2306 for (QDockWidgetGroupWindow *dwgw : groups) {
2307 info = dwgw->layoutInfo()->info(widget);
2314void QMainWindowLayout::tabChanged()
2316 QTabBar *tb = qobject_cast<QTabBar*>(sender());
2319 QDockAreaLayoutInfo *info = dockInfo(tb);
2320 if (info ==
nullptr)
2323 QDockWidget *activated = info->apply(QWidgetAnimator::AnimationRule::Stop);
2326 emit
static_cast<QMainWindow *>(parentWidget())->tabifiedDockWidgetActivated(activated);
2328 if (
auto dwgw = qobject_cast<QDockWidgetGroupWindow*>(tb->parentWidget()))
2329 dwgw->adjustFlags();
2331 if (QWidget *w = centralWidget())
2335void QMainWindowLayout::tabMoved(
int from,
int to)
2337 QTabBar *tb = qobject_cast<QTabBar*>(sender());
2339 QDockAreaLayoutInfo *info = dockInfo(tb);
2342 info->moveTab(from, to);
2345void QMainWindowLayout::raise(QDockWidget *widget)
2347 QDockAreaLayoutInfo *info = dockInfo(widget);
2348 if (info ==
nullptr)
2352 info->setCurrentTab(widget);
2360
2361
2363int QMainWindowLayout::count()
const
2366 while (itemAt(result))
2371QLayoutItem *QMainWindowLayout::itemAt(
int index)
const
2375 if (QLayoutItem *ret = layoutState.itemAt(index, &x))
2378 if (statusbar && x++ == index)
2384QLayoutItem *QMainWindowLayout::takeAt(
int index)
2388 if (QLayoutItem *ret = layoutState.takeAt(index, &x)) {
2390 if (QWidget *w = ret->widget()) {
2391 widgetAnimator.abort(w);
2392 if (w == pluggingWidget)
2393 pluggingWidget =
nullptr;
2396 if (savedState.isValid() ) {
2398 savedState.remove(ret);
2400 layoutState.remove(ret);
2403#if QT_CONFIG(toolbar)
2404 if (!currentGapPos.isEmpty() && currentGapPos.constFirst() == 0) {
2405 currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
2406 if (!currentGapPos.isEmpty()) {
2407 currentGapPos.prepend(0);
2408 currentGapRect = layoutState.itemRect(currentGapPos);
2416 if (statusbar && x++ == index) {
2417 QLayoutItem *ret = statusbar;
2418 statusbar =
nullptr;
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442void QMainWindowLayout::applyRestoredState()
2444 if (restoredState) {
2445 layoutState = *restoredState;
2446 restoredState.reset();
2447 discardRestoredStateTimer.stop();
2451void QMainWindowLayout::setGeometry(
const QRect &_r)
2455 if (savedState.isValid() || (restoredState && isInApplyState))
2460 QLayout::setGeometry(r);
2463 QRect sbr(QPoint(r.left(), 0),
2464 QSize(r.width(), statusbar->heightForWidth(r.width()))
2465 .expandedTo(statusbar->minimumSize()));
2466 sbr.moveBottom(r.bottom());
2467 QRect vr = QStyle::visualRect(parentWidget()->layoutDirection(), _r, sbr);
2468 statusbar->setGeometry(vr);
2469 r.setBottom(sbr.top() - 1);
2472 if (restoredState) {
2474
2475
2476
2477
2478
2479
2480 layoutState = *restoredState;
2481 if (restoredState->fits()) {
2482 restoredState.reset();
2483 discardRestoredStateTimer.stop();
2486
2487
2488
2489
2490
2491
2492
2493
2494 discardRestoredStateTimer.start(150,
this);
2498 layoutState.rect = r;
2500 layoutState.fitLayout();
2501 applyState(layoutState,
false);
2504void QMainWindowLayout::timerEvent(QTimerEvent *e)
2506 if (e->timerId() == discardRestoredStateTimer.timerId()) {
2507 discardRestoredStateTimer.stop();
2508 restoredState.reset();
2510 QLayout::timerEvent(e);
2513void QMainWindowLayout::addItem(QLayoutItem *)
2514{ qWarning(
"QMainWindowLayout::addItem: Please use the public QMainWindow API instead"); }
2516QSize QMainWindowLayout::sizeHint()
const
2518 if (!szHint.isValid()) {
2519 szHint = layoutState.sizeHint();
2520 const QSize sbHint = statusbar ? statusbar->sizeHint() : QSize(0, 0);
2521 szHint = QSize(qMax(sbHint.width(), szHint.width()),
2522 sbHint.height() + szHint.height());
2527QSize QMainWindowLayout::minimumSize()
const
2529 if (!minSize.isValid()) {
2530 minSize = layoutState.minimumSize();
2531 const QSize sbMin = statusbar ? statusbar->minimumSize() : QSize(0, 0);
2532 minSize = QSize(qMax(sbMin.width(), minSize.width()),
2533 sbMin.height() + minSize.height());
2538void QMainWindowLayout::invalidate()
2540 QLayout::invalidate();
2541 minSize = szHint = QSize();
2544#if QT_CONFIG(dockwidget)
2545void QMainWindowLayout::setCurrentHoveredFloat(QDockWidgetGroupWindow *w)
2547 if (currentHoveredFloat != w) {
2548 if (currentHoveredFloat) {
2549 disconnect(currentHoveredFloat.data(), &QObject::destroyed,
2550 this, &QMainWindowLayout::updateGapIndicator);
2551 disconnect(currentHoveredFloat.data(), &QDockWidgetGroupWindow::resized,
2552 this, &QMainWindowLayout::updateGapIndicator);
2553 if (currentHoveredFloat)
2554 currentHoveredFloat->restore();
2556 restore(QInternal::KeepSavedState);
2559 currentHoveredFloat = w;
2562 connect(w, &QObject::destroyed,
2563 this, &QMainWindowLayout::updateGapIndicator, Qt::UniqueConnection);
2564 connect(w, &QDockWidgetGroupWindow::resized,
2565 this, &QMainWindowLayout::updateGapIndicator, Qt::UniqueConnection);
2568 updateGapIndicator();
2574
2575
2579#if QT_CONFIG(toolbar)
2580 QToolBar *toolBar = qobject_cast<QToolBar*>(item->widget());
2581 if (toolBar ==
nullptr)
2584 QRect oldGeo = toolBar->geometry();
2586 QInternal::DockPosition pos
2587 =
static_cast<QInternal::DockPosition>(dockPos);
2588 Qt::Orientation o = pos == QInternal::TopDock || pos == QInternal::BottomDock
2589 ? Qt::Horizontal : Qt::Vertical;
2590 if (o != toolBar->orientation())
2591 toolBar->setOrientation(o);
2593 QSize hint = toolBar->sizeHint().boundedTo(toolBar->maximumSize())
2594 .expandedTo(toolBar->minimumSize());
2596 if (toolBar->size() != hint) {
2597 QRect newGeo(oldGeo.topLeft(), hint);
2598 if (toolBar->layoutDirection() == Qt::RightToLeft)
2599 newGeo.moveRight(oldGeo.right());
2600 toolBar->setGeometry(newGeo);
2609void QMainWindowLayout::revert(QLayoutItem *widgetItem)
2611 if (!savedState.isValid())
2614 QWidget *widget = widgetItem->widget();
2615 layoutState = savedState;
2616 currentGapPos = layoutState.indexOf(widget);
2617 if (currentGapPos.isEmpty())
2619 fixToolBarOrientation(widgetItem, currentGapPos.at(1));
2620 layoutState.unplug(currentGapPos);
2621 layoutState.fitLayout();
2622 currentGapRect = layoutState.itemRect(currentGapPos);
2627bool QMainWindowLayout::plug(QLayoutItem *widgetItem)
2629#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget) && QT_CONFIG(tabbar)
2630 if (currentHoveredFloat) {
2631 QWidget *widget = widgetItem->widget();
2632 QList<
int> previousPath = layoutState.indexOf(widget);
2633 if (!previousPath.isEmpty())
2634 layoutState.remove(previousPath);
2635 previousPath = currentHoveredFloat->layoutInfo()->indexOf(widget);
2638 parent()->findChildren<QDockWidgetGroupWindow*>(Qt::FindDirectChildrenOnly);
2639 for (QDockWidgetGroupWindow *dwgw : groups) {
2640 if (dwgw == currentHoveredFloat)
2642 QList<
int> path = dwgw->layoutInfo()->indexOf(widget);
2643 if (!path.isEmpty())
2644 dwgw->layoutInfo()->remove(path);
2646 currentGapRect = QRect();
2647 currentHoveredFloat->apply();
2648 if (!previousPath.isEmpty())
2649 currentHoveredFloat->layoutInfo()->remove(previousPath);
2650 QRect globalRect = currentHoveredFloat->currentGapRect;
2651 globalRect.moveTopLeft(currentHoveredFloat->mapToGlobal(globalRect.topLeft()));
2652 pluggingWidget = widget;
2653 const auto rule = toAnimationRule(dockOptions);
2654 widgetAnimator.animate(widget, globalRect, rule);
2659 if (!parentWidget()->isVisible() || parentWidget()->isMinimized() || currentGapPos.isEmpty())
2662 fixToolBarOrientation(widgetItem, currentGapPos.at(1));
2664 QWidget *widget = widgetItem->widget();
2666#if QT_CONFIG(dockwidget)
2669 parent()->findChildren<QDockWidgetGroupWindow*>(Qt::FindDirectChildrenOnly);
2670 for (QDockWidgetGroupWindow *dwgw : groups) {
2671 QList<
int> path = dwgw->layoutInfo()->indexOf(widget);
2672 if (!path.isEmpty())
2673 dwgw->layoutInfo()->remove(path);
2677 QList<
int> previousPath = layoutState.indexOf(widget);
2679 const QLayoutItem *it = layoutState.plug(currentGapPos);
2682 Q_ASSERT(it == widgetItem);
2683 if (!previousPath.isEmpty())
2684 layoutState.remove(previousPath);
2686 pluggingWidget = widget;
2687 QRect globalRect = currentGapRect;
2688 globalRect.moveTopLeft(parentWidget()->mapToGlobal(globalRect.topLeft()));
2689#if QT_CONFIG(dockwidget)
2690 if (qobject_cast<QDockWidget*>(widget) !=
nullptr) {
2691 QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(widget->layout());
2692 if (layout->nativeWindowDeco()) {
2693 globalRect.adjust(0, layout->titleHeight(), 0, 0);
2695 int fw = widget->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth,
nullptr, widget);
2696 globalRect.adjust(-fw, -fw, fw, fw);
2700 const auto rule = toAnimationRule(dockOptions);
2701 widgetAnimator.animate(widget, globalRect, rule);
2706void QMainWindowLayout::animationFinished(QWidget *widget)
2710#if QT_CONFIG(toolbar)
2711 if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
2712 QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(tb->layout());
2713 if (tbl->animating) {
2714 tbl->animating =
false;
2716 tbl->layoutActions(tb->size());
2722 if (widget == pluggingWidget) {
2724#if QT_CONFIG(dockwidget)
2725#if QT_CONFIG(tabbar)
2726 if (QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
2730 QDockAreaLayoutInfo *srcInfo = dwgw->layoutInfo();
2731 const QDockAreaLayoutInfo *srcTabInfo = dwgw->tabLayoutInfo();
2732 QDockAreaLayoutInfo *dstParentInfo;
2735 if (currentHoveredFloat) {
2736 dstPath = currentHoveredFloat->layoutInfo()->indexOf(widget);
2737 Q_ASSERT(dstPath.size() >= 1);
2738 dstParentInfo = currentHoveredFloat->layoutInfo()->info(dstPath);
2740 dstPath = layoutState.dockAreaLayout.indexOf(widget);
2741 Q_ASSERT(dstPath.size() >= 2);
2742 dstParentInfo = layoutState.dockAreaLayout.info(dstPath);
2744 Q_ASSERT(dstParentInfo);
2745 int idx = dstPath.constLast();
2746 Q_ASSERT(dstParentInfo->item_list[idx].widgetItem->widget() == dwgw);
2747 if (dstParentInfo->tabbed && srcTabInfo) {
2749 delete dstParentInfo->item_list[idx].widgetItem;
2750 dstParentInfo->item_list.removeAt(idx);
2751 std::copy(srcTabInfo->item_list.cbegin(), srcTabInfo->item_list.cend(),
2752 std::inserter(dstParentInfo->item_list,
2753 dstParentInfo->item_list.begin() + idx));
2754 quintptr currentId = srcTabInfo->currentTabId();
2755 *srcInfo = QDockAreaLayoutInfo();
2756 dstParentInfo->reparentWidgets(currentHoveredFloat ? currentHoveredFloat.data()
2758 dstParentInfo->updateTabBar();
2759 dstParentInfo->setCurrentTabId(currentId);
2761 QDockAreaLayoutItem &item = dstParentInfo->item_list[idx];
2762 Q_ASSERT(item.widgetItem->widget() == dwgw);
2763 delete item.widgetItem;
2764 item.widgetItem =
nullptr;
2765 item.subinfo =
new QDockAreaLayoutInfo(std::move(*srcInfo));
2766 *srcInfo = QDockAreaLayoutInfo();
2767 item.subinfo->reparentWidgets(currentHoveredFloat ? currentHoveredFloat.data()
2769 item.subinfo->setTabBarShape(dstParentInfo->tabBarShape);
2771 dwgw->destroyOrHideIfEmpty();
2775 if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
2776 dw->setParent(currentHoveredFloat ? currentHoveredFloat.data() : parentWidget());
2778 dw->d_func()->plug(currentGapRect);
2781#if QT_CONFIG(toolbar)
2782 if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
2783 tb->d_func()->plug(currentGapRect);
2787 currentGapPos.clear();
2788 pluggingWidget =
nullptr;
2789#if QT_CONFIG(dockwidget)
2790 setCurrentHoveredFloat(
nullptr);
2794 layoutState.apply(QWidgetAnimator::AnimationRule::Stop);
2796#if QT_CONFIG(dockwidget)
2797#if QT_CONFIG(tabbar)
2798 if (qobject_cast<QDockWidget*>(widget) !=
nullptr) {
2801 if (QDockAreaLayoutInfo *info = dockInfo(widget))
2802 info->setCurrentTab(widget);
2808 if (!widgetAnimator.animating()) {
2810#if QT_CONFIG(dockwidget)
2811 parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
2812#if QT_CONFIG(tabbar)
2818 updateGapIndicator();
2821void QMainWindowLayout::restore(QInternal::SaveStateRule rule)
2823 if (!savedState.isValid())
2826 layoutState = savedState;
2827 applyState(layoutState);
2828 if (rule == QInternal::ClearSavedState)
2830 currentGapPos.clear();
2831 pluggingWidget =
nullptr;
2832 updateGapIndicator();
2835QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLayout)
2836 : QLayout(parentLayout ?
static_cast<QWidget *>(
nullptr) : mainwindow)
2837 , layoutState(mainwindow)
2838 , savedState(mainwindow)
2839 , dockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowTabbedDocks)
2840 , statusbar(
nullptr)
2841#if QT_CONFIG(dockwidget)
2842#if QT_CONFIG(tabbar)
2843 , _documentMode(
false)
2844 , verticalTabsEnabled(
false)
2845#if QT_CONFIG(tabwidget)
2846 , _tabShape(QTabWidget::Rounded)
2850 , widgetAnimator(
this)
2851 , pluggingWidget(
nullptr)
2854 setParent(parentLayout);
2856#if QT_CONFIG(dockwidget)
2857#if QT_CONFIG(tabbar)
2858 sep = mainwindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent,
nullptr, mainwindow);
2861#if QT_CONFIG(tabwidget)
2862 for (
int i = 0; i < QInternal::DockCount; ++i)
2863 tabPositions[i] = QTabWidget::South;
2866 pluggingWidget =
nullptr;
2868 setObjectName(mainwindow->objectName() +
"_layout"_L1);
2871QMainWindowLayout::~QMainWindowLayout()
2873 layoutState.deleteAllLayoutItems();
2874 layoutState.deleteCentralWidgetItem();
2879void QMainWindowLayout::setDockOptions(QMainWindow::DockOptions opts)
2881 if (opts == dockOptions)
2886#if QT_CONFIG(dockwidget) && QT_CONFIG(tabbar)
2887 setVerticalTabsEnabled(opts & QMainWindow::VerticalTabs);
2893#if QT_CONFIG(statusbar)
2894QStatusBar *QMainWindowLayout::statusBar()
const
2895{
return statusbar ? qobject_cast<QStatusBar *>(statusbar->widget()) : 0; }
2897void QMainWindowLayout::setStatusBar(QStatusBar *sb)
2902 statusbar = sb ?
new QWidgetItemV2(sb) :
nullptr;
2907QWidget *QMainWindowLayout::centralWidget()
const
2909 return layoutState.centralWidget();
2912void QMainWindowLayout::setCentralWidget(QWidget *widget)
2914 if (widget !=
nullptr)
2915 addChildWidget(widget);
2916 layoutState.setCentralWidget(widget);
2917 if (savedState.isValid()) {
2918#if QT_CONFIG(dockwidget)
2919 savedState.dockAreaLayout.centralWidgetItem = layoutState.dockAreaLayout.centralWidgetItem;
2920 savedState.dockAreaLayout.fallbackToSizeHints =
true;
2922 savedState.centralWidgetItem = layoutState.centralWidgetItem;
2928#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
2930
2931
2932
2933
2934
2935
2936static bool unplugGroup(QMainWindowLayout *layout, QLayoutItem **item,
2937 QDockAreaLayoutItem &parentItem)
2939 if (!parentItem.subinfo || !parentItem.subinfo->tabbed)
2943 QDockWidgetGroupWindow *floatingTabs = layout->createTabbedDockWindow();
2944 QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
2945 *info = std::move(*parentItem.subinfo);
2946 delete parentItem.subinfo;
2947 parentItem.subinfo =
nullptr;
2948 floatingTabs->setGeometry(info->rect.translated(layout->parentWidget()->pos()));
2949 floatingTabs->show();
2950 floatingTabs->raise();
2951 *item =
new QDockWidgetGroupWindowItem(floatingTabs);
2952 parentItem.widgetItem = *item;
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, QDockWidgetPrivate::DragScope scope)
2969#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
2970 auto *groupWindow = qobject_cast<
const QDockWidgetGroupWindow *>(widget->parentWidget());
2971 if (!widget->isWindow() && groupWindow) {
2972 if (scope == QDockWidgetPrivate::DragScope::Group && groupWindow->tabLayoutInfo()) {
2975 if (QDockAreaLayoutInfo *info = dockInfo(widget->parentWidget())) {
2976 QList<
int> groupWindowPath = info->indexOf(widget->parentWidget());
2977 return groupWindowPath.isEmpty() ?
nullptr : info->item(groupWindowPath).widgetItem;
2979 qCDebug(lcQpaDockWidgets) <<
"Drag only:" << widget <<
"Group:" << (scope == QDockWidgetPrivate::DragScope::Group);
2982 const QList<
int> path = groupWindow->layoutInfo()->indexOf(widget);
2983 QDockAreaLayoutItem parentItem = groupWindow->layoutInfo()->item(path);
2984 QLayoutItem *item = parentItem.widgetItem;
2985 if (scope == QDockWidgetPrivate::DragScope::Group && path.size() > 1
2986 && unplugGroup(
this, &item, parentItem)) {
2987 qCDebug(lcQpaDockWidgets) <<
"Unplugging:" << widget <<
"from" << item;
2991 QDockWidget *dockWidget = qobject_cast<QDockWidget *>(widget);
2992 Q_ASSERT(dockWidget);
2993 dockWidget->d_func()->unplug(widget->geometry());
2995 qCDebug(lcQpaDockWidgets) <<
"Unplugged from floating dock:" << widget <<
"from" << groupWindow;
3000 QList<
int> path = layoutState.indexOf(widget);
3004 QLayoutItem *item = layoutState.item(path);
3005 if (widget->isWindow())
3008 QRect r = layoutState.itemRect(path);
3009 savedState = layoutState;
3011#if QT_CONFIG(dockwidget)
3012 if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
3013 Q_ASSERT(path.constFirst() == 1);
3014#if QT_CONFIG(tabwidget)
3015 if (scope == QDockWidgetPrivate::DragScope::Group && (dockOptions & QMainWindow::GroupedDragging) && path.size() > 3
3016 && unplugGroup(
this, &item,
3017 layoutState.dockAreaLayout.item(path.mid(1, path.size() - 2)))) {
3019 savedState = layoutState;
3025 switch (dockWidgetArea(dw)) {
3026 case Qt::LeftDockWidgetArea:
3027 case Qt::RightDockWidgetArea:
3028 r.setHeight(r.height() - sep);
3030 case Qt::TopDockWidgetArea:
3031 case Qt::BottomDockWidgetArea:
3032 r.setWidth(r.width() - sep);
3034 case Qt::NoDockWidgetArea:
3035 case Qt::DockWidgetArea_Mask:
3043 const auto *layout = qobject_cast<QDockWidgetLayout *>(dw->layout());
3044 const bool verticalTitleBar = layout ? layout->verticalTitleBar :
false;
3045 const int tbHeight = QApplication::style()
3046 ? QApplication::style()->pixelMetric(QStyle::PixelMetric::PM_TitleBarHeight,
nullptr, dw)
3048 const int minHeight = verticalTitleBar ? 2 * tbHeight : tbHeight;
3049 const int minWidth = verticalTitleBar ? tbHeight : 2 * tbHeight;
3050 r.setSize(r.size().expandedTo(QSize(minWidth, minHeight)));
3051 qCDebug(lcQpaDockWidgets) << dw <<
"will be unplugged with size" << r.size();
3053 dw->d_func()->unplug(r);
3057#if QT_CONFIG(toolbar)
3058 if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
3059 tb->d_func()->unplug(r);
3063#if !QT_CONFIG(dockwidget) || !QT_CONFIG(tabbar)
3067 layoutState.unplug(path ,&savedState);
3068 savedState.fitLayout();
3069 currentGapPos = path;
3071 updateGapIndicator();
3073 fixToolBarOrientation(item, currentGapPos.at(1));
3078void QMainWindowLayout::updateGapIndicator()
3080#if QT_CONFIG(rubberband)
3081 if (!widgetAnimator.animating() && (!currentGapPos.isEmpty()
3082#if QT_CONFIG(dockwidget)
3083 || currentHoveredFloat
3086 QWidget *expectedParent =
3087#if QT_CONFIG(dockwidget)
3088 currentHoveredFloat ? currentHoveredFloat.data() :
3091 if (!gapIndicator) {
3092 gapIndicator =
new QRubberBand(QRubberBand::Rectangle, expectedParent);
3094 gapIndicator->setObjectName(
"qt_rubberband"_L1);
3095 }
else if (gapIndicator->parent() != expectedParent) {
3096 gapIndicator->setParent(expectedParent);
3100 const bool sigBlockState = gapIndicator->signalsBlocked();
3101 auto resetSignals = qScopeGuard([
this, sigBlockState](){ gapIndicator->blockSignals(sigBlockState); });
3102 gapIndicator->blockSignals(
true);
3104#if QT_CONFIG(dockwidget)
3105 if (currentHoveredFloat)
3106 gapIndicator->setGeometry(currentHoveredFloat->currentGapRect);
3109 gapIndicator->setGeometry(currentGapRect);
3111 gapIndicator->show();
3112 gapIndicator->raise();
3116 }
else if (gapIndicator) {
3117 gapIndicator->hide();
3123void QMainWindowLayout::hover(QLayoutItem *hoverTarget,
3124 const QPoint &mousePos) {
3125 if (!parentWidget()->isVisible() || parentWidget()->isMinimized() ||
3126 pluggingWidget !=
nullptr || hoverTarget ==
nullptr)
3129 QWidget *widget = hoverTarget->widget();
3131#if QT_CONFIG(dockwidget)
3133 if ((dockOptions & QMainWindow::GroupedDragging) && (qobject_cast<QDockWidget*>(widget)
3134 || qobject_cast<QDockWidgetGroupWindow *>(widget))) {
3137 QVarLengthArray<QWidget *, 10> candidates;
3138 const auto siblings = parentWidget()->children();
3139 for (QObject *c : siblings) {
3140 QWidget *w = qobject_cast<QWidget*>(c);
3145 if (!qobject_cast<QDockWidget*>(w) && !qobject_cast<QDockWidgetGroupWindow *>(w))
3151 if (w != widget && w->isWindow() && w->isVisible() && !w->isMinimized())
3154 if (QDockWidgetGroupWindow *group = qobject_cast<QDockWidgetGroupWindow *>(w)) {
3157 const auto groupChildren = group->children();
3158 for (QObject *c : groupChildren) {
3159 if (QDockWidget *dw = qobject_cast<QDockWidget*>(c)) {
3160 if (dw != widget && dw->isFloating() && dw->isVisible() && !dw->isMinimized())
3167 for (QWidget *w : candidates) {
3168 const QScreen *screen1 = qt_widget_private(widget)->associatedScreen();
3169 const QScreen *screen2 = qt_widget_private(w)->associatedScreen();
3170 if (screen1 && screen2 && screen1 != screen2)
3172 if (!w->geometry().contains(mousePos))
3175#if QT_CONFIG(tabwidget)
3176 if (
auto dropTo = qobject_cast<QDockWidget *>(w)) {
3179 w = dropTo->widget();
3182 if (!qobject_cast<QDockWidgetGroupWindow *>(w)) {
3183 QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow();
3184 floatingTabs->setGeometry(dropTo->geometry());
3185 QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
3186 const QTabBar::Shape shape = tabwidgetPositionToTabBarShape(dropTo);
3193 QInternal::DockPosition dockPosition = toDockPos(dockWidgetArea(dropTo));
3194 if (dockPosition == QInternal::DockPosition::DockCount)
3195 dockPosition = toDockPos(dockWidgetArea(widget));
3196 if (dockPosition == QInternal::DockPosition::DockCount)
3197 dockPosition = QInternal::DockPosition::RightDock;
3199 *info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, dockPosition,
3200 Qt::Horizontal, shape,
3201 static_cast<QMainWindow *>(parentWidget()));
3202 info->tabBar = getTabBar();
3203 info->tabbed =
true;
3205 QDockAreaLayoutInfo &parentInfo = layoutState.dockAreaLayout.docks[dockPosition];
3206 parentInfo.add(floatingTabs);
3207 dropTo->setParent(floatingTabs);
3208 qCDebug(lcQpaDockWidgets) <<
"Wrapping" << widget <<
"into floating tabs" << floatingTabs;
3214 qCDebug(lcQpaDockWidgets) <<
"Showing" << dropTo;
3216 qCDebug(lcQpaDockWidgets) <<
"Raising" << widget;
3219 auto *groupWindow = qobject_cast<QDockWidgetGroupWindow *>(w);
3220 Q_ASSERT(groupWindow);
3221 if (groupWindow->hover(hoverTarget, groupWindow->mapFromGlobal(mousePos))) {
3223 setCurrentHoveredFloat(groupWindow);
3224 applyState(layoutState);
3232 if (currentHoveredFloat)
3233 currentHoveredFloat->destroyIfSingleItemLeft();
3235 setCurrentHoveredFloat(
nullptr);
3236 layoutState.dockAreaLayout.fallbackToSizeHints =
false;
3239 QPoint pos = parentWidget()->mapFromGlobal(mousePos);
3241 if (!savedState.isValid())
3242 savedState = layoutState;
3244 QList<
int> path = savedState.gapIndex(widget, pos);
3246 if (!path.isEmpty()) {
3247 bool allowed =
false;
3249#if QT_CONFIG(dockwidget)
3250 allowed = isAreaAllowed(widget, path);
3252#if QT_CONFIG(toolbar)
3253 if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
3254 allowed = tb->isAreaAllowed(toToolBarArea(path.at(1)));
3261 if (path == currentGapPos)
3264 currentGapPos = path;
3265 if (path.isEmpty()) {
3266 fixToolBarOrientation(hoverTarget, 2);
3267 restore(QInternal::KeepSavedState);
3271 fixToolBarOrientation(hoverTarget, currentGapPos.at(1));
3273 QMainWindowLayoutState newState = savedState;
3275 if (!newState.insertGap(path, hoverTarget)) {
3276 restore(QInternal::KeepSavedState);
3280 QSize min = newState.minimumSize();
3281 QSize size = newState.rect.size();
3283 if (min.width() > size.width() || min.height() > size.height()) {
3284 restore(QInternal::KeepSavedState);
3288 newState.fitLayout();
3290 currentGapRect = newState.gapRect(currentGapPos);
3292#if QT_CONFIG(dockwidget)
3293 parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
3295 layoutState = std::move(newState);
3296 applyState(layoutState);
3298 updateGapIndicator();
3301#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
3302QDockWidgetGroupWindow *QMainWindowLayout::createTabbedDockWindow()
3304 QDockWidgetGroupWindow* f =
new QDockWidgetGroupWindow(parentWidget(), Qt::Tool);
3305 new QDockWidgetGroupLayout(f);
3310void QMainWindowLayout::applyState(QMainWindowLayoutState &newState,
bool animate)
3317 isInApplyState =
true;
3318#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
3319 QSet<QTabBar*> used = newState.dockAreaLayout.usedTabBars();
3321 parent()->findChildren<QDockWidgetGroupWindow*>(Qt::FindDirectChildrenOnly);
3322 for (QDockWidgetGroupWindow *dwgw : groups)
3323 used += dwgw->layoutInfo()->usedTabBars();
3325 const QSet<QTabBar*> retired = usedTabBars - used;
3327 for (QTabBar *tab_bar : retired) {
3328 unuseTabBar(tab_bar);
3332 const QSet<QWidget*> usedSeps = newState.dockAreaLayout.usedSeparatorWidgets();
3333 const QSet<QWidget*> retiredSeps = usedSeparatorWidgets - usedSeps;
3334 usedSeparatorWidgets = usedSeps;
3335 for (QWidget *sepWidget : retiredSeps)
3339 for (
int i = 0; i < QInternal::DockCount; ++i)
3340 newState.dockAreaLayout.docks[i].reparentWidgets(parentWidget());
3343 const auto rule = animate ? toAnimationRule(dockOptions) : QWidgetAnimator::AnimationRule::Stop;
3344 newState.apply(rule);
3345 isInApplyState =
false;
3348void QMainWindowLayout::saveState(QDataStream &stream)
const
3350 layoutState.saveState(stream);
3353bool QMainWindowLayout::restoreState(QDataStream &stream)
3355 QScopedValueRollback<
bool> guard(isInRestoreState,
true);
3356 savedState = layoutState;
3357 layoutState.clear();
3358 layoutState.rect = savedState.rect;
3360 if (!layoutState.restoreState(stream, savedState)) {
3361 layoutState.deleteAllLayoutItems();
3362 layoutState = savedState;
3363 if (parentWidget()->isVisible())
3364 applyState(layoutState,
false);
3368 if (parentWidget()->isVisible()) {
3369 layoutState.fitLayout();
3370 applyState(layoutState,
false);
3373
3374
3375
3376
3377
3378
3379 if ((parentWidget()->windowState() & (Qt::WindowFullScreen | Qt::WindowMaximized))
3380 && !layoutState.fits()) {
3381 restoredState.reset(
new QMainWindowLayoutState(layoutState));
3385 savedState.deleteAllLayoutItems();
3388#if QT_CONFIG(dockwidget) && QT_CONFIG(tabbar)
3389 if (parentWidget()->isVisible())
3396#if QT_CONFIG(draganddrop)
3397bool QMainWindowLayout::needsPlatformDrag()
3399 static const bool wayland =
3400 QGuiApplication::platformName().startsWith(
"wayland"_L1, Qt::CaseInsensitive);
3404Qt::DropAction QMainWindowLayout::performPlatformWidgetDrag(QLayoutItem *widgetItem,
3405 const QPoint &pressPosition)
3407 draggingWidget = widgetItem;
3408 QWidget *widget = widgetItem->widget();
3409 auto drag = QDrag(widget);
3410 auto mimeData =
new QMimeData();
3411 auto window = widgetItem->widget()->windowHandle();
3413 auto serialize = [](
const auto &object) {
3415 QDataStream dataStream(&data, QIODevice::WriteOnly);
3416 dataStream << object;
3419 mimeData->setData(
"application/x-qt-mainwindowdrag-window"_L1,
3420 serialize(
reinterpret_cast<qintptr>(window)));
3421 mimeData->setData(
"application/x-qt-mainwindowdrag-position"_L1, serialize(pressPosition));
3422 drag.setMimeData(mimeData);
3424 auto result = drag.exec();
3426 draggingWidget =
nullptr;
3433#include "qmainwindowlayout.moc"
3434#include "moc_qmainwindowlayout_p.cpp"
Combined button and popup list for selecting options.
QMainWindowLayout * qt_mainwindow_layout(const QMainWindow *mainWindow)
static void fixToolBarOrientation(QLayoutItem *item, int dockPos)
static constexpr QWidgetAnimator::AnimationRule toAnimationRule(QMainWindow::DockOptions options)
QTextStream & operator<<(QTextStream &s, QTextStreamFunction f)
QDataStream & operator>>(QDataStream &stream, QImage &image)