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 QDOCKAREALAYOUT_P_H
41 #define QDOCKAREALAYOUT_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 "QtCore/qrect.h"
56 #include "QtCore/qpair.h"
57 #include "QtCore/qlist.h"
58 #include "QtCore/qvector.h"
59 #include "QtWidgets/qlayout.h"
60 
61 QT_REQUIRE_CONFIG(dockwidget);
62 
63 QT_BEGIN_NAMESPACE
64 
65 class QLayoutItem;
66 class QWidget;
67 class QLayoutItem;
68 class QDockAreaLayoutInfo;
69 class QPlaceHolderItem;
70 class QDockWidget;
71 class QMainWindow;
72 class QWidgetAnimator;
73 class QMainWindowLayout;
74 struct QLayoutStruct;
75 class QTabBar;
76 
77 // The classes in this file represent the tree structure that represents all the docks
78 // Also see the wiki internal documentation
79 // At the root of the tree is: QDockAreaLayout, which handles all 4 sides, so there is only one.
80 // For each side it has one QDockAreaLayoutInfo child. (See QDockAreaLayout::docks.)
81 // The QDockAreaLayoutInfo have QDockAreaLayoutItems as children (See QDockAreaLayoutInfo::item_list),
82 // which then has one QDockAreaLayoutInfo as a child. (QDockAreaLayoutItem::subInfo) or
83 // a widgetItem if this is a node of the tree (QDockAreaLayoutItem::widgetItem)
84 //
85 // A path indetifies uniquely one object in this tree, the first number being the side and all the following
86 // indexes into the QDockAreaLayoutInfo::item_list.
87 
88 struct QDockAreaLayoutItem
89 {
90     enum ItemFlags { NoFlags = 0, GapItem = 1, KeepSize = 2 };
91 
92     explicit QDockAreaLayoutItem(QLayoutItem *_widgetItem = nullptr);
93     explicit QDockAreaLayoutItem(QDockAreaLayoutInfo *_subinfo);
94     explicit QDockAreaLayoutItem(QPlaceHolderItem *_placeHolderItem);
95     QDockAreaLayoutItem(const QDockAreaLayoutItem &other);
96     ~QDockAreaLayoutItem();
97 
98     QDockAreaLayoutItem &operator = (const QDockAreaLayoutItem &other);
99 
100     bool skip() const;
101     QSize minimumSize() const;
102     QSize maximumSize() const;
103     QSize sizeHint() const;
104     bool expansive(Qt::Orientation o) const;
105     bool hasFixedSize(Qt::Orientation o) const;
106 
107     QLayoutItem *widgetItem;
108     QDockAreaLayoutInfo *subinfo;
109     QPlaceHolderItem *placeHolderItem;
110     int pos;
111     int size;
112     uint flags;
113 };
114 
115 class Q_AUTOTEST_EXPORT QPlaceHolderItem
116 {
117 public:
QPlaceHolderItem()118     QPlaceHolderItem() : hidden(false), window(false) {}
119     explicit QPlaceHolderItem(QWidget *w);
120 
121     QString objectName;
122     bool hidden, window;
123     QRect topLevelRect;
124 };
125 
126 class Q_AUTOTEST_EXPORT QDockAreaLayoutInfo
127 {
128 public:
129     QDockAreaLayoutInfo();
130     QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos, Qt::Orientation _o,
131                         int tbhape, QMainWindow *window);
132 
133     QSize minimumSize() const;
134     QSize maximumSize() const;
135     QSize sizeHint() const;
136     QSize size() const;
137 
138     bool insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem);
139     QLayoutItem *plug(const QList<int> &path);
140     QLayoutItem *unplug(const QList<int> &path);
141     enum TabMode { NoTabs, AllowTabs, ForceTabs };
142     QList<int> gapIndex(const QPoint &pos, bool nestingEnabled,
143                             TabMode tabMode) const;
144     void remove(const QList<int> &path);
145     void unnest(int index);
146     void split(int index, Qt::Orientation orientation, QLayoutItem *dockWidgetItem);
147 #if QT_CONFIG(tabbar)
148     void tab(int index, QLayoutItem *dockWidgetItem);
149 #endif
150     QDockAreaLayoutItem &item(const QList<int> &path);
151     QDockAreaLayoutInfo *info(const QList<int> &path);
152     QDockAreaLayoutInfo *info(QWidget *widget);
153 
154     enum { // sentinel values used to validate state data
155         SequenceMarker = 0xfc,
156         TabMarker = 0xfa,
157         WidgetMarker = 0xfb
158     };
159     void saveState(QDataStream &stream) const;
160     bool restoreState(QDataStream &stream, QList<QDockWidget*> &widgets, bool testing);
161 
162     void fitItems();
163     bool expansive(Qt::Orientation o) const;
164     int changeSize(int index, int size, bool below);
165     QRect itemRect(int index, bool isGap = false) const;
166     QRect itemRect(const QList<int> &path) const;
167     QRect separatorRect(int index) const;
168     QRect separatorRect(const QList<int> &path) const;
169 
170     void clear();
171     bool isEmpty() const;
172     bool onlyHasPlaceholders() const;
173     bool hasFixedSize() const;
174     QList<int> findSeparator(const QPoint &pos) const;
175     int next(int idx) const;
176     int prev(int idx) const;
177 
178     QList<int> indexOf(QWidget *widget) const;
179     QList<int> indexOfPlaceHolder(const QString &objectName) const;
180 
181     QDockWidget *apply(bool animate);
182 
183     void paintSeparators(QPainter *p, QWidget *widget, const QRegion &clip,
184                             const QPoint &mouse) const;
185     QRegion separatorRegion() const;
186     int separatorMove(int index, int delta);
187     int separatorMove(const QList<int> &separator, const QPoint &origin, const QPoint &dest);
188 
189     QLayoutItem *itemAt(int *x, int index) const;
190     QLayoutItem *takeAt(int *x, int index);
191     void deleteAllLayoutItems();
192 
193     QMainWindowLayout *mainWindowLayout() const;
194 
195     const int *sep;
196     mutable QVector<QWidget*> separatorWidgets;
197     QInternal::DockPosition dockPos;
198     Qt::Orientation o;
199     QRect rect;
200     QMainWindow *mainWindow;
201     QList<QDockAreaLayoutItem> item_list;
202 #if QT_CONFIG(tabbar)
203     void updateSeparatorWidgets() const;
204     QSet<QWidget*> usedSeparatorWidgets() const;
205 
206     quintptr currentTabId() const;
207     void setCurrentTab(QWidget *widget);
208     void setCurrentTabId(quintptr id);
209     QRect tabContentRect() const;
210     bool tabbed;
211     QTabBar *tabBar;
212     int tabBarShape;
213 
214     void reparentWidgets(QWidget *p);
215     bool updateTabBar() const;
216     void setTabBarShape(int shape);
217     QSize tabBarMinimumSize() const;
218     QSize tabBarSizeHint() const;
219 
220     QSet<QTabBar*> usedTabBars() const;
221 
222     int tabIndexToListIndex(int) const;
223     void moveTab(int from, int to);
224 #endif // QT_CONFIG(tabbar)
225 };
226 
227 class Q_AUTOTEST_EXPORT QDockAreaLayout
228 {
229 public:
230     enum { EmptyDropAreaSize = 80 }; // when a dock area is empty, how "wide" is it?
231 
232     Qt::DockWidgetArea corners[4]; // use a Qt::Corner for indexing
233     QRect rect;
234     QLayoutItem *centralWidgetItem;
235     QMainWindow *mainWindow;
236     QRect centralWidgetRect;
237     QDockAreaLayout(QMainWindow *win);
238     QDockAreaLayoutInfo docks[4];
239     int sep; // separator extent
240     bool fallbackToSizeHints; //determines if we should use the sizehint for the dock areas (true until the layout is restored or the separator is moved by user)
241     mutable QVector<QWidget*> separatorWidgets;
242 
243     bool isValid() const;
244 
245     enum { DockWidgetStateMarker = 0xfd, FloatingDockWidgetTabMarker = 0xf9 };
246     static QRect constrainedRect(QRect rect, QWidget *widget);
247     void saveState(QDataStream &stream) const;
248     bool restoreState(QDataStream &stream, const QList<QDockWidget*> &widgets, bool testing = false);
249 
250     QList<int> indexOfPlaceHolder(const QString &objectName) const;
251     QList<int> indexOf(QWidget *dockWidget) const;
252     QList<int> gapIndex(const QPoint &pos, bool disallowTabs) const;
253     QList<int> findSeparator(const QPoint &pos) const;
254 
255     QDockAreaLayoutItem &item(const QList<int> &path);
256     QDockAreaLayoutInfo *info(const QList<int> &path);
257     const QDockAreaLayoutInfo *info(const QList<int> &path) const;
258     QDockAreaLayoutInfo *info(QWidget *widget);
259     QRect itemRect(const QList<int> &path) const;
260     QRect separatorRect(int index) const;
261     QRect separatorRect(const QList<int> &path) const;
262 
263     bool insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem);
264     QLayoutItem *plug(const QList<int> &path);
265     QLayoutItem *unplug(const QList<int> &path);
266     void remove(const QList<int> &path);
267     void removePlaceHolder(const QString &name);
268 
269     void fitLayout();
270 
271     void clear();
272 
273     QSize sizeHint() const;
274     QSize minimumSize() const;
275 
276     void addDockWidget(QInternal::DockPosition pos, QDockWidget *dockWidget, Qt::Orientation orientation);
277     bool restoreDockWidget(QDockWidget *dockWidget);
278     void splitDockWidget(QDockWidget *after, QDockWidget *dockWidget,
279                          Qt::Orientation orientation);
280 #if QT_CONFIG(tabbar)
281     void tabifyDockWidget(QDockWidget *first, QDockWidget *second);
282 #endif
283     void resizeDocks(const QList<QDockWidget *> &docks, const QList<int> &sizes, Qt::Orientation o);
284 
285     void apply(bool animate);
286 
287     void paintSeparators(QPainter *p, QWidget *widget, const QRegion &clip,
288                             const QPoint &mouse) const;
289     QRegion separatorRegion() const;
290     int separatorMove(const QList<int> &separator, const QPoint &origin, const QPoint &dest);
291 #if QT_CONFIG(tabbar)
292     void updateSeparatorWidgets() const;
293 #endif // QT_CONFIG(tabbar)
294 
295     QLayoutItem *itemAt(int *x, int index) const;
296     QLayoutItem *takeAt(int *x, int index);
297     void deleteAllLayoutItems();
298 
299     void getGrid(QVector<QLayoutStruct> *ver_struct_list,
300                     QVector<QLayoutStruct> *hor_struct_list);
301     void setGrid(QVector<QLayoutStruct> *ver_struct_list,
302                     QVector<QLayoutStruct> *hor_struct_list);
303 
304     QRect gapRect(const QList<int> &path) const;
305 
306     void keepSize(QDockWidget *w);
307 #if QT_CONFIG(tabbar)
308     QSet<QTabBar*> usedTabBars() const;
309     QSet<QWidget*> usedSeparatorWidgets() const;
310 #endif // QT_CONFIG(tabbar)
311     void styleChangedEvent();
312 };
313 
314 QT_END_NAMESPACE
315 
316 #endif // QDOCKAREALAYOUT_P_H
317