1 | /**************************************************************************** |
---|---|
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtWidgets module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #ifndef QDYNAMICMAINWINDOWLAYOUT_P_H |
41 | #define QDYNAMICMAINWINDOWLAYOUT_P_H |
42 | |
43 | // |
44 | // W A R N I N G |
45 | // ------------- |
46 | // |
47 | // This file is not part of the Qt API. It exists purely as an |
48 | // implementation detail. This header file may change from version to |
49 | // version without notice, or even be removed. |
50 | // |
51 | // We mean it. |
52 | // |
53 | |
54 | #include <QtWidgets/private/qtwidgetsglobal_p.h> |
55 | #include "qmainwindow.h" |
56 | |
57 | #include "QtWidgets/qlayout.h" |
58 | #if QT_CONFIG(tabbar) |
59 | #include "QtWidgets/qtabbar.h" |
60 | #include "QtGui/qpainter.h" |
61 | #include "QtGui/qevent.h" |
62 | #endif |
63 | #include "QtCore/qvector.h" |
64 | #include "QtCore/qset.h" |
65 | #include "QtCore/qbasictimer.h" |
66 | #include "private/qlayoutengine_p.h" |
67 | #include "private/qwidgetanimator_p.h" |
68 | |
69 | #if QT_CONFIG(dockwidget) |
70 | #include "qdockarealayout_p.h" |
71 | #endif |
72 | #if QT_CONFIG(toolbar) |
73 | #include "qtoolbararealayout_p.h" |
74 | #endif |
75 | |
76 | QT_REQUIRE_CONFIG(mainwindow); |
77 | |
78 | QT_BEGIN_NAMESPACE |
79 | |
80 | class QToolBar; |
81 | class QRubberBand; |
82 | |
83 | template <typename Layout> // Make use of the "Curiously recurring template pattern" |
84 | class QMainWindowLayoutSeparatorHelper |
85 | { |
86 | Layout *layout() { return static_cast<Layout *>(this); } |
87 | const Layout *layout() const { return static_cast<const Layout *>(this); } |
88 | QWidget *window() { return layout()->parentWidget(); } |
89 | |
90 | public: |
91 | Q_DISABLE_COPY_MOVE(QMainWindowLayoutSeparatorHelper) |
92 | |
93 | QMainWindowLayoutSeparatorHelper() = default; |
94 | |
95 | QList<int> hoverSeparator; |
96 | QPoint hoverPos; |
97 | |
98 | #if QT_CONFIG(dockwidget) |
99 | |
100 | #if QT_CONFIG(cursor) |
101 | QCursor separatorCursor(const QList<int> &path); |
102 | void adjustCursor(const QPoint &pos); |
103 | QCursor oldCursor; |
104 | QCursor adjustedCursor; |
105 | bool hasOldCursor = false; |
106 | bool cursorAdjusted = false; |
107 | #endif // QT_CONFIG(cursor) |
108 | |
109 | QList<int> movingSeparator; |
110 | QPoint movingSeparatorOrigin, movingSeparatorPos; |
111 | QBasicTimer separatorMoveTimer; |
112 | |
113 | bool startSeparatorMove(const QPoint &pos); |
114 | bool separatorMove(const QPoint &pos); |
115 | bool endSeparatorMove(const QPoint &pos); |
116 | bool windowEvent(QEvent *e); |
117 | |
118 | #endif // QT_CONFIG(dockwidget) |
119 | |
120 | }; |
121 | |
122 | #if QT_CONFIG(dockwidget) |
123 | |
124 | #if QT_CONFIG(cursor) |
125 | template <typename Layout> |
126 | QCursor QMainWindowLayoutSeparatorHelper<Layout>::separatorCursor(const QList<int> &path) |
127 | { |
128 | const QDockAreaLayoutInfo *info = layout()->dockAreaLayoutInfo()->info(path); |
129 | Q_ASSERT(info != nullptr); |
130 | if (path.size() == 1) { // is this the "top-level" separator which separates a dock area |
131 | // from the central widget? |
132 | switch (path.first()) { |
133 | case QInternal::LeftDock: |
134 | case QInternal::RightDock: |
135 | return Qt::SplitHCursor; |
136 | case QInternal::TopDock: |
137 | case QInternal::BottomDock: |
138 | return Qt::SplitVCursor; |
139 | default: |
140 | break; |
141 | } |
142 | } |
143 | |
144 | // no, it's a splitter inside a dock area, separating two dock widgets |
145 | |
146 | return info->o == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor; |
147 | } |
148 | |
149 | template <typename Layout> |
150 | void QMainWindowLayoutSeparatorHelper<Layout>::adjustCursor(const QPoint &pos) |
151 | { |
152 | QWidget *w = layout()->window(); |
153 | hoverPos = pos; |
154 | |
155 | if (pos == QPoint(0, 0)) { |
156 | if (!hoverSeparator.isEmpty()) |
157 | w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator)); |
158 | hoverSeparator.clear(); |
159 | |
160 | if (cursorAdjusted) { |
161 | cursorAdjusted = false; |
162 | if (hasOldCursor) |
163 | w->setCursor(oldCursor); |
164 | else |
165 | w->unsetCursor(); |
166 | } |
167 | } else if (movingSeparator.isEmpty()) { // Don't change cursor when moving separator |
168 | QList<int> pathToSeparator = layout()->dockAreaLayoutInfo()->findSeparator(pos); |
169 | |
170 | if (pathToSeparator != hoverSeparator) { |
171 | if (!hoverSeparator.isEmpty()) |
172 | w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator)); |
173 | |
174 | hoverSeparator = pathToSeparator; |
175 | |
176 | if (hoverSeparator.isEmpty()) { |
177 | if (cursorAdjusted) { |
178 | cursorAdjusted = false; |
179 | if (hasOldCursor) |
180 | w->setCursor(oldCursor); |
181 | else |
182 | w->unsetCursor(); |
183 | } |
184 | } else { |
185 | w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator)); |
186 | if (!cursorAdjusted) { |
187 | oldCursor = w->cursor(); |
188 | hasOldCursor = w->testAttribute(attribute: Qt::WA_SetCursor); |
189 | } |
190 | adjustedCursor = separatorCursor(path: hoverSeparator); |
191 | w->setCursor(adjustedCursor); |
192 | cursorAdjusted = true; |
193 | } |
194 | } |
195 | } |
196 | } |
197 | #endif // QT_CONFIG(cursor) |
198 | |
199 | template <typename Layout> |
200 | bool QMainWindowLayoutSeparatorHelper<Layout>::windowEvent(QEvent *event) |
201 | { |
202 | QWidget *w = window(); |
203 | switch (event->type()) { |
204 | case QEvent::Paint: { |
205 | QPainter p(w); |
206 | QRegion r = static_cast<QPaintEvent *>(event)->region(); |
207 | layout()->dockAreaLayoutInfo()->paintSeparators(&p, w, r, hoverPos); |
208 | break; |
209 | } |
210 | |
211 | #if QT_CONFIG(cursor) |
212 | case QEvent::HoverMove: { |
213 | adjustCursor(pos: static_cast<QHoverEvent *>(event)->pos()); |
214 | break; |
215 | } |
216 | |
217 | // We don't want QWidget to call update() on the entire QMainWindow |
218 | // on HoverEnter and HoverLeave, hence accept the event (return true). |
219 | case QEvent::HoverEnter: |
220 | return true; |
221 | case QEvent::HoverLeave: |
222 | adjustCursor(pos: QPoint(0, 0)); |
223 | return true; |
224 | case QEvent::ShortcutOverride: // when a menu pops up |
225 | adjustCursor(pos: QPoint(0, 0)); |
226 | break; |
227 | #endif // QT_CONFIG(cursor) |
228 | |
229 | case QEvent::MouseButtonPress: { |
230 | QMouseEvent *e = static_cast<QMouseEvent *>(event); |
231 | if (e->button() == Qt::LeftButton && startSeparatorMove(pos: e->pos())) { |
232 | // The click was on a separator, eat this event |
233 | e->accept(); |
234 | return true; |
235 | } |
236 | break; |
237 | } |
238 | |
239 | case QEvent::MouseMove: { |
240 | QMouseEvent *e = static_cast<QMouseEvent *>(event); |
241 | |
242 | #if QT_CONFIG(cursor) |
243 | adjustCursor(pos: e->pos()); |
244 | #endif |
245 | if (e->buttons() & Qt::LeftButton) { |
246 | if (separatorMove(pos: e->pos())) { |
247 | // We're moving a separator, eat this event |
248 | e->accept(); |
249 | return true; |
250 | } |
251 | } |
252 | |
253 | break; |
254 | } |
255 | |
256 | case QEvent::MouseButtonRelease: { |
257 | QMouseEvent *e = static_cast<QMouseEvent *>(event); |
258 | if (endSeparatorMove(pos: e->pos())) { |
259 | // We've released a separator, eat this event |
260 | e->accept(); |
261 | return true; |
262 | } |
263 | break; |
264 | } |
265 | |
266 | #if QT_CONFIG(cursor) |
267 | case QEvent::CursorChange: |
268 | // CursorChange events are triggered as mouse moves to new widgets even |
269 | // if the cursor doesn't actually change, so do not change oldCursor if |
270 | // the "changed" cursor has same shape as adjusted cursor. |
271 | if (cursorAdjusted && adjustedCursor.shape() != w->cursor().shape()) { |
272 | oldCursor = w->cursor(); |
273 | hasOldCursor = w->testAttribute(attribute: Qt::WA_SetCursor); |
274 | |
275 | // Ensure our adjusted cursor stays visible |
276 | w->setCursor(adjustedCursor); |
277 | } |
278 | break; |
279 | #endif // QT_CONFIG(cursor) |
280 | case QEvent::Timer: |
281 | if (static_cast<QTimerEvent *>(event)->timerId() == separatorMoveTimer.timerId()) { |
282 | // let's move the separators |
283 | separatorMoveTimer.stop(); |
284 | if (movingSeparator.isEmpty()) |
285 | return true; |
286 | if (movingSeparatorOrigin == movingSeparatorPos) |
287 | return true; |
288 | |
289 | // when moving the separator, we need to update the previous position |
290 | window()->update(layout()->dockAreaLayoutInfo()->separatorRegion()); |
291 | |
292 | layout()->layoutState = layout()->savedState; |
293 | layout()->dockAreaLayoutInfo()->separatorMove(movingSeparator, movingSeparatorOrigin, |
294 | movingSeparatorPos); |
295 | movingSeparatorPos = movingSeparatorOrigin; |
296 | return true; |
297 | } |
298 | break; |
299 | default: |
300 | break; |
301 | } |
302 | return false; |
303 | } |
304 | |
305 | template <typename Layout> |
306 | bool QMainWindowLayoutSeparatorHelper<Layout>::startSeparatorMove(const QPoint &pos) |
307 | { |
308 | movingSeparator = layout()->dockAreaLayoutInfo()->findSeparator(pos); |
309 | |
310 | if (movingSeparator.isEmpty()) |
311 | return false; |
312 | |
313 | layout()->savedState = layout()->layoutState; |
314 | movingSeparatorPos = movingSeparatorOrigin = pos; |
315 | |
316 | return true; |
317 | } |
318 | template <typename Layout> |
319 | bool QMainWindowLayoutSeparatorHelper<Layout>::separatorMove(const QPoint &pos) |
320 | { |
321 | if (movingSeparator.isEmpty()) |
322 | return false; |
323 | movingSeparatorPos = pos; |
324 | separatorMoveTimer.start(0, window()); |
325 | return true; |
326 | } |
327 | template <typename Layout> |
328 | bool QMainWindowLayoutSeparatorHelper<Layout>::endSeparatorMove(const QPoint &) |
329 | { |
330 | if (movingSeparator.isEmpty()) |
331 | return false; |
332 | movingSeparator.clear(); |
333 | layout()->savedState.clear(); |
334 | return true; |
335 | } |
336 | |
337 | class QDockWidgetGroupWindow : public QWidget |
338 | { |
339 | Q_OBJECT |
340 | public: |
341 | explicit QDockWidgetGroupWindow(QWidget* parent = nullptr, Qt::WindowFlags f = { }) |
342 | : QWidget(parent, f) {} |
343 | QDockAreaLayoutInfo *layoutInfo() const; |
344 | #if QT_CONFIG(tabbar) |
345 | const QDockAreaLayoutInfo *tabLayoutInfo() const; |
346 | QDockWidget *activeTabbedDockWidget() const; |
347 | #endif |
348 | void destroyOrHideIfEmpty(); |
349 | void adjustFlags(); |
350 | bool hasNativeDecos() const; |
351 | |
352 | bool hover(QLayoutItem *widgetItem, const QPoint &mousePos); |
353 | void updateCurrentGapRect(); |
354 | void restore(); |
355 | void apply(); |
356 | |
357 | QRect currentGapRect; |
358 | QList<int> currentGapPos; |
359 | |
360 | signals: |
361 | void resized(); |
362 | |
363 | protected: |
364 | bool event(QEvent *) override; |
365 | void paintEvent(QPaintEvent*) override; |
366 | |
367 | private: |
368 | QSize m_removedFrameSize; |
369 | }; |
370 | |
371 | // This item will be used in the layout for the gap item. We cannot use QWidgetItem directly |
372 | // because QWidgetItem functions return an empty size for widgets that are are floating. |
373 | class QDockWidgetGroupWindowItem : public QWidgetItem |
374 | { |
375 | public: |
376 | explicit QDockWidgetGroupWindowItem(QDockWidgetGroupWindow *parent) : QWidgetItem(parent) {} |
377 | QSize minimumSize() const override { return lay()->minimumSize(); } |
378 | QSize maximumSize() const override { return lay()->maximumSize(); } |
379 | QSize sizeHint() const override { return lay()->sizeHint(); } |
380 | |
381 | private: |
382 | QLayout *lay() const { return const_cast<QDockWidgetGroupWindowItem *>(this)->widget()->layout(); } |
383 | }; |
384 | #endif // QT_CONFIG(dockwidget) |
385 | |
386 | /* This data structure represents the state of all the tool-bars and dock-widgets. It's value based |
387 | so it can be easilly copied into a temporary variable. All operations are performed without moving |
388 | any widgets. Only when we are sure we have the desired state, we call apply(), which moves the |
389 | widgets. |
390 | */ |
391 | |
392 | class QMainWindowLayoutState |
393 | { |
394 | public: |
395 | QRect rect; |
396 | QMainWindow *mainWindow; |
397 | |
398 | QMainWindowLayoutState(QMainWindow *win); |
399 | |
400 | #if QT_CONFIG(toolbar) |
401 | QToolBarAreaLayout toolBarAreaLayout; |
402 | #endif |
403 | |
404 | #if QT_CONFIG(dockwidget) |
405 | QDockAreaLayout dockAreaLayout; |
406 | #else |
407 | QLayoutItem *centralWidgetItem; |
408 | QRect centralWidgetRect; |
409 | #endif |
410 | |
411 | void apply(bool animated); |
412 | void deleteAllLayoutItems(); |
413 | void deleteCentralWidgetItem(); |
414 | |
415 | QSize sizeHint() const; |
416 | QSize minimumSize() const; |
417 | void fitLayout(); |
418 | |
419 | QLayoutItem *itemAt(int index, int *x) const; |
420 | QLayoutItem *takeAt(int index, int *x); |
421 | QList<int> indexOf(QWidget *widget) const; |
422 | QLayoutItem *item(const QList<int> &path); |
423 | QRect itemRect(const QList<int> &path) const; |
424 | QRect gapRect(const QList<int> &path) const; // ### get rid of this, use itemRect() instead |
425 | |
426 | bool contains(QWidget *widget) const; |
427 | |
428 | void setCentralWidget(QWidget *widget); |
429 | QWidget *centralWidget() const; |
430 | |
431 | QList<int> gapIndex(QWidget *widget, const QPoint &pos) const; |
432 | bool insertGap(const QList<int> &path, QLayoutItem *item); |
433 | void remove(const QList<int> &path); |
434 | void remove(QLayoutItem *item); |
435 | void clear(); |
436 | bool isValid() const; |
437 | |
438 | QLayoutItem *plug(const QList<int> &path); |
439 | QLayoutItem *unplug(const QList<int> &path, QMainWindowLayoutState *savedState = nullptr); |
440 | |
441 | void saveState(QDataStream &stream) const; |
442 | bool checkFormat(QDataStream &stream); |
443 | bool restoreState(QDataStream &stream, const QMainWindowLayoutState &oldState); |
444 | }; |
445 | |
446 | class Q_AUTOTEST_EXPORT QMainWindowLayout |
447 | : public QLayout, |
448 | public QMainWindowLayoutSeparatorHelper<QMainWindowLayout> |
449 | { |
450 | Q_OBJECT |
451 | |
452 | public: |
453 | QMainWindowLayoutState layoutState, savedState; |
454 | |
455 | QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLayout); |
456 | ~QMainWindowLayout(); |
457 | |
458 | QMainWindow::DockOptions dockOptions; |
459 | void setDockOptions(QMainWindow::DockOptions opts); |
460 | |
461 | // status bar |
462 | |
463 | QLayoutItem *statusbar; |
464 | |
465 | #if QT_CONFIG(statusbar) |
466 | QStatusBar *statusBar() const; |
467 | void setStatusBar(QStatusBar *sb); |
468 | #endif |
469 | |
470 | // central widget |
471 | |
472 | QWidget *centralWidget() const; |
473 | void setCentralWidget(QWidget *cw); |
474 | |
475 | // toolbars |
476 | |
477 | #if QT_CONFIG(toolbar) |
478 | void addToolBarBreak(Qt::ToolBarArea area); |
479 | void insertToolBarBreak(QToolBar *before); |
480 | void removeToolBarBreak(QToolBar *before); |
481 | |
482 | void addToolBar(Qt::ToolBarArea area, QToolBar *toolbar, bool needAddChildWidget = true); |
483 | void insertToolBar(QToolBar *before, QToolBar *toolbar); |
484 | Qt::ToolBarArea toolBarArea(const QToolBar *toolbar) const; |
485 | bool toolBarBreak(QToolBar *toolBar) const; |
486 | void getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar) const; |
487 | void removeToolBar(QToolBar *toolbar); |
488 | void toggleToolBarsVisible(); |
489 | void moveToolBar(QToolBar *toolbar, int pos); |
490 | #endif |
491 | |
492 | // dock widgets |
493 | |
494 | #if QT_CONFIG(dockwidget) |
495 | void setCorner(Qt::Corner corner, Qt::DockWidgetArea area); |
496 | Qt::DockWidgetArea corner(Qt::Corner corner) const; |
497 | void addDockWidget(Qt::DockWidgetArea area, |
498 | QDockWidget *dockwidget, |
499 | Qt::Orientation orientation); |
500 | void splitDockWidget(QDockWidget *after, |
501 | QDockWidget *dockwidget, |
502 | Qt::Orientation orientation); |
503 | Qt::DockWidgetArea dockWidgetArea(QWidget* widget) const; |
504 | bool restoreDockWidget(QDockWidget *dockwidget); |
505 | #if QT_CONFIG(tabbar) |
506 | void tabifyDockWidget(QDockWidget *first, QDockWidget *second); |
507 | void raise(QDockWidget *widget); |
508 | void setVerticalTabsEnabled(bool enabled); |
509 | |
510 | QDockAreaLayoutInfo *dockInfo(QWidget *w); |
511 | bool _documentMode; |
512 | bool documentMode() const; |
513 | void setDocumentMode(bool enabled); |
514 | |
515 | QTabBar *getTabBar(); |
516 | QSet<QTabBar*> usedTabBars; |
517 | QList<QTabBar*> unusedTabBars; |
518 | bool verticalTabsEnabled; |
519 | |
520 | QWidget *getSeparatorWidget(); |
521 | QSet<QWidget*> usedSeparatorWidgets; |
522 | QList<QWidget*> unusedSeparatorWidgets; |
523 | int sep; // separator extent |
524 | |
525 | #if QT_CONFIG(tabwidget) |
526 | QTabWidget::TabPosition tabPositions[QInternal::DockCount]; |
527 | QTabWidget::TabShape _tabShape; |
528 | |
529 | QTabWidget::TabShape tabShape() const; |
530 | void setTabShape(QTabWidget::TabShape tabShape); |
531 | QTabWidget::TabPosition tabPosition(Qt::DockWidgetArea area) const; |
532 | void setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition); |
533 | |
534 | QDockWidgetGroupWindow *createTabbedDockWindow(); |
535 | #endif // QT_CONFIG(tabwidget) |
536 | #endif // QT_CONFIG(tabbar) |
537 | |
538 | QDockAreaLayout *dockAreaLayoutInfo() { return &layoutState.dockAreaLayout; } |
539 | void keepSize(QDockWidget *w); |
540 | #endif // QT_CONFIG(dockwidget) |
541 | |
542 | // save/restore |
543 | |
544 | enum VersionMarkers { // sentinel values used to validate state data |
545 | VersionMarker = 0xff |
546 | }; |
547 | void saveState(QDataStream &stream) const; |
548 | bool restoreState(QDataStream &stream); |
549 | |
550 | // QLayout interface |
551 | |
552 | void addItem(QLayoutItem *item) override; |
553 | void setGeometry(const QRect &r) override; |
554 | QLayoutItem *itemAt(int index) const override; |
555 | QLayoutItem *takeAt(int index) override; |
556 | int count() const override; |
557 | |
558 | QSize sizeHint() const override; |
559 | QSize minimumSize() const override; |
560 | mutable QSize szHint; |
561 | mutable QSize minSize; |
562 | void invalidate() override; |
563 | |
564 | // animations |
565 | |
566 | QWidgetAnimator widgetAnimator; |
567 | QList<int> currentGapPos; |
568 | QRect currentGapRect; |
569 | QWidget *pluggingWidget; |
570 | #if QT_CONFIG(rubberband) |
571 | QPointer<QRubberBand> gapIndicator; |
572 | #endif |
573 | #if QT_CONFIG(dockwidget) |
574 | QPointer<QDockWidgetGroupWindow> currentHoveredFloat; // set when dragging over a floating dock widget |
575 | void setCurrentHoveredFloat(QDockWidgetGroupWindow *w); |
576 | #endif |
577 | |
578 | void hover(QLayoutItem *widgetItem, const QPoint &mousePos); |
579 | bool plug(QLayoutItem *widgetItem); |
580 | QLayoutItem *unplug(QWidget *widget, bool group = false); |
581 | void revert(QLayoutItem *widgetItem); |
582 | void paintDropIndicator(QPainter *p, QWidget *widget, const QRegion &clip); |
583 | void applyState(QMainWindowLayoutState &newState, bool animate = true); |
584 | void restore(bool keepSavedState = false); |
585 | void animationFinished(QWidget *widget); |
586 | |
587 | private Q_SLOTS: |
588 | void updateGapIndicator(); |
589 | #if QT_CONFIG(dockwidget) |
590 | #if QT_CONFIG(tabbar) |
591 | void tabChanged(); |
592 | void tabMoved(int from, int to); |
593 | #endif |
594 | #endif |
595 | private: |
596 | #if QT_CONFIG(tabbar) |
597 | void updateTabBarShapes(); |
598 | #endif |
599 | }; |
600 | |
601 | #if QT_CONFIG(dockwidget) && !defined(QT_NO_DEBUG_STREAM) |
602 | class QDebug; |
603 | QDebug operator<<(QDebug debug, const QDockAreaLayout &layout); |
604 | QDebug operator<<(QDebug debug, const QMainWindowLayout *layout); |
605 | #endif |
606 | |
607 | QT_END_NAMESPACE |
608 | |
609 | #endif // QDYNAMICMAINWINDOWLAYOUT_P_H |
610 |
Definitions
- QMainWindowLayoutSeparatorHelper
- layout
- layout
- window
- QMainWindowLayoutSeparatorHelper
- QMainWindowLayoutSeparatorHelper
- QMainWindowLayoutSeparatorHelper
- separatorCursor
- adjustCursor
- windowEvent
- startSeparatorMove
- separatorMove
- endSeparatorMove
- QDockWidgetGroupWindow
- QDockWidgetGroupWindow
- QDockWidgetGroupWindowItem
- QDockWidgetGroupWindowItem
- minimumSize
- maximumSize
- sizeHint
- lay
- QMainWindowLayoutState
- QMainWindowLayout
- dockAreaLayoutInfo
Learn Advanced QML with KDAB
Find out more