5#ifndef QMAINWINDOWLAYOUT_P_H
6#define QMAINWINDOWLAYOUT_P_H
19#include <QtWidgets/private/qtwidgetsglobal_p.h>
22#include "QtWidgets/qlayout.h"
24#include "QtWidgets/qtabbar.h"
25#include "QtGui/qpainter.h"
26#include "QtGui/qevent.h"
28#include "QtCore/qbasictimer.h"
29#include "QtCore/qlist.h"
30#include "QtCore/qset.h"
31#include "private/qlayoutengine_p.h"
32#include "private/qwidgetanimator_p.h"
33#if QT_CONFIG(dockwidget)
34#include "private/qdockwidget_p.h"
36#include "qdockarealayout_p.h"
37#include "qdockwidget.h"
39struct QDockWidgetPrivate {
40 enum class DragScope {
46#include "qtoolbararealayout_p.h"
50#include <QtCore/qloggingcategory.h>
51#include <QtCore/qpointer.h>
62template <
typename Layout>
65 Layout *layout() {
return static_cast<Layout *>(
this); }
66 const Layout *layout()
const {
return static_cast<
const Layout *>(
this); }
67 QWidget *window() {
return layout()->parentWidget(); }
77#if QT_CONFIG(dockwidget)
104#if QT_CONFIG(dockwidget)
107template <
typename Layout>
108QCursor QMainWindowLayoutSeparatorHelper<Layout>::separatorCursor(
const QList<
int> &path)
110 const QDockAreaLayoutInfo *info = layout()->dockAreaLayoutInfo()->info(path);
111 Q_ASSERT(info !=
nullptr);
112 if (path.size() == 1) {
114 switch (path.first()) {
115 case QInternal::LeftDock:
116 case QInternal::RightDock:
117 return Qt::SplitHCursor;
118 case QInternal::TopDock:
119 case QInternal::BottomDock:
120 return Qt::SplitVCursor;
128 return info->o == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor;
131template <
typename Layout>
132void QMainWindowLayoutSeparatorHelper<Layout>::adjustCursor(
const QPoint &pos)
134 QWidget *w = layout()->window();
137 if (pos == QPoint(0, 0)) {
138 if (!hoverSeparator.isEmpty())
139 w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator));
140 hoverSeparator.clear();
142 if (cursorAdjusted) {
143 cursorAdjusted =
false;
145 w->setCursor(oldCursor);
149 }
else if (movingSeparator.isEmpty()) {
150 QList<
int> pathToSeparator = findSeparator(pos);
152 if (pathToSeparator != hoverSeparator) {
153 if (!hoverSeparator.isEmpty())
154 w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator));
156 hoverSeparator = pathToSeparator;
158 if (hoverSeparator.isEmpty()) {
159 if (cursorAdjusted) {
160 cursorAdjusted =
false;
162 w->setCursor(oldCursor);
167 w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator));
168 if (!cursorAdjusted) {
169 oldCursor = w->cursor();
170 hasOldCursor = w->testAttribute(Qt::WA_SetCursor);
172 adjustedCursor = separatorCursor(hoverSeparator);
173 w->setCursor(adjustedCursor);
174 cursorAdjusted =
true;
181template <
typename Layout>
182bool QMainWindowLayoutSeparatorHelper<Layout>::windowEvent(QEvent *event)
184 QWidget *w = window();
185 switch (event->type()) {
186 case QEvent::Paint: {
188 QRegion r =
static_cast<QPaintEvent *>(event)->region();
189 layout()->dockAreaLayoutInfo()->paintSeparators(&p, w, r, hoverPos);
194 case QEvent::HoverMove: {
195 adjustCursor(
static_cast<QHoverEvent *>(event)->position().toPoint());
201 case QEvent::HoverEnter:
203 case QEvent::HoverLeave:
204 adjustCursor(QPoint(0, 0));
206 case QEvent::ShortcutOverride:
207 adjustCursor(QPoint(0, 0));
211 case QEvent::MouseButtonPress: {
212 QMouseEvent *e =
static_cast<QMouseEvent *>(event);
213 if (e->button() == Qt::LeftButton && startSeparatorMove(e->position().toPoint())) {
221 case QEvent::MouseMove: {
222 QMouseEvent *e =
static_cast<QMouseEvent *>(event);
225 adjustCursor(e->position().toPoint());
227 if (e->buttons() & Qt::LeftButton) {
228 if (separatorMove(e->position().toPoint())) {
238 case QEvent::MouseButtonRelease: {
239 QMouseEvent *e =
static_cast<QMouseEvent *>(event);
240 if (endSeparatorMove(e->position().toPoint())) {
249 case QEvent::CursorChange:
253 if (cursorAdjusted && adjustedCursor.shape() != w->cursor().shape()) {
254 oldCursor = w->cursor();
255 hasOldCursor = w->testAttribute(Qt::WA_SetCursor);
258 w->setCursor(adjustedCursor);
263 if (
static_cast<QTimerEvent *>(event)->timerId() == separatorMoveTimer.timerId()) {
265 separatorMoveTimer.stop();
266 if (movingSeparator.isEmpty())
268 if (movingSeparatorOrigin == movingSeparatorPos)
272 window()->update(layout()->dockAreaLayoutInfo()->separatorRegion());
274 layout()->layoutState = layout()->savedState;
275 layout()->dockAreaLayoutInfo()->separatorMove(movingSeparator, movingSeparatorOrigin,
277 movingSeparatorPos = movingSeparatorOrigin;
287template <
typename Layout>
288QList<
int> QMainWindowLayoutSeparatorHelper<Layout>::findSeparator(
const QPoint &pos)
const
290 Layout *layout =
const_cast<Layout*>(
this->layout());
291#if QT_CONFIG(toolbar)
292 QToolBarAreaLayout *toolBarAreaLayout = layout->toolBarAreaLayout();
293 if (toolBarAreaLayout && !toolBarAreaLayout->isEmpty()) {
298 const QWidget *widget = layout->window();
299 QWidget *childWidget = widget->childAt(pos);
300 while (childWidget && childWidget != widget) {
301 if (
auto *toolBar = qobject_cast<QToolBar*>(childWidget)) {
302 if (!toolBarAreaLayout->indexOf(toolBar).isEmpty())
305 childWidget = childWidget->parentWidget();
309 return layout->dockAreaLayoutInfo()->findSeparator(pos);
312template <
typename Layout>
313bool QMainWindowLayoutSeparatorHelper<Layout>::startSeparatorMove(
const QPoint &pos)
315 movingSeparator = findSeparator(pos);
317 if (movingSeparator.isEmpty())
320 layout()->savedState = layout()->layoutState;
321 movingSeparatorPos = movingSeparatorOrigin = pos;
325template <
typename Layout>
326bool QMainWindowLayoutSeparatorHelper<Layout>::separatorMove(
const QPoint &pos)
328 if (movingSeparator.isEmpty())
330 movingSeparatorPos = pos;
331 separatorMoveTimer.start(0, window());
334template <
typename Layout>
335bool QMainWindowLayoutSeparatorHelper<Layout>::endSeparatorMove(
const QPoint &)
337 if (movingSeparator.isEmpty())
339 movingSeparator.clear();
340 layout()->savedState.clear();
344class Q_AUTOTEST_EXPORT QDockWidgetGroupWindow :
public QWidget
348 explicit QDockWidgetGroupWindow(QWidget *parent =
nullptr, Qt::WindowFlags f = {})
352 QDockAreaLayoutInfo *layoutInfo()
const;
354 const QDockAreaLayoutInfo *tabLayoutInfo()
const;
355 QDockWidget *activeTabbedDockWidget()
const;
357 void destroyOrHideIfEmpty();
358 bool hasVisibleDockWidgets()
const;
360 bool hasNativeDecos()
const;
362 bool hover(QLayoutItem *widgetItem,
const QPoint &mousePos);
363 void updateCurrentGapRect();
366 void childEvent(QChildEvent *event) override;
367 void reparentToMainWindow(QDockWidget *dockWidget);
368 void destroyIfSingleItemLeft();
369 QList<QDockWidget *> dockWidgets()
const {
return findChildren<QDockWidget *>(); }
371 QRect currentGapRect;
372 QList<
int> currentGapPos;
378 bool event(QEvent *) override;
379 bool eventFilter(QObject *obj, QEvent *event) override;
380 void paintEvent(QPaintEvent*) override;
383 QSize m_removedFrameSize;
388class QDockWidgetGroupWindowItem :
public QWidgetItem
391 explicit QDockWidgetGroupWindowItem(QDockWidgetGroupWindow *parent) : QWidgetItem(parent) {}
395 QSize minimumSize()
const override
397 if (
auto dw = widget()->findChild<QDockWidget *>())
398 return dw->minimumSize();
399 return lay()->minimumSize();
401 QSize maximumSize()
const override
403 auto dw = widget()->findChild<QDockWidget *>();
405 return dw->maximumSize();
406 return lay()->maximumSize();
408 QSize sizeHint()
const override
410 auto dw = widget()->findChild<QDockWidget *>();
412 return dw->sizeHint();
413 return lay()->sizeHint();
415 QWidget* widget()
const override {
return wid; }
418 QLayout *lay()
const {
return const_cast<QDockWidgetGroupWindowItem *>(
this)->widget()->layout(); }
423
424
425
426
432 QMainWindow *mainWindow;
434 QMainWindowLayoutState(QMainWindow *win);
436#if QT_CONFIG(toolbar)
437 QToolBarAreaLayout toolBarAreaLayout;
440#if QT_CONFIG(dockwidget)
441 QDockAreaLayout dockAreaLayout;
443 QLayoutItem *centralWidgetItem;
444 QRect centralWidgetRect;
447 void apply(
bool animated);
448 void deleteAllLayoutItems();
449 void deleteCentralWidgetItem();
451 QSize sizeHint()
const;
452 QSize minimumSize()
const;
456 QLayoutItem *itemAt(
int index,
int *x)
const;
457 QLayoutItem *takeAt(
int index,
int *x);
458 QList<
int> indexOf(QWidget *widget)
const;
459 QLayoutItem *item(
const QList<
int> &path);
460 QRect itemRect(
const QList<
int> &path)
const;
461 QRect gapRect(
const QList<
int> &path)
const;
463 bool contains(QWidget *widget)
const;
465 void setCentralWidget(QWidget *widget);
466 QWidget *centralWidget()
const;
468 QList<
int> gapIndex(QWidget *widget,
const QPoint &pos)
const;
469 bool insertGap(
const QList<
int> &path, QLayoutItem *item);
470 void remove(
const QList<
int> &path);
471 void remove(QLayoutItem *item);
473 bool isValid()
const;
475 QLayoutItem *plug(
const QList<
int> &path);
476 QLayoutItem *unplug(
const QList<
int> &path, QMainWindowLayoutState *savedState =
nullptr);
478 void saveState(QDataStream &stream)
const;
479 bool checkFormat(QDataStream &stream);
480 bool restoreState(QDataStream &stream,
const QMainWindowLayoutState &oldState);
483class QMainWindowTabBar;
486 public QMainWindowLayoutSeparatorHelper<QMainWindowLayout>
491 QMainWindowLayoutState layoutState, savedState;
492 std::unique_ptr<QMainWindowLayoutState> restoredState;
494 QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLayout);
495 ~QMainWindowLayout();
497 QMainWindow::DockOptions dockOptions;
498 void setDockOptions(QMainWindow::DockOptions opts);
500 QLayoutItem *statusbar;
503#if QT_CONFIG(statusbar)
504 QStatusBar *statusBar()
const;
505 void setStatusBar(QStatusBar *sb);
509 QWidget *centralWidget()
const;
510 void setCentralWidget(QWidget *cw);
513#if QT_CONFIG(toolbar)
514 void addToolBarBreak(Qt::ToolBarArea area);
515 void insertToolBarBreak(QToolBar *before);
516 void removeToolBarBreak(QToolBar *before);
518 void addToolBar(Qt::ToolBarArea area, QToolBar *toolbar,
bool needAddChildWidget =
true);
519 void insertToolBar(QToolBar *before, QToolBar *toolbar);
520 Qt::ToolBarArea toolBarArea(
const QToolBar *toolbar)
const;
521 bool toolBarBreak(QToolBar *toolBar)
const;
522 void getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar)
const;
523 void removeToolBar(QToolBar *toolbar);
524 void toggleToolBarsVisible();
525 void moveToolBar(QToolBar *toolbar,
int pos);
526 QToolBarAreaLayout *toolBarAreaLayout() {
return &layoutState.toolBarAreaLayout; }
530#if QT_CONFIG(dockwidget)
531 void setCorner(Qt::Corner corner, Qt::DockWidgetArea area);
532 Qt::DockWidgetArea corner(Qt::Corner corner)
const;
533 enum DockWidgetAreaSize {Visible, Maximum};
534 QRect dockWidgetAreaRect(Qt::DockWidgetArea area, DockWidgetAreaSize size = Maximum)
const;
535 void addDockWidget(Qt::DockWidgetArea area,
536 QDockWidget *dockwidget,
537 Qt::Orientation orientation);
538 void splitDockWidget(QDockWidget *after,
539 QDockWidget *dockwidget,
540 Qt::Orientation orientation);
541 Qt::DockWidgetArea dockWidgetArea(
const QWidget* widget)
const;
542 bool restoreDockWidget(QDockWidget *dockwidget);
544 void tabifyDockWidget(QDockWidget *first, QDockWidget *second);
545 void raise(QDockWidget *widget);
546 void setVerticalTabsEnabled(
bool enabled);
548 QDockAreaLayoutInfo *dockInfo(QWidget *w);
550 bool documentMode()
const;
551 void setDocumentMode(
bool enabled);
553 QTabBar *getTabBar();
554 void unuseTabBar(QTabBar *bar);
555 QSet<QTabBar*> usedTabBars;
556 bool verticalTabsEnabled;
558 QWidget *getSeparatorWidget();
559 QSet<QWidget*> usedSeparatorWidgets;
562#if QT_CONFIG(tabwidget)
563 QTabWidget::TabPosition tabPositions[QInternal::DockCount];
564 QTabWidget::TabShape _tabShape;
566 QTabWidget::TabShape tabShape()
const;
567 void setTabShape(QTabWidget::TabShape tabShape);
568 QTabWidget::TabPosition tabPosition(Qt::DockWidgetArea area)
const;
569 void setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition);
571 QDockWidgetGroupWindow *createTabbedDockWindow();
575 QDockAreaLayout *dockAreaLayoutInfo() {
return &layoutState.dockAreaLayout; }
576 void keepSize(QDockWidget *w);
580 enum VersionMarkers {
583 void saveState(QDataStream &stream)
const;
584 bool restoreState(QDataStream &stream);
585 QBasicTimer discardRestoredStateTimer;
588 void addItem(QLayoutItem *item) override;
589 void setGeometry(
const QRect &r) override;
590 QLayoutItem *itemAt(
int index)
const override;
591 QLayoutItem *takeAt(
int index) override;
592 int count()
const override;
594 QSize sizeHint()
const override;
595 QSize minimumSize()
const override;
596 mutable QSize szHint;
597 mutable QSize minSize;
598 void invalidate() override;
601 QWidgetAnimator widgetAnimator;
602 QList<
int> currentGapPos;
603 QRect currentGapRect;
604 QWidget *pluggingWidget;
605#if QT_CONFIG(rubberband)
606 QPointer<QRubberBand> gapIndicator;
608#if QT_CONFIG(dockwidget)
609 QPointer<QDockWidgetGroupWindow> currentHoveredFloat;
610 void setCurrentHoveredFloat(QDockWidgetGroupWindow *w);
612 bool isDockWidgetTabbed(
const QDockWidget *dockWidget)
const;
613 QList<QDockWidget *> tabifiedDockWidgets(
const QDockWidget *dockWidget)
const;
614 QMainWindowTabBar *findTabBar(
const QDockWidget *dockWidget)
const;
617 bool isInApplyState =
false;
619 void hover(QLayoutItem *hoverTarget,
const QPoint &mousePos);
620 bool plug(QLayoutItem *widgetItem);
621 QLayoutItem *unplug(QWidget *widget, QDockWidgetPrivate::DragScope scope);
622 void revert(QLayoutItem *widgetItem);
623 void applyState(QMainWindowLayoutState &newState,
bool animate =
true);
624 void applyRestoredState();
625 void restore(
bool keepSavedState =
false);
626 void animationFinished(QWidget *widget);
628#if QT_CONFIG(draganddrop)
629 static bool needsPlatformDrag();
630 Qt::DropAction performPlatformWidgetDrag(QLayoutItem *widgetItem,
const QPoint &pressPosition);
631 QLayoutItem *draggingWidget =
nullptr;
635 void timerEvent(QTimerEvent *e) override;
638 void updateGapIndicator();
639#if QT_CONFIG(dockwidget)
642 void tabMoved(
int from,
int to);
648 void updateTabBarShapes();
650 bool isInRestoreState =
false;
653#if QT_CONFIG(dockwidget) && !defined(QT_NO_DEBUG_STREAM)
655QDebug operator<<(QDebug debug,
const QDockAreaLayout &layout);
656QDebug operator<<(QDebug debug,
const QMainWindowLayout *layout);
QList< int > hoverSeparator
The QMainWindow class provides a main application window.
QT_REQUIRE_CONFIG(animation)
static int grow(QLayoutStruct &ls, int delta)
static QRect dockedGeometry(QWidget *widget)
static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
static int realMinSize(const QDockAreaLayoutInfo &info)
static int qMax(int i1, int i2, int i3)
static int shrink(QLayoutStruct &ls, int delta)
static 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)
QT_REQUIRE_CONFIG(dockwidget)
QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcher)
QT_REQUIRE_CONFIG(mainwindow)