|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtGui module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qmainwindowlayout_p.h" |
|
43 #include "qdockarealayout_p.h" |
|
44 |
|
45 #ifndef QT_NO_MAINWINDOW |
|
46 #include "qdockwidget.h" |
|
47 #include "qdockwidget_p.h" |
|
48 #include "qtoolbar_p.h" |
|
49 #include "qmainwindow.h" |
|
50 #include "qmainwindowlayout_p.h" |
|
51 #include "qtoolbar.h" |
|
52 #include "qtoolbarlayout_p.h" |
|
53 #include "qwidgetanimator_p.h" |
|
54 #include "qrubberband.h" |
|
55 #include "qdockwidget_p.h" |
|
56 #include "qtabbar_p.h" |
|
57 |
|
58 #include <qapplication.h> |
|
59 #include <qstatusbar.h> |
|
60 #include <qstring.h> |
|
61 #include <qstyle.h> |
|
62 #include <qvarlengtharray.h> |
|
63 #include <qstack.h> |
|
64 #include <qmap.h> |
|
65 #include <qtimer.h> |
|
66 |
|
67 #include <qdebug.h> |
|
68 |
|
69 #include <private/qapplication_p.h> |
|
70 #include <private/qlayoutengine_p.h> |
|
71 #ifdef Q_WS_MAC |
|
72 # include <private/qcore_mac_p.h> |
|
73 # include <private/qt_cocoa_helpers_mac_p.h> |
|
74 #endif |
|
75 |
|
76 #ifdef Q_DEBUG_MAINWINDOW_LAYOUT |
|
77 # include <QTextStream> |
|
78 #endif |
|
79 |
|
80 QT_BEGIN_NAMESPACE |
|
81 |
|
82 /****************************************************************************** |
|
83 ** debug |
|
84 */ |
|
85 |
|
86 #if defined(Q_DEBUG_MAINWINDOW_LAYOUT) && !defined(QT_NO_DOCKWIDGET) |
|
87 |
|
88 static QTextStream qout(stderr, QIODevice::WriteOnly); |
|
89 |
|
90 static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent); |
|
91 |
|
92 static void dumpLayout(QTextStream &qout, const QDockAreaLayoutItem &item, QString indent) |
|
93 { |
|
94 qout << indent << "QDockAreaLayoutItem: " |
|
95 << "pos: " << item.pos << " size:" << item.size |
|
96 << " gap:" << (item.flags & QDockAreaLayoutItem::GapItem) |
|
97 << " keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize) << '\n'; |
|
98 indent += QLatin1String(" "); |
|
99 if (item.widgetItem != 0) { |
|
100 qout << indent << "widget: " |
|
101 << item.widgetItem->widget()->metaObject()->className() |
|
102 << ' ' << item.widgetItem->widget()->windowTitle() << '\n'; |
|
103 } else if (item.subinfo != 0) { |
|
104 qout << indent << "subinfo:\n"; |
|
105 dumpLayout(qout, *item.subinfo, indent + QLatin1String(" ")); |
|
106 } else if (item.placeHolderItem != 0) { |
|
107 QRect r = item.placeHolderItem->topLevelRect; |
|
108 qout << indent << "placeHolder: " |
|
109 << "pos: " << item.pos << " size:" << item.size |
|
110 << " gap:" << (item.flags & QDockAreaLayoutItem::GapItem) |
|
111 << " keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize) |
|
112 << " objectName:" << item.placeHolderItem->objectName |
|
113 << " hidden:" << item.placeHolderItem->hidden |
|
114 << " window:" << item.placeHolderItem->window |
|
115 << " rect:" << r.x() << ',' << r.y() << ' ' |
|
116 << r.width() << 'x' << r.height() << '\n'; |
|
117 } |
|
118 qout.flush(); |
|
119 } |
|
120 |
|
121 static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent) |
|
122 { |
|
123 qout << indent << "QDockAreaLayoutInfo: " |
|
124 << layout.rect.left() << ',' |
|
125 << layout.rect.top() << ' ' |
|
126 << layout.rect.width() << 'x' |
|
127 << layout.rect.height() |
|
128 << " orient:" << layout.o |
|
129 << " tabbed:" << layout.tabbed |
|
130 << " tbshape:" << layout.tabBarShape << '\n'; |
|
131 |
|
132 indent += QLatin1String(" "); |
|
133 |
|
134 for (int i = 0; i < layout.item_list.count(); ++i) { |
|
135 qout << indent << "Item: " << i << '\n'; |
|
136 dumpLayout(qout, layout.item_list.at(i), indent + QLatin1String(" ")); |
|
137 } |
|
138 qout.flush(); |
|
139 }; |
|
140 |
|
141 static void dumpLayout(QTextStream &qout, const QDockAreaLayout &layout, QString indent) |
|
142 { |
|
143 qout << indent << "QDockAreaLayout: " |
|
144 << layout.rect.left() << ',' |
|
145 << layout.rect.top() << ' ' |
|
146 << layout.rect.width() << 'x' |
|
147 << layout.rect.height() << '\n'; |
|
148 |
|
149 qout << indent << "TopDockArea:\n"; |
|
150 dumpLayout(qout, layout.docks[QInternal::TopDock], indent + QLatin1String(" ")); |
|
151 qout << indent << "LeftDockArea:\n"; |
|
152 dumpLayout(qout, layout.docks[QInternal::LeftDock], indent + QLatin1String(" ")); |
|
153 qout << indent << "RightDockArea:\n"; |
|
154 dumpLayout(qout, layout.docks[QInternal::RightDock], indent + QLatin1String(" ")); |
|
155 qout << indent << "BottomDockArea:\n"; |
|
156 dumpLayout(qout, layout.docks[QInternal::BottomDock], indent + QLatin1String(" ")); |
|
157 |
|
158 qout.flush(); |
|
159 }; |
|
160 |
|
161 void qt_dumpLayout(QTextStream &qout, QMainWindow *window) |
|
162 { |
|
163 QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(window->layout()); |
|
164 dumpLayout(qout, layout->layoutState.dockAreaLayout, QString()); |
|
165 } |
|
166 |
|
167 #endif // Q_DEBUG_MAINWINDOW_LAYOUT && !QT_NO_DOCKWIDGET |
|
168 |
|
169 /****************************************************************************** |
|
170 ** QMainWindowLayoutState |
|
171 */ |
|
172 |
|
173 // we deal with all the #ifndefferry here so QMainWindowLayout code is clean |
|
174 |
|
175 QMainWindowLayoutState::QMainWindowLayoutState(QMainWindow *win) |
|
176 : |
|
177 #ifndef QT_NO_TOOLBAR |
|
178 toolBarAreaLayout(win), |
|
179 #endif |
|
180 #ifndef QT_NO_DOCKWIDGET |
|
181 dockAreaLayout(win) |
|
182 #else |
|
183 centralWidgetItem(0) |
|
184 #endif |
|
185 |
|
186 { |
|
187 mainWindow = win; |
|
188 } |
|
189 |
|
190 QSize QMainWindowLayoutState::sizeHint() const |
|
191 { |
|
192 |
|
193 QSize result(0, 0); |
|
194 |
|
195 #ifndef QT_NO_DOCKWIDGET |
|
196 result = dockAreaLayout.sizeHint(); |
|
197 #else |
|
198 if (centralWidgetItem != 0) |
|
199 result = centralWidgetItem->sizeHint(); |
|
200 #endif |
|
201 |
|
202 #ifndef QT_NO_TOOLBAR |
|
203 result = toolBarAreaLayout.sizeHint(result); |
|
204 #endif // QT_NO_TOOLBAR |
|
205 |
|
206 return result; |
|
207 } |
|
208 |
|
209 QSize QMainWindowLayoutState::minimumSize() const |
|
210 { |
|
211 QSize result(0, 0); |
|
212 |
|
213 #ifndef QT_NO_DOCKWIDGET |
|
214 result = dockAreaLayout.minimumSize(); |
|
215 #else |
|
216 if (centralWidgetItem != 0) |
|
217 result = centralWidgetItem->minimumSize(); |
|
218 #endif |
|
219 |
|
220 #ifndef QT_NO_TOOLBAR |
|
221 result = toolBarAreaLayout.minimumSize(result); |
|
222 #endif // QT_NO_TOOLBAR |
|
223 |
|
224 return result; |
|
225 } |
|
226 |
|
227 void QMainWindowLayoutState::apply(bool animated) |
|
228 { |
|
229 #ifndef QT_NO_TOOLBAR |
|
230 toolBarAreaLayout.apply(animated); |
|
231 #endif |
|
232 |
|
233 #ifndef QT_NO_DOCKWIDGET |
|
234 // dumpLayout(dockAreaLayout, QString()); |
|
235 dockAreaLayout.apply(animated); |
|
236 #else |
|
237 if (centralWidgetItem != 0) { |
|
238 QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(mainWindow->layout()); |
|
239 Q_ASSERT(layout != 0); |
|
240 layout->widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect, animated); |
|
241 } |
|
242 #endif |
|
243 } |
|
244 |
|
245 void QMainWindowLayoutState::fitLayout() |
|
246 { |
|
247 QRect r; |
|
248 #ifdef QT_NO_TOOLBAR |
|
249 r = rect; |
|
250 #else |
|
251 toolBarAreaLayout.rect = rect; |
|
252 r = toolBarAreaLayout.fitLayout(); |
|
253 #endif // QT_NO_TOOLBAR |
|
254 |
|
255 #ifndef QT_NO_DOCKWIDGET |
|
256 dockAreaLayout.rect = r; |
|
257 dockAreaLayout.fitLayout(); |
|
258 #else |
|
259 centralWidgetRect = r; |
|
260 #endif |
|
261 } |
|
262 |
|
263 void QMainWindowLayoutState::deleteAllLayoutItems() |
|
264 { |
|
265 #ifndef QT_NO_TOOLBAR |
|
266 toolBarAreaLayout.deleteAllLayoutItems(); |
|
267 #endif |
|
268 |
|
269 #ifndef QT_NO_DOCKWIDGET |
|
270 dockAreaLayout.deleteAllLayoutItems(); |
|
271 #endif |
|
272 } |
|
273 |
|
274 void QMainWindowLayoutState::deleteCentralWidgetItem() |
|
275 { |
|
276 #ifndef QT_NO_DOCKWIDGET |
|
277 delete dockAreaLayout.centralWidgetItem; |
|
278 dockAreaLayout.centralWidgetItem = 0; |
|
279 #else |
|
280 delete centralWidgetItem; |
|
281 centralWidgetItem = 0; |
|
282 #endif |
|
283 } |
|
284 |
|
285 QLayoutItem *QMainWindowLayoutState::itemAt(int index, int *x) const |
|
286 { |
|
287 #ifndef QT_NO_TOOLBAR |
|
288 if (QLayoutItem *ret = toolBarAreaLayout.itemAt(x, index)) |
|
289 return ret; |
|
290 #endif |
|
291 |
|
292 #ifndef QT_NO_DOCKWIDGET |
|
293 if (QLayoutItem *ret = dockAreaLayout.itemAt(x, index)) |
|
294 return ret; |
|
295 #else |
|
296 if (centralWidgetItem != 0 && (*x)++ == index) |
|
297 return centralWidgetItem; |
|
298 #endif |
|
299 |
|
300 return 0; |
|
301 } |
|
302 |
|
303 QLayoutItem *QMainWindowLayoutState::takeAt(int index, int *x) |
|
304 { |
|
305 #ifndef QT_NO_TOOLBAR |
|
306 if (QLayoutItem *ret = toolBarAreaLayout.takeAt(x, index)) |
|
307 return ret; |
|
308 #endif |
|
309 |
|
310 #ifndef QT_NO_DOCKWIDGET |
|
311 if (QLayoutItem *ret = dockAreaLayout.takeAt(x, index)) |
|
312 return ret; |
|
313 #else |
|
314 if (centralWidgetItem != 0 && (*x)++ == index) { |
|
315 QLayoutItem *ret = centralWidgetItem; |
|
316 centralWidgetItem = 0; |
|
317 return ret; |
|
318 } |
|
319 #endif |
|
320 |
|
321 return 0; |
|
322 } |
|
323 |
|
324 QList<int> QMainWindowLayoutState::indexOf(QWidget *widget) const |
|
325 { |
|
326 QList<int> result; |
|
327 |
|
328 #ifndef QT_NO_TOOLBAR |
|
329 // is it a toolbar? |
|
330 if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) { |
|
331 result = toolBarAreaLayout.indexOf(toolBar); |
|
332 if (!result.isEmpty()) |
|
333 result.prepend(0); |
|
334 return result; |
|
335 } |
|
336 #endif |
|
337 |
|
338 #ifndef QT_NO_DOCKWIDGET |
|
339 // is it a dock widget? |
|
340 if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(widget)) { |
|
341 result = dockAreaLayout.indexOf(dockWidget); |
|
342 if (!result.isEmpty()) |
|
343 result.prepend(1); |
|
344 return result; |
|
345 } |
|
346 #endif //QT_NO_DOCKWIDGET |
|
347 |
|
348 return result; |
|
349 } |
|
350 |
|
351 bool QMainWindowLayoutState::contains(QWidget *widget) const |
|
352 { |
|
353 #ifndef QT_NO_DOCKWIDGET |
|
354 if (dockAreaLayout.centralWidgetItem != 0 && dockAreaLayout.centralWidgetItem->widget() == widget) |
|
355 return true; |
|
356 if (!dockAreaLayout.indexOf(widget).isEmpty()) |
|
357 return true; |
|
358 #else |
|
359 if (centralWidgetItem != 0 && centralWidgetItem->widget() == widget) |
|
360 return true; |
|
361 #endif |
|
362 |
|
363 #ifndef QT_NO_TOOLBAR |
|
364 if (!toolBarAreaLayout.indexOf(widget).isEmpty()) |
|
365 return true; |
|
366 #endif |
|
367 return false; |
|
368 } |
|
369 |
|
370 void QMainWindowLayoutState::setCentralWidget(QWidget *widget) |
|
371 { |
|
372 QLayoutItem *item = 0; |
|
373 //make sure we remove the widget |
|
374 deleteCentralWidgetItem(); |
|
375 |
|
376 if (widget != 0) |
|
377 item = new QWidgetItemV2(widget); |
|
378 |
|
379 #ifndef QT_NO_DOCKWIDGET |
|
380 dockAreaLayout.centralWidgetItem = item; |
|
381 #else |
|
382 centralWidgetItem = item; |
|
383 #endif |
|
384 } |
|
385 |
|
386 QWidget *QMainWindowLayoutState::centralWidget() const |
|
387 { |
|
388 QLayoutItem *item = 0; |
|
389 |
|
390 #ifndef QT_NO_DOCKWIDGET |
|
391 item = dockAreaLayout.centralWidgetItem; |
|
392 #else |
|
393 item = centralWidgetItem; |
|
394 #endif |
|
395 |
|
396 if (item != 0) |
|
397 return item->widget(); |
|
398 return 0; |
|
399 } |
|
400 |
|
401 QList<int> QMainWindowLayoutState::gapIndex(QWidget *widget, |
|
402 const QPoint &pos) const |
|
403 { |
|
404 QList<int> result; |
|
405 |
|
406 #ifndef QT_NO_TOOLBAR |
|
407 // is it a toolbar? |
|
408 if (qobject_cast<QToolBar*>(widget) != 0) { |
|
409 result = toolBarAreaLayout.gapIndex(pos); |
|
410 if (!result.isEmpty()) |
|
411 result.prepend(0); |
|
412 return result; |
|
413 } |
|
414 #endif |
|
415 |
|
416 #ifndef QT_NO_DOCKWIDGET |
|
417 // is it a dock widget? |
|
418 if (qobject_cast<QDockWidget *>(widget) != 0) { |
|
419 result = dockAreaLayout.gapIndex(pos); |
|
420 if (!result.isEmpty()) |
|
421 result.prepend(1); |
|
422 return result; |
|
423 } |
|
424 #endif //QT_NO_DOCKWIDGET |
|
425 |
|
426 return result; |
|
427 } |
|
428 |
|
429 bool QMainWindowLayoutState::insertGap(const QList<int> &path, QLayoutItem *item) |
|
430 { |
|
431 if (path.isEmpty()) |
|
432 return false; |
|
433 |
|
434 int i = path.first(); |
|
435 |
|
436 #ifndef QT_NO_TOOLBAR |
|
437 if (i == 0) { |
|
438 Q_ASSERT(qobject_cast<QToolBar*>(item->widget()) != 0); |
|
439 return toolBarAreaLayout.insertGap(path.mid(1), item); |
|
440 } |
|
441 #endif |
|
442 |
|
443 #ifndef QT_NO_DOCKWIDGET |
|
444 if (i == 1) { |
|
445 Q_ASSERT(qobject_cast<QDockWidget*>(item->widget()) != 0); |
|
446 return dockAreaLayout.insertGap(path.mid(1), item); |
|
447 } |
|
448 #endif //QT_NO_DOCKWIDGET |
|
449 |
|
450 return false; |
|
451 } |
|
452 |
|
453 void QMainWindowLayoutState::remove(const QList<int> &path) |
|
454 { |
|
455 int i = path.first(); |
|
456 |
|
457 #ifndef QT_NO_TOOLBAR |
|
458 if (i == 0) |
|
459 toolBarAreaLayout.remove(path.mid(1)); |
|
460 #endif |
|
461 |
|
462 #ifndef QT_NO_DOCKWIDGET |
|
463 if (i == 1) |
|
464 dockAreaLayout.remove(path.mid(1)); |
|
465 #endif //QT_NO_DOCKWIDGET |
|
466 } |
|
467 |
|
468 void QMainWindowLayoutState::remove(QLayoutItem *item) |
|
469 { |
|
470 #ifndef QT_NO_TOOLBAR |
|
471 toolBarAreaLayout.remove(item); |
|
472 #endif |
|
473 |
|
474 #ifndef QT_NO_DOCKWIDGET |
|
475 // is it a dock widget? |
|
476 if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(item->widget())) { |
|
477 QList<int> path = dockAreaLayout.indexOf(dockWidget); |
|
478 if (!path.isEmpty()) |
|
479 dockAreaLayout.remove(path); |
|
480 } |
|
481 #endif //QT_NO_DOCKWIDGET |
|
482 } |
|
483 |
|
484 void QMainWindowLayoutState::clear() |
|
485 { |
|
486 #ifndef QT_NO_TOOLBAR |
|
487 toolBarAreaLayout.clear(); |
|
488 #endif |
|
489 |
|
490 #ifndef QT_NO_DOCKWIDGET |
|
491 dockAreaLayout.clear(); |
|
492 #else |
|
493 centralWidgetRect = QRect(); |
|
494 #endif |
|
495 |
|
496 rect = QRect(); |
|
497 } |
|
498 |
|
499 bool QMainWindowLayoutState::isValid() const |
|
500 { |
|
501 return rect.isValid(); |
|
502 } |
|
503 |
|
504 QLayoutItem *QMainWindowLayoutState::item(const QList<int> &path) |
|
505 { |
|
506 int i = path.first(); |
|
507 |
|
508 #ifndef QT_NO_TOOLBAR |
|
509 if (i == 0) |
|
510 return toolBarAreaLayout.item(path.mid(1)).widgetItem; |
|
511 #endif |
|
512 |
|
513 #ifndef QT_NO_DOCKWIDGET |
|
514 if (i == 1) |
|
515 return dockAreaLayout.item(path.mid(1)).widgetItem; |
|
516 #endif //QT_NO_DOCKWIDGET |
|
517 |
|
518 return 0; |
|
519 } |
|
520 |
|
521 QRect QMainWindowLayoutState::itemRect(const QList<int> &path) const |
|
522 { |
|
523 int i = path.first(); |
|
524 |
|
525 #ifndef QT_NO_TOOLBAR |
|
526 if (i == 0) |
|
527 return toolBarAreaLayout.itemRect(path.mid(1)); |
|
528 #endif |
|
529 |
|
530 #ifndef QT_NO_DOCKWIDGET |
|
531 if (i == 1) |
|
532 return dockAreaLayout.itemRect(path.mid(1)); |
|
533 #endif //QT_NO_DOCKWIDGET |
|
534 |
|
535 return QRect(); |
|
536 } |
|
537 |
|
538 QRect QMainWindowLayoutState::gapRect(const QList<int> &path) const |
|
539 { |
|
540 int i = path.first(); |
|
541 |
|
542 #ifndef QT_NO_TOOLBAR |
|
543 if (i == 0) |
|
544 return toolBarAreaLayout.itemRect(path.mid(1)); |
|
545 #endif |
|
546 |
|
547 #ifndef QT_NO_DOCKWIDGET |
|
548 if (i == 1) |
|
549 return dockAreaLayout.gapRect(path.mid(1)); |
|
550 #endif //QT_NO_DOCKWIDGET |
|
551 |
|
552 return QRect(); |
|
553 } |
|
554 |
|
555 QLayoutItem *QMainWindowLayoutState::plug(const QList<int> &path) |
|
556 { |
|
557 int i = path.first(); |
|
558 |
|
559 #ifndef QT_NO_TOOLBAR |
|
560 if (i == 0) |
|
561 return toolBarAreaLayout.plug(path.mid(1)); |
|
562 #endif |
|
563 |
|
564 #ifndef QT_NO_DOCKWIDGET |
|
565 if (i == 1) |
|
566 return dockAreaLayout.plug(path.mid(1)); |
|
567 #endif //QT_NO_DOCKWIDGET |
|
568 |
|
569 return 0; |
|
570 } |
|
571 |
|
572 QLayoutItem *QMainWindowLayoutState::unplug(const QList<int> &path, QMainWindowLayoutState *other) |
|
573 { |
|
574 int i = path.first(); |
|
575 |
|
576 #ifdef QT_NO_TOOLBAR |
|
577 Q_UNUSED(other); |
|
578 #else |
|
579 if (i == 0) |
|
580 return toolBarAreaLayout.unplug(path.mid(1), other ? &other->toolBarAreaLayout : 0); |
|
581 #endif |
|
582 |
|
583 #ifndef QT_NO_DOCKWIDGET |
|
584 if (i == 1) |
|
585 return dockAreaLayout.unplug(path.mid(1)); |
|
586 #endif //QT_NO_DOCKWIDGET |
|
587 |
|
588 return 0; |
|
589 } |
|
590 |
|
591 void QMainWindowLayoutState::saveState(QDataStream &stream) const |
|
592 { |
|
593 #ifndef QT_NO_DOCKWIDGET |
|
594 dockAreaLayout.saveState(stream); |
|
595 #endif |
|
596 #ifndef QT_NO_TOOLBAR |
|
597 toolBarAreaLayout.saveState(stream); |
|
598 #endif |
|
599 } |
|
600 |
|
601 template <typename T> |
|
602 static QList<T> findChildrenHelper(const QObject *o) |
|
603 { |
|
604 const QObjectList &list = o->children(); |
|
605 QList<T> result; |
|
606 |
|
607 for (int i=0; i < list.size(); ++i) { |
|
608 if (T t = qobject_cast<T>(list[i])) { |
|
609 result.append(t); |
|
610 } |
|
611 } |
|
612 |
|
613 return result; |
|
614 } |
|
615 |
|
616 //pre4.3 tests the format that was used before 4.3 |
|
617 bool QMainWindowLayoutState::checkFormat(QDataStream &stream, bool pre43) |
|
618 { |
|
619 #ifdef QT_NO_TOOLBAR |
|
620 Q_UNUSED(pre43); |
|
621 #endif |
|
622 while (!stream.atEnd()) { |
|
623 uchar marker; |
|
624 stream >> marker; |
|
625 switch(marker) |
|
626 { |
|
627 #ifndef QT_NO_TOOLBAR |
|
628 case QToolBarAreaLayout::ToolBarStateMarker: |
|
629 case QToolBarAreaLayout::ToolBarStateMarkerEx: |
|
630 { |
|
631 QList<QToolBar *> toolBars = findChildrenHelper<QToolBar*>(mainWindow); |
|
632 if (!toolBarAreaLayout.restoreState(stream, toolBars, marker, |
|
633 pre43 /*testing 4.3 format*/, true /*testing*/)) { |
|
634 return false; |
|
635 } |
|
636 } |
|
637 break; |
|
638 #endif // QT_NO_TOOLBAR |
|
639 |
|
640 #ifndef QT_NO_DOCKWIDGET |
|
641 case QDockAreaLayout::DockWidgetStateMarker: |
|
642 { |
|
643 QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow); |
|
644 if (!dockAreaLayout.restoreState(stream, dockWidgets, true /*testing*/)) { |
|
645 return false; |
|
646 } |
|
647 } |
|
648 break; |
|
649 #endif |
|
650 default: |
|
651 //there was an error during the parsing |
|
652 return false; |
|
653 }// switch |
|
654 } //while |
|
655 |
|
656 //everything went fine: it must be a pre-4.3 saved state |
|
657 return true; |
|
658 } |
|
659 |
|
660 bool QMainWindowLayoutState::restoreState(QDataStream &_stream, |
|
661 const QMainWindowLayoutState &oldState) |
|
662 { |
|
663 //make a copy of the data so that we can read it more than once |
|
664 QByteArray copy; |
|
665 while(!_stream.atEnd()) { |
|
666 int length = 1024; |
|
667 QByteArray ba(length, '\0'); |
|
668 length = _stream.readRawData(ba.data(), ba.size()); |
|
669 ba.resize(length); |
|
670 copy += ba; |
|
671 } |
|
672 |
|
673 QDataStream ds(copy); |
|
674 const bool oldFormat = !checkFormat(ds, false); |
|
675 if (oldFormat) { |
|
676 //we should try with the old format |
|
677 QDataStream ds2(copy); |
|
678 if (!checkFormat(ds2, true)) { |
|
679 return false; //format unknown |
|
680 } |
|
681 } |
|
682 |
|
683 QDataStream stream(copy); |
|
684 |
|
685 while (!stream.atEnd()) { |
|
686 uchar marker; |
|
687 stream >> marker; |
|
688 switch(marker) |
|
689 { |
|
690 #ifndef QT_NO_DOCKWIDGET |
|
691 case QDockAreaLayout::DockWidgetStateMarker: |
|
692 { |
|
693 QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow); |
|
694 if (!dockAreaLayout.restoreState(stream, dockWidgets)) |
|
695 return false; |
|
696 |
|
697 for (int i = 0; i < dockWidgets.size(); ++i) { |
|
698 QDockWidget *w = dockWidgets.at(i); |
|
699 QList<int> path = dockAreaLayout.indexOf(w); |
|
700 if (path.isEmpty()) { |
|
701 QList<int> oldPath = oldState.dockAreaLayout.indexOf(w); |
|
702 if (oldPath.isEmpty()) { |
|
703 continue; |
|
704 } |
|
705 QDockAreaLayoutInfo *info = dockAreaLayout.info(oldPath); |
|
706 if (info == 0) { |
|
707 continue; |
|
708 } |
|
709 info->item_list.append(QDockAreaLayoutItem(new QDockWidgetItem(w))); |
|
710 } |
|
711 } |
|
712 } |
|
713 break; |
|
714 #endif // QT_NO_DOCKWIDGET |
|
715 |
|
716 #ifndef QT_NO_TOOLBAR |
|
717 case QToolBarAreaLayout::ToolBarStateMarker: |
|
718 case QToolBarAreaLayout::ToolBarStateMarkerEx: |
|
719 { |
|
720 QList<QToolBar *> toolBars = findChildrenHelper<QToolBar*>(mainWindow); |
|
721 if (!toolBarAreaLayout.restoreState(stream, toolBars, marker, oldFormat)) |
|
722 return false; |
|
723 |
|
724 for (int i = 0; i < toolBars.size(); ++i) { |
|
725 QToolBar *w = toolBars.at(i); |
|
726 QList<int> path = toolBarAreaLayout.indexOf(w); |
|
727 if (path.isEmpty()) { |
|
728 QList<int> oldPath = oldState.toolBarAreaLayout.indexOf(w); |
|
729 if (oldPath.isEmpty()) { |
|
730 continue; |
|
731 } |
|
732 toolBarAreaLayout.docks[oldPath.at(0)].insertToolBar(0, w); |
|
733 } |
|
734 } |
|
735 } |
|
736 break; |
|
737 #endif //QT_NO_TOOLBAR |
|
738 default: |
|
739 return false; |
|
740 }// switch |
|
741 } //while |
|
742 |
|
743 |
|
744 return true; |
|
745 } |
|
746 |
|
747 /****************************************************************************** |
|
748 ** QMainWindowLayoutState - toolbars |
|
749 */ |
|
750 |
|
751 #ifndef QT_NO_TOOLBAR |
|
752 |
|
753 static inline void validateToolBarArea(Qt::ToolBarArea &area) |
|
754 { |
|
755 switch (area) { |
|
756 case Qt::LeftToolBarArea: |
|
757 case Qt::RightToolBarArea: |
|
758 case Qt::TopToolBarArea: |
|
759 case Qt::BottomToolBarArea: |
|
760 break; |
|
761 default: |
|
762 area = Qt::TopToolBarArea; |
|
763 } |
|
764 } |
|
765 |
|
766 static QInternal::DockPosition toDockPos(Qt::ToolBarArea area) |
|
767 { |
|
768 switch (area) { |
|
769 case Qt::LeftToolBarArea: return QInternal::LeftDock; |
|
770 case Qt::RightToolBarArea: return QInternal::RightDock; |
|
771 case Qt::TopToolBarArea: return QInternal::TopDock; |
|
772 case Qt::BottomToolBarArea: return QInternal::BottomDock; |
|
773 default: |
|
774 break; |
|
775 } |
|
776 |
|
777 return QInternal::DockCount; |
|
778 } |
|
779 |
|
780 static Qt::ToolBarArea toToolBarArea(QInternal::DockPosition pos) |
|
781 { |
|
782 switch (pos) { |
|
783 case QInternal::LeftDock: return Qt::LeftToolBarArea; |
|
784 case QInternal::RightDock: return Qt::RightToolBarArea; |
|
785 case QInternal::TopDock: return Qt::TopToolBarArea; |
|
786 case QInternal::BottomDock: return Qt::BottomToolBarArea; |
|
787 default: break; |
|
788 } |
|
789 return Qt::NoToolBarArea; |
|
790 } |
|
791 |
|
792 static inline Qt::ToolBarArea toToolBarArea(int pos) |
|
793 { |
|
794 return toToolBarArea(static_cast<QInternal::DockPosition>(pos)); |
|
795 } |
|
796 |
|
797 void QMainWindowLayout::addToolBarBreak(Qt::ToolBarArea area) |
|
798 { |
|
799 validateToolBarArea(area); |
|
800 |
|
801 layoutState.toolBarAreaLayout.addToolBarBreak(toDockPos(area)); |
|
802 if (savedState.isValid()) |
|
803 savedState.toolBarAreaLayout.addToolBarBreak(toDockPos(area)); |
|
804 |
|
805 invalidate(); |
|
806 } |
|
807 |
|
808 void QMainWindowLayout::insertToolBarBreak(QToolBar *before) |
|
809 { |
|
810 layoutState.toolBarAreaLayout.insertToolBarBreak(before); |
|
811 if (savedState.isValid()) |
|
812 savedState.toolBarAreaLayout.insertToolBarBreak(before); |
|
813 invalidate(); |
|
814 } |
|
815 |
|
816 void QMainWindowLayout::removeToolBarBreak(QToolBar *before) |
|
817 { |
|
818 layoutState.toolBarAreaLayout.removeToolBarBreak(before); |
|
819 if (savedState.isValid()) |
|
820 savedState.toolBarAreaLayout.removeToolBarBreak(before); |
|
821 invalidate(); |
|
822 } |
|
823 |
|
824 void QMainWindowLayout::moveToolBar(QToolBar *toolbar, int pos) |
|
825 { |
|
826 layoutState.toolBarAreaLayout.moveToolBar(toolbar, pos); |
|
827 if (savedState.isValid()) |
|
828 savedState.toolBarAreaLayout.moveToolBar(toolbar, pos); |
|
829 invalidate(); |
|
830 } |
|
831 |
|
832 /* Removes the toolbar from the mainwindow so that it can be added again. Does not |
|
833 explicitly hide the toolbar. */ |
|
834 void QMainWindowLayout::removeToolBar(QToolBar *toolbar) |
|
835 { |
|
836 if (toolbar) { |
|
837 QObject::disconnect(parentWidget(), SIGNAL(iconSizeChanged(QSize)), |
|
838 toolbar, SLOT(_q_updateIconSize(QSize))); |
|
839 QObject::disconnect(parentWidget(), SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)), |
|
840 toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle))); |
|
841 |
|
842 #ifdef Q_WS_MAC |
|
843 if (usesHIToolBar(toolbar)) { |
|
844 removeFromMacToolbar(toolbar); |
|
845 } else |
|
846 #endif // Q_WS_MAC |
|
847 { |
|
848 removeWidget(toolbar); |
|
849 } |
|
850 } |
|
851 } |
|
852 |
|
853 /*! |
|
854 Adds \a toolbar to \a area, continuing the current line. |
|
855 */ |
|
856 void QMainWindowLayout::addToolBar(Qt::ToolBarArea area, |
|
857 QToolBar *toolbar, |
|
858 bool) |
|
859 { |
|
860 validateToolBarArea(area); |
|
861 #ifdef Q_WS_MAC |
|
862 if ((area == Qt::TopToolBarArea) |
|
863 && layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) { |
|
864 insertIntoMacToolbar(0, toolbar); |
|
865 } else |
|
866 #endif |
|
867 { |
|
868 //let's add the toolbar to the layout |
|
869 addChildWidget(toolbar); |
|
870 QLayoutItem * item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar); |
|
871 if (savedState.isValid() && item) { |
|
872 // copy the toolbar also in the saved state |
|
873 savedState.toolBarAreaLayout.insertItem(toDockPos(area), item); |
|
874 } |
|
875 invalidate(); |
|
876 |
|
877 //this ensures that the toolbar has the right window flags (not floating any more) |
|
878 toolbar->d_func()->updateWindowFlags(false /*floating*/); |
|
879 } |
|
880 } |
|
881 |
|
882 /*! |
|
883 Adds \a toolbar before \a before |
|
884 */ |
|
885 void QMainWindowLayout::insertToolBar(QToolBar *before, QToolBar *toolbar) |
|
886 { |
|
887 #ifdef Q_WS_MAC |
|
888 if (usesHIToolBar(before)) { |
|
889 insertIntoMacToolbar(before, toolbar); |
|
890 } else |
|
891 #endif // Q_WS_MAC |
|
892 { |
|
893 addChildWidget(toolbar); |
|
894 QLayoutItem * item = layoutState.toolBarAreaLayout.insertToolBar(before, toolbar); |
|
895 if (savedState.isValid() && item) { |
|
896 // copy the toolbar also in the saved state |
|
897 savedState.toolBarAreaLayout.insertItem(before, item); |
|
898 } |
|
899 if (!currentGapPos.isEmpty() && currentGapPos.first() == 0) { |
|
900 currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex(); |
|
901 if (!currentGapPos.isEmpty()) { |
|
902 currentGapPos.prepend(0); |
|
903 currentGapRect = layoutState.itemRect(currentGapPos); |
|
904 } |
|
905 } |
|
906 invalidate(); |
|
907 } |
|
908 } |
|
909 |
|
910 Qt::ToolBarArea QMainWindowLayout::toolBarArea(QToolBar *toolbar) const |
|
911 { |
|
912 QInternal::DockPosition pos = layoutState.toolBarAreaLayout.findToolBar(toolbar); |
|
913 switch (pos) { |
|
914 case QInternal::LeftDock: return Qt::LeftToolBarArea; |
|
915 case QInternal::RightDock: return Qt::RightToolBarArea; |
|
916 case QInternal::TopDock: return Qt::TopToolBarArea; |
|
917 case QInternal::BottomDock: return Qt::BottomToolBarArea; |
|
918 default: break; |
|
919 } |
|
920 #ifdef Q_WS_MAC |
|
921 if (pos == QInternal::DockCount) { |
|
922 if (qtoolbarsInUnifiedToolbarList.contains(toolbar)) |
|
923 return Qt::TopToolBarArea; |
|
924 } |
|
925 #endif |
|
926 return Qt::NoToolBarArea; |
|
927 } |
|
928 |
|
929 bool QMainWindowLayout::toolBarBreak(QToolBar *toolBar) const |
|
930 { |
|
931 return layoutState.toolBarAreaLayout.toolBarBreak(toolBar); |
|
932 } |
|
933 |
|
934 void QMainWindowLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar) const |
|
935 { |
|
936 option->toolBarArea = toolBarArea(toolBar); |
|
937 layoutState.toolBarAreaLayout.getStyleOptionInfo(option, toolBar); |
|
938 } |
|
939 |
|
940 void QMainWindowLayout::toggleToolBarsVisible() |
|
941 { |
|
942 bool updateNonUnifiedParts = true; |
|
943 #ifdef Q_WS_MAC |
|
944 if (layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) { |
|
945 // If we hit this case, someone has pressed the "toolbar button" which will |
|
946 // toggle the unified toolbar visiblity, because that's what the user wants. |
|
947 // We might be in a situation where someone has hidden all the toolbars |
|
948 // beforehand (maybe in construction), but now they've hit this button and |
|
949 // and are expecting the items to show. What do we do? |
|
950 // 1) Check the visibility of all the toolbars, if one is visible, do nothing, this |
|
951 // preserves what people would expect (these toolbars were visible when I clicked last time). |
|
952 // 2) If NONE are visible, then show them all. Again, this preserves the user expectation |
|
953 // of, "I want to see the toolbars." The user may get more toolbars than expected, but this |
|
954 // is better seeing nothing. |
|
955 // Don't worry about any of this if we are going invisible. This does mean we may get |
|
956 // into issues when switching into and out of fullscreen mode, but this is probably minor. |
|
957 // If we ever need to do hiding, that would have to be taken care of after the unified toolbar |
|
958 // has finished hiding. |
|
959 // People can of course handle the QEvent::ToolBarChange event themselves and do |
|
960 // WHATEVER they want if they don't like what we are doing (though the unified toolbar |
|
961 // will fire regardless). |
|
962 |
|
963 // Check if we REALLY need to update the geometry below. If we only have items in the |
|
964 // unified toolbar, all the docks will be empty, so there's very little point |
|
965 // in doing the geometry as Apple will do it (we also avoid flicker in Cocoa as well). |
|
966 // FWIW, layoutState.toolBarAreaLayout.visible and the state of the unified toolbar |
|
967 // visibility can get out of sync. I really don't think it's a big issue. It is kept |
|
968 // to a minimum because we only change the visibility if we absolutely must. |
|
969 // update the "non unified parts." |
|
970 updateNonUnifiedParts = !layoutState.toolBarAreaLayout.isEmpty(); |
|
971 |
|
972 // We get this function before the unified toolbar does its thing. |
|
973 // So, the value will be opposite of what we expect. |
|
974 bool goingVisible = !macWindowToolbarIsVisible(qt_mac_window_for(layoutState.mainWindow)); |
|
975 if (goingVisible) { |
|
976 const int ToolBarCount = qtoolbarsInUnifiedToolbarList.size(); |
|
977 bool needAllVisible = true; |
|
978 for (int i = 0; i < ToolBarCount; ++i) { |
|
979 if (!qtoolbarsInUnifiedToolbarList.at(i)->isHidden()) { |
|
980 needAllVisible = false; |
|
981 break; |
|
982 } |
|
983 } |
|
984 if (needAllVisible) { |
|
985 QBoolBlocker blocker(blockVisiblityCheck); // Disable the visibilty check because |
|
986 // the toggle has already happened. |
|
987 for (int i = 0; i < ToolBarCount; ++i) |
|
988 qtoolbarsInUnifiedToolbarList.at(i)->setVisible(true); |
|
989 } |
|
990 } |
|
991 if (!updateNonUnifiedParts) |
|
992 layoutState.toolBarAreaLayout.visible = goingVisible; |
|
993 } |
|
994 #endif |
|
995 if (updateNonUnifiedParts) { |
|
996 layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible; |
|
997 if (!layoutState.mainWindow->isMaximized()) { |
|
998 QPoint topLeft = parentWidget()->geometry().topLeft(); |
|
999 QRect r = parentWidget()->geometry(); |
|
1000 r = layoutState.toolBarAreaLayout.rectHint(r); |
|
1001 r.moveTo(topLeft); |
|
1002 parentWidget()->setGeometry(r); |
|
1003 } else { |
|
1004 update(); |
|
1005 } |
|
1006 } |
|
1007 } |
|
1008 |
|
1009 #endif // QT_NO_TOOLBAR |
|
1010 |
|
1011 /****************************************************************************** |
|
1012 ** QMainWindowLayoutState - dock areas |
|
1013 */ |
|
1014 |
|
1015 #ifndef QT_NO_DOCKWIDGET |
|
1016 |
|
1017 static inline void validateDockWidgetArea(Qt::DockWidgetArea &area) |
|
1018 { |
|
1019 switch (area) { |
|
1020 case Qt::LeftDockWidgetArea: |
|
1021 case Qt::RightDockWidgetArea: |
|
1022 case Qt::TopDockWidgetArea: |
|
1023 case Qt::BottomDockWidgetArea: |
|
1024 break; |
|
1025 default: |
|
1026 area = Qt::LeftDockWidgetArea; |
|
1027 } |
|
1028 } |
|
1029 |
|
1030 static QInternal::DockPosition toDockPos(Qt::DockWidgetArea area) |
|
1031 { |
|
1032 switch (area) { |
|
1033 case Qt::LeftDockWidgetArea: return QInternal::LeftDock; |
|
1034 case Qt::RightDockWidgetArea: return QInternal::RightDock; |
|
1035 case Qt::TopDockWidgetArea: return QInternal::TopDock; |
|
1036 case Qt::BottomDockWidgetArea: return QInternal::BottomDock; |
|
1037 default: |
|
1038 break; |
|
1039 } |
|
1040 |
|
1041 return QInternal::DockCount; |
|
1042 } |
|
1043 |
|
1044 static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos) |
|
1045 { |
|
1046 switch (pos) { |
|
1047 case QInternal::LeftDock : return Qt::LeftDockWidgetArea; |
|
1048 case QInternal::RightDock : return Qt::RightDockWidgetArea; |
|
1049 case QInternal::TopDock : return Qt::TopDockWidgetArea; |
|
1050 case QInternal::BottomDock : return Qt::BottomDockWidgetArea; |
|
1051 default: |
|
1052 break; |
|
1053 } |
|
1054 |
|
1055 return Qt::NoDockWidgetArea; |
|
1056 } |
|
1057 |
|
1058 inline static Qt::DockWidgetArea toDockWidgetArea(int pos) |
|
1059 { |
|
1060 return toDockWidgetArea(static_cast<QInternal::DockPosition>(pos)); |
|
1061 } |
|
1062 |
|
1063 void QMainWindowLayout::setCorner(Qt::Corner corner, Qt::DockWidgetArea area) |
|
1064 { |
|
1065 if (layoutState.dockAreaLayout.corners[corner] == area) |
|
1066 return; |
|
1067 layoutState.dockAreaLayout.corners[corner] = area; |
|
1068 if (savedState.isValid()) |
|
1069 savedState.dockAreaLayout.corners[corner] = area; |
|
1070 invalidate(); |
|
1071 } |
|
1072 |
|
1073 Qt::DockWidgetArea QMainWindowLayout::corner(Qt::Corner corner) const |
|
1074 { |
|
1075 return layoutState.dockAreaLayout.corners[corner]; |
|
1076 } |
|
1077 |
|
1078 void QMainWindowLayout::addDockWidget(Qt::DockWidgetArea area, |
|
1079 QDockWidget *dockwidget, |
|
1080 Qt::Orientation orientation) |
|
1081 { |
|
1082 addChildWidget(dockwidget); |
|
1083 |
|
1084 // If we are currently moving a separator, then we need to abort the move, since each |
|
1085 // time we move the mouse layoutState is replaced by savedState modified by the move. |
|
1086 if (!movingSeparator.isEmpty()) |
|
1087 endSeparatorMove(movingSeparatorPos); |
|
1088 |
|
1089 layoutState.dockAreaLayout.addDockWidget(toDockPos(area), dockwidget, orientation); |
|
1090 emit dockwidget->dockLocationChanged(area); |
|
1091 invalidate(); |
|
1092 } |
|
1093 |
|
1094 void QMainWindowLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second) |
|
1095 { |
|
1096 addChildWidget(second); |
|
1097 layoutState.dockAreaLayout.tabifyDockWidget(first, second); |
|
1098 emit second->dockLocationChanged(dockWidgetArea(first)); |
|
1099 invalidate(); |
|
1100 } |
|
1101 |
|
1102 bool QMainWindowLayout::restoreDockWidget(QDockWidget *dockwidget) |
|
1103 { |
|
1104 addChildWidget(dockwidget); |
|
1105 if (!layoutState.dockAreaLayout.restoreDockWidget(dockwidget)) |
|
1106 return false; |
|
1107 emit dockwidget->dockLocationChanged(dockWidgetArea(dockwidget)); |
|
1108 invalidate(); |
|
1109 return true; |
|
1110 } |
|
1111 |
|
1112 #ifndef QT_NO_TABBAR |
|
1113 bool QMainWindowLayout::documentMode() const |
|
1114 { |
|
1115 return _documentMode; |
|
1116 } |
|
1117 |
|
1118 void QMainWindowLayout::setDocumentMode(bool enabled) |
|
1119 { |
|
1120 if (_documentMode == enabled) |
|
1121 return; |
|
1122 |
|
1123 _documentMode = enabled; |
|
1124 |
|
1125 // Update the document mode for all tab bars |
|
1126 foreach (QTabBar *bar, usedTabBars) |
|
1127 bar->setDocumentMode(_documentMode); |
|
1128 foreach (QTabBar *bar, unusedTabBars) |
|
1129 bar->setDocumentMode(_documentMode); |
|
1130 } |
|
1131 #endif // QT_NO_TABBAR |
|
1132 |
|
1133 void QMainWindowLayout::setVerticalTabsEnabled(bool enabled) |
|
1134 { |
|
1135 #ifdef QT_NO_TABBAR |
|
1136 Q_UNUSED(enabled); |
|
1137 #else |
|
1138 if (verticalTabsEnabled == enabled) |
|
1139 return; |
|
1140 |
|
1141 verticalTabsEnabled = enabled; |
|
1142 |
|
1143 updateTabBarShapes(); |
|
1144 #endif // QT_NO_TABBAR |
|
1145 } |
|
1146 |
|
1147 #ifndef QT_NO_TABWIDGET |
|
1148 QTabWidget::TabShape QMainWindowLayout::tabShape() const |
|
1149 { |
|
1150 return _tabShape; |
|
1151 } |
|
1152 |
|
1153 void QMainWindowLayout::setTabShape(QTabWidget::TabShape tabShape) |
|
1154 { |
|
1155 if (_tabShape == tabShape) |
|
1156 return; |
|
1157 |
|
1158 _tabShape = tabShape; |
|
1159 |
|
1160 updateTabBarShapes(); |
|
1161 } |
|
1162 |
|
1163 QTabWidget::TabPosition QMainWindowLayout::tabPosition(Qt::DockWidgetArea area) const |
|
1164 { |
|
1165 return tabPositions[toDockPos(area)]; |
|
1166 } |
|
1167 |
|
1168 void QMainWindowLayout::setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition) |
|
1169 { |
|
1170 const Qt::DockWidgetArea dockWidgetAreas[] = { |
|
1171 Qt::TopDockWidgetArea, |
|
1172 Qt::LeftDockWidgetArea, |
|
1173 Qt::BottomDockWidgetArea, |
|
1174 Qt::RightDockWidgetArea |
|
1175 }; |
|
1176 const QInternal::DockPosition dockPositions[] = { |
|
1177 QInternal::TopDock, |
|
1178 QInternal::LeftDock, |
|
1179 QInternal::BottomDock, |
|
1180 QInternal::RightDock |
|
1181 }; |
|
1182 |
|
1183 for (int i = 0; i < QInternal::DockCount; ++i) |
|
1184 if (areas & dockWidgetAreas[i]) |
|
1185 tabPositions[dockPositions[i]] = tabPosition; |
|
1186 |
|
1187 updateTabBarShapes(); |
|
1188 } |
|
1189 |
|
1190 static inline QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position) |
|
1191 { |
|
1192 const bool rounded = (shape == QTabWidget::Rounded); |
|
1193 if (position == QTabWidget::North) |
|
1194 return rounded ? QTabBar::RoundedNorth : QTabBar::TriangularNorth; |
|
1195 if (position == QTabWidget::South) |
|
1196 return rounded ? QTabBar::RoundedSouth : QTabBar::TriangularSouth; |
|
1197 if (position == QTabWidget::East) |
|
1198 return rounded ? QTabBar::RoundedEast : QTabBar::TriangularEast; |
|
1199 if (position == QTabWidget::West) |
|
1200 return rounded ? QTabBar::RoundedWest : QTabBar::TriangularWest; |
|
1201 return QTabBar::RoundedNorth; |
|
1202 } |
|
1203 #endif // QT_NO_TABWIDGET |
|
1204 |
|
1205 #ifndef QT_NO_TABBAR |
|
1206 void QMainWindowLayout::updateTabBarShapes() |
|
1207 { |
|
1208 #ifndef QT_NO_TABWIDGET |
|
1209 const QTabWidget::TabPosition vertical[] = { |
|
1210 QTabWidget::West, |
|
1211 QTabWidget::East, |
|
1212 QTabWidget::North, |
|
1213 QTabWidget::South |
|
1214 }; |
|
1215 #else |
|
1216 const QTabBar::Shape vertical[] = { |
|
1217 QTabBar::RoundedWest, |
|
1218 QTabBar::RoundedEast, |
|
1219 QTabBar::RoundedNorth, |
|
1220 QTabBar::RoundedSouth |
|
1221 }; |
|
1222 #endif |
|
1223 |
|
1224 QDockAreaLayout &layout = layoutState.dockAreaLayout; |
|
1225 |
|
1226 for (int i = 0; i < QInternal::DockCount; ++i) { |
|
1227 #ifndef QT_NO_TABWIDGET |
|
1228 QTabWidget::TabPosition pos = verticalTabsEnabled ? vertical[i] : tabPositions[i]; |
|
1229 QTabBar::Shape shape = tabBarShapeFrom(_tabShape, pos); |
|
1230 #else |
|
1231 QTabBar::Shape shape = verticalTabsEnabled ? vertical[i] : QTabBar::RoundedSouth; |
|
1232 #endif |
|
1233 layout.docks[i].setTabBarShape(shape); |
|
1234 } |
|
1235 } |
|
1236 #endif // QT_NO_TABBAR |
|
1237 |
|
1238 void QMainWindowLayout::splitDockWidget(QDockWidget *after, |
|
1239 QDockWidget *dockwidget, |
|
1240 Qt::Orientation orientation) |
|
1241 { |
|
1242 addChildWidget(dockwidget); |
|
1243 layoutState.dockAreaLayout.splitDockWidget(after, dockwidget, orientation); |
|
1244 emit dockwidget->dockLocationChanged(dockWidgetArea(after)); |
|
1245 invalidate(); |
|
1246 } |
|
1247 |
|
1248 Qt::DockWidgetArea QMainWindowLayout::dockWidgetArea(QDockWidget *widget) const |
|
1249 { |
|
1250 QList<int> pathToWidget = layoutState.dockAreaLayout.indexOf(widget); |
|
1251 if (pathToWidget.isEmpty()) |
|
1252 return Qt::NoDockWidgetArea; |
|
1253 return toDockWidgetArea(pathToWidget.first()); |
|
1254 } |
|
1255 |
|
1256 void QMainWindowLayout::keepSize(QDockWidget *w) |
|
1257 { |
|
1258 layoutState.dockAreaLayout.keepSize(w); |
|
1259 } |
|
1260 |
|
1261 #ifndef QT_NO_TABBAR |
|
1262 |
|
1263 class QMainWindowTabBar : public QTabBar |
|
1264 { |
|
1265 public: |
|
1266 QMainWindowTabBar(QWidget *parent); |
|
1267 protected: |
|
1268 bool event(QEvent *e); |
|
1269 }; |
|
1270 |
|
1271 QMainWindowTabBar::QMainWindowTabBar(QWidget *parent) |
|
1272 : QTabBar(parent) |
|
1273 { |
|
1274 setExpanding(false); |
|
1275 } |
|
1276 |
|
1277 bool QMainWindowTabBar::event(QEvent *e) |
|
1278 { |
|
1279 // show the tooltip if tab is too small to fit label |
|
1280 |
|
1281 if (e->type() != QEvent::ToolTip) |
|
1282 return QTabBar::event(e); |
|
1283 QSize size = this->size(); |
|
1284 QSize hint = sizeHint(); |
|
1285 if (shape() == QTabBar::RoundedWest || shape() == QTabBar::RoundedEast) { |
|
1286 size.transpose(); |
|
1287 hint.transpose(); |
|
1288 } |
|
1289 if (size.width() < hint.width()) |
|
1290 return QTabBar::event(e); |
|
1291 e->accept(); |
|
1292 return true; |
|
1293 } |
|
1294 |
|
1295 QTabBar *QMainWindowLayout::getTabBar() |
|
1296 { |
|
1297 QTabBar *result = 0; |
|
1298 if (!unusedTabBars.isEmpty()) { |
|
1299 result = unusedTabBars.takeLast(); |
|
1300 } else { |
|
1301 result = new QMainWindowTabBar(parentWidget()); |
|
1302 result->setDrawBase(true); |
|
1303 result->setElideMode(Qt::ElideRight); |
|
1304 result->setDocumentMode(_documentMode); |
|
1305 connect(result, SIGNAL(currentChanged(int)), this, SLOT(tabChanged())); |
|
1306 } |
|
1307 |
|
1308 usedTabBars.insert(result); |
|
1309 return result; |
|
1310 } |
|
1311 |
|
1312 // Allocates a new separator widget if needed |
|
1313 QWidget *QMainWindowLayout::getSeparatorWidget() |
|
1314 { |
|
1315 QWidget *result = 0; |
|
1316 if (!unusedSeparatorWidgets.isEmpty()) { |
|
1317 result = unusedSeparatorWidgets.takeLast(); |
|
1318 } else { |
|
1319 result = new QWidget(parentWidget()); |
|
1320 result->setAttribute(Qt::WA_MouseNoMask, true); |
|
1321 result->setAutoFillBackground(false); |
|
1322 result->setObjectName(QLatin1String("qt_qmainwindow_extended_splitter")); |
|
1323 } |
|
1324 usedSeparatorWidgets.insert(result); |
|
1325 return result; |
|
1326 } |
|
1327 |
|
1328 void QMainWindowLayout::tabChanged() |
|
1329 { |
|
1330 QTabBar *tb = qobject_cast<QTabBar*>(sender()); |
|
1331 if (tb == 0) |
|
1332 return; |
|
1333 QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(tb); |
|
1334 if (info == 0) |
|
1335 return; |
|
1336 info->apply(false); |
|
1337 |
|
1338 if (QWidget *w = centralWidget()) |
|
1339 w->raise(); |
|
1340 } |
|
1341 #endif // QT_NO_TABBAR |
|
1342 |
|
1343 bool QMainWindowLayout::startSeparatorMove(const QPoint &pos) |
|
1344 { |
|
1345 movingSeparator = layoutState.dockAreaLayout.findSeparator(pos); |
|
1346 |
|
1347 if (movingSeparator.isEmpty()) |
|
1348 return false; |
|
1349 |
|
1350 savedState = layoutState; |
|
1351 movingSeparatorPos = movingSeparatorOrigin = pos; |
|
1352 |
|
1353 return true; |
|
1354 } |
|
1355 |
|
1356 bool QMainWindowLayout::separatorMove(const QPoint &pos) |
|
1357 { |
|
1358 if (movingSeparator.isEmpty()) |
|
1359 return false; |
|
1360 movingSeparatorPos = pos; |
|
1361 separatorMoveTimer.start(0, this); |
|
1362 return true; |
|
1363 } |
|
1364 |
|
1365 bool QMainWindowLayout::endSeparatorMove(const QPoint&) |
|
1366 { |
|
1367 bool result = !movingSeparator.isEmpty(); |
|
1368 movingSeparator.clear(); |
|
1369 savedState.clear(); |
|
1370 return result; |
|
1371 } |
|
1372 |
|
1373 void QMainWindowLayout::raise(QDockWidget *widget) |
|
1374 { |
|
1375 QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget); |
|
1376 if (info == 0) |
|
1377 return; |
|
1378 #ifndef QT_NO_TABBAR |
|
1379 if (!info->tabbed) |
|
1380 return; |
|
1381 info->setCurrentTab(widget); |
|
1382 #endif |
|
1383 } |
|
1384 |
|
1385 #endif // QT_NO_DOCKWIDGET |
|
1386 |
|
1387 |
|
1388 /****************************************************************************** |
|
1389 ** QMainWindowLayoutState - layout interface |
|
1390 */ |
|
1391 |
|
1392 int QMainWindowLayout::count() const |
|
1393 { |
|
1394 qWarning("QMainWindowLayout::count: ?"); |
|
1395 return 0; //################################################# |
|
1396 } |
|
1397 |
|
1398 QLayoutItem *QMainWindowLayout::itemAt(int index) const |
|
1399 { |
|
1400 int x = 0; |
|
1401 |
|
1402 if (QLayoutItem *ret = layoutState.itemAt(index, &x)) |
|
1403 return ret; |
|
1404 |
|
1405 if (statusbar && x++ == index) |
|
1406 return statusbar; |
|
1407 |
|
1408 return 0; |
|
1409 } |
|
1410 |
|
1411 QLayoutItem *QMainWindowLayout::takeAt(int index) |
|
1412 { |
|
1413 int x = 0; |
|
1414 |
|
1415 if (QLayoutItem *ret = layoutState.takeAt(index, &x)) { |
|
1416 // the widget might in fact have been destroyed by now |
|
1417 if (QWidget *w = ret->widget()) { |
|
1418 widgetAnimator.abort(w); |
|
1419 if (w == pluggingWidget) |
|
1420 pluggingWidget = 0; |
|
1421 } |
|
1422 |
|
1423 if (savedState.isValid() ) { |
|
1424 //we need to remove the item also from the saved state to prevent crash |
|
1425 savedState.remove(ret); |
|
1426 //Also, the item may be contained several times as a gap item. |
|
1427 layoutState.remove(ret); |
|
1428 } |
|
1429 |
|
1430 #ifndef QT_NO_TOOLBAR |
|
1431 if (!currentGapPos.isEmpty() && currentGapPos.first() == 0) { |
|
1432 currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex(); |
|
1433 if (!currentGapPos.isEmpty()) { |
|
1434 currentGapPos.prepend(0); |
|
1435 currentGapRect = layoutState.itemRect(currentGapPos); |
|
1436 } |
|
1437 } |
|
1438 #endif |
|
1439 |
|
1440 return ret; |
|
1441 } |
|
1442 |
|
1443 if (statusbar && x++ == index) { |
|
1444 QLayoutItem *ret = statusbar; |
|
1445 statusbar = 0; |
|
1446 return ret; |
|
1447 } |
|
1448 |
|
1449 return 0; |
|
1450 } |
|
1451 |
|
1452 void QMainWindowLayout::setGeometry(const QRect &_r) |
|
1453 { |
|
1454 if (savedState.isValid()) |
|
1455 return; |
|
1456 |
|
1457 QRect r = _r; |
|
1458 |
|
1459 QLayout::setGeometry(r); |
|
1460 |
|
1461 if (statusbar) { |
|
1462 QRect sbr(QPoint(0, 0), |
|
1463 QSize(r.width(), statusbar->heightForWidth(r.width())) |
|
1464 .expandedTo(statusbar->minimumSize())); |
|
1465 sbr.moveBottom(r.bottom()); |
|
1466 QRect vr = QStyle::visualRect(parentWidget()->layoutDirection(), _r, sbr); |
|
1467 statusbar->setGeometry(vr); |
|
1468 r.setBottom(sbr.top() - 1); |
|
1469 } |
|
1470 |
|
1471 layoutState.rect = r; |
|
1472 layoutState.fitLayout(); |
|
1473 applyState(layoutState, false); |
|
1474 } |
|
1475 |
|
1476 void QMainWindowLayout::addItem(QLayoutItem *) |
|
1477 { qWarning("QMainWindowLayout::addItem: Please use the public QMainWindow API instead"); } |
|
1478 |
|
1479 QSize QMainWindowLayout::sizeHint() const |
|
1480 { |
|
1481 if (!szHint.isValid()) { |
|
1482 szHint = layoutState.sizeHint(); |
|
1483 const QSize sbHint = statusbar ? statusbar->sizeHint() : QSize(0, 0); |
|
1484 szHint = QSize(qMax(sbHint.width(), szHint.width()), |
|
1485 sbHint.height() + szHint.height()); |
|
1486 } |
|
1487 return szHint; |
|
1488 } |
|
1489 |
|
1490 QSize QMainWindowLayout::minimumSize() const |
|
1491 { |
|
1492 if (!minSize.isValid()) { |
|
1493 minSize = layoutState.minimumSize(); |
|
1494 const QSize sbMin = statusbar ? statusbar->minimumSize() : QSize(0, 0); |
|
1495 minSize = QSize(qMax(sbMin.width(), minSize.width()), |
|
1496 sbMin.height() + minSize.height()); |
|
1497 #ifdef Q_WS_MAC |
|
1498 const QSize storedSize = minSize; |
|
1499 int minWidth = 0; |
|
1500 foreach (QToolBar *toolbar, qtoolbarsInUnifiedToolbarList) { |
|
1501 minWidth += toolbar->sizeHint().width() + 20; |
|
1502 } |
|
1503 minSize = QSize(qMax(minWidth, storedSize.width()), storedSize.height()); |
|
1504 #endif |
|
1505 } |
|
1506 return minSize; |
|
1507 } |
|
1508 |
|
1509 void QMainWindowLayout::invalidate() |
|
1510 { |
|
1511 QLayout::invalidate(); |
|
1512 minSize = szHint = QSize(); |
|
1513 } |
|
1514 |
|
1515 /****************************************************************************** |
|
1516 ** QMainWindowLayout - remaining stuff |
|
1517 */ |
|
1518 |
|
1519 static void fixToolBarOrientation(QLayoutItem *item, int dockPos) |
|
1520 { |
|
1521 #ifndef QT_NO_TOOLBAR |
|
1522 QToolBar *toolBar = qobject_cast<QToolBar*>(item->widget()); |
|
1523 if (toolBar == 0) |
|
1524 return; |
|
1525 |
|
1526 QRect oldGeo = toolBar->geometry(); |
|
1527 |
|
1528 QInternal::DockPosition pos |
|
1529 = static_cast<QInternal::DockPosition>(dockPos); |
|
1530 Qt::Orientation o = pos == QInternal::TopDock || pos == QInternal::BottomDock |
|
1531 ? Qt::Horizontal : Qt::Vertical; |
|
1532 if (o != toolBar->orientation()) |
|
1533 toolBar->setOrientation(o); |
|
1534 |
|
1535 QSize hint = toolBar->sizeHint().boundedTo(toolBar->maximumSize()) |
|
1536 .expandedTo(toolBar->minimumSize()); |
|
1537 |
|
1538 if (toolBar->size() != hint) { |
|
1539 QRect newGeo(oldGeo.topLeft(), hint); |
|
1540 if (toolBar->layoutDirection() == Qt::RightToLeft) |
|
1541 newGeo.moveRight(oldGeo.right()); |
|
1542 toolBar->setGeometry(newGeo); |
|
1543 } |
|
1544 |
|
1545 #else |
|
1546 Q_UNUSED(item); |
|
1547 Q_UNUSED(dockPos); |
|
1548 #endif |
|
1549 } |
|
1550 |
|
1551 void QMainWindowLayout::revert(QLayoutItem *widgetItem) |
|
1552 { |
|
1553 if (!savedState.isValid()) |
|
1554 return; |
|
1555 |
|
1556 QWidget *widget = widgetItem->widget(); |
|
1557 layoutState = savedState; |
|
1558 currentGapPos = layoutState.indexOf(widget); |
|
1559 fixToolBarOrientation(widgetItem, currentGapPos.at(1)); |
|
1560 layoutState.unplug(currentGapPos); |
|
1561 layoutState.fitLayout(); |
|
1562 currentGapRect = layoutState.itemRect(currentGapPos); |
|
1563 |
|
1564 plug(widgetItem); |
|
1565 } |
|
1566 |
|
1567 bool QMainWindowLayout::plug(QLayoutItem *widgetItem) |
|
1568 { |
|
1569 if (!parentWidget()->isVisible() || parentWidget()->isMinimized() || currentGapPos.isEmpty()) |
|
1570 return false; |
|
1571 |
|
1572 fixToolBarOrientation(widgetItem, currentGapPos.at(1)); |
|
1573 |
|
1574 QWidget *widget = widgetItem->widget(); |
|
1575 |
|
1576 QList<int> previousPath = layoutState.indexOf(widget); |
|
1577 |
|
1578 QLayoutItem *it = layoutState.plug(currentGapPos); |
|
1579 Q_ASSERT(it == widgetItem); |
|
1580 Q_UNUSED(it); |
|
1581 if (!previousPath.isEmpty()) |
|
1582 layoutState.remove(previousPath); |
|
1583 |
|
1584 pluggingWidget = widget; |
|
1585 QRect globalRect = currentGapRect; |
|
1586 globalRect.moveTopLeft(parentWidget()->mapToGlobal(globalRect.topLeft())); |
|
1587 #ifndef QT_NO_DOCKWIDGET |
|
1588 if (qobject_cast<QDockWidget*>(widget) != 0) { |
|
1589 QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(widget->layout()); |
|
1590 if (layout->nativeWindowDeco()) { |
|
1591 globalRect.adjust(0, layout->titleHeight(), 0, 0); |
|
1592 } else { |
|
1593 int fw = widget->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, widget); |
|
1594 globalRect.adjust(-fw, -fw, fw, fw); |
|
1595 } |
|
1596 } |
|
1597 #endif |
|
1598 widgetAnimator.animate(widget, globalRect, dockOptions & QMainWindow::AnimatedDocks); |
|
1599 |
|
1600 return true; |
|
1601 } |
|
1602 |
|
1603 void QMainWindowLayout::animationFinished(QWidget *widget) |
|
1604 { |
|
1605 //this function is called from within the Widget Animator whenever an animation is finished |
|
1606 //on a certain widget |
|
1607 #ifndef QT_NO_TOOLBAR |
|
1608 if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) { |
|
1609 QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(tb->layout()); |
|
1610 if (tbl->animating) { |
|
1611 tbl->animating = false; |
|
1612 if (tbl->expanded) |
|
1613 tbl->layoutActions(tb->size()); |
|
1614 tb->update(); |
|
1615 } |
|
1616 } |
|
1617 #endif |
|
1618 |
|
1619 if (widget == pluggingWidget) { |
|
1620 |
|
1621 #ifndef QT_NO_DOCKWIDGET |
|
1622 if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) |
|
1623 dw->d_func()->plug(currentGapRect); |
|
1624 #endif |
|
1625 #ifndef QT_NO_TOOLBAR |
|
1626 if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) |
|
1627 tb->d_func()->plug(currentGapRect); |
|
1628 #endif |
|
1629 |
|
1630 #ifndef QT_NO_DOCKWIDGET |
|
1631 #ifndef QT_NO_TABBAR |
|
1632 if (qobject_cast<QDockWidget*>(widget) != 0) { |
|
1633 // info() might return null if the widget is destroyed while |
|
1634 // animating but before the animationFinished signal is received. |
|
1635 if (QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget)) |
|
1636 info->setCurrentTab(widget); |
|
1637 } |
|
1638 #endif |
|
1639 #endif |
|
1640 |
|
1641 savedState.clear(); |
|
1642 currentGapPos.clear(); |
|
1643 pluggingWidget = 0; |
|
1644 } |
|
1645 |
|
1646 if (!widgetAnimator.animating()) { |
|
1647 //all animations are finished |
|
1648 #ifndef QT_NO_DOCKWIDGET |
|
1649 parentWidget()->update(layoutState.dockAreaLayout.separatorRegion()); |
|
1650 #ifndef QT_NO_TABBAR |
|
1651 foreach (QTabBar *tab_bar, usedTabBars) |
|
1652 tab_bar->show(); |
|
1653 #endif // QT_NO_TABBAR |
|
1654 #endif // QT_NO_DOCKWIDGET |
|
1655 } |
|
1656 |
|
1657 updateGapIndicator(); |
|
1658 } |
|
1659 |
|
1660 void QMainWindowLayout::restore(bool keepSavedState) |
|
1661 { |
|
1662 if (!savedState.isValid()) |
|
1663 return; |
|
1664 |
|
1665 layoutState = savedState; |
|
1666 applyState(layoutState); |
|
1667 if (!keepSavedState) |
|
1668 savedState.clear(); |
|
1669 currentGapPos.clear(); |
|
1670 pluggingWidget = 0; |
|
1671 updateGapIndicator(); |
|
1672 } |
|
1673 |
|
1674 QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow) |
|
1675 : QLayout(mainwindow) |
|
1676 , layoutState(mainwindow) |
|
1677 , savedState(mainwindow) |
|
1678 , dockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowTabbedDocks) |
|
1679 , statusbar(0) |
|
1680 #ifndef QT_NO_DOCKWIDGET |
|
1681 #ifndef QT_NO_TABBAR |
|
1682 , _documentMode(false) |
|
1683 , verticalTabsEnabled(false) |
|
1684 #ifndef QT_NO_TABWIDGET |
|
1685 , _tabShape(QTabWidget::Rounded) |
|
1686 #endif |
|
1687 #endif |
|
1688 #endif // QT_NO_DOCKWIDGET |
|
1689 , widgetAnimator(this) |
|
1690 , pluggingWidget(0) |
|
1691 #ifndef QT_NO_RUBBERBAND |
|
1692 , gapIndicator(new QRubberBand(QRubberBand::Rectangle, mainwindow)) |
|
1693 #endif //QT_NO_RUBBERBAND |
|
1694 #ifdef Q_WS_MAC |
|
1695 , blockVisiblityCheck(false) |
|
1696 #endif |
|
1697 { |
|
1698 #ifndef QT_NO_DOCKWIDGET |
|
1699 #ifndef QT_NO_TABBAR |
|
1700 sep = mainwindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, mainwindow); |
|
1701 #endif |
|
1702 |
|
1703 #ifndef QT_NO_TABWIDGET |
|
1704 for (int i = 0; i < QInternal::DockCount; ++i) |
|
1705 tabPositions[i] = QTabWidget::South; |
|
1706 #endif |
|
1707 #endif // QT_NO_DOCKWIDGET |
|
1708 |
|
1709 #ifndef QT_NO_RUBBERBAND |
|
1710 // For accessibility to identify this special widget. |
|
1711 gapIndicator->setObjectName(QLatin1String("qt_rubberband")); |
|
1712 gapIndicator->hide(); |
|
1713 #endif |
|
1714 pluggingWidget = 0; |
|
1715 |
|
1716 setObjectName(mainwindow->objectName() + QLatin1String("_layout")); |
|
1717 } |
|
1718 |
|
1719 QMainWindowLayout::~QMainWindowLayout() |
|
1720 { |
|
1721 layoutState.deleteAllLayoutItems(); |
|
1722 layoutState.deleteCentralWidgetItem(); |
|
1723 |
|
1724 #ifdef Q_WS_MAC |
|
1725 cleanUpMacToolbarItems(); |
|
1726 #endif |
|
1727 |
|
1728 delete statusbar; |
|
1729 } |
|
1730 |
|
1731 void QMainWindowLayout::setDockOptions(QMainWindow::DockOptions opts) |
|
1732 { |
|
1733 if (opts == dockOptions) |
|
1734 return; |
|
1735 |
|
1736 dockOptions = opts; |
|
1737 |
|
1738 #ifndef QT_NO_DOCKWIDGET |
|
1739 setVerticalTabsEnabled(opts & QMainWindow::VerticalTabs); |
|
1740 #endif |
|
1741 |
|
1742 invalidate(); |
|
1743 } |
|
1744 |
|
1745 #ifndef QT_NO_STATUSBAR |
|
1746 QStatusBar *QMainWindowLayout::statusBar() const |
|
1747 { return statusbar ? qobject_cast<QStatusBar *>(statusbar->widget()) : 0; } |
|
1748 |
|
1749 void QMainWindowLayout::setStatusBar(QStatusBar *sb) |
|
1750 { |
|
1751 if (sb) |
|
1752 addChildWidget(sb); |
|
1753 delete statusbar; |
|
1754 statusbar = sb ? new QWidgetItemV2(sb) : 0; |
|
1755 invalidate(); |
|
1756 } |
|
1757 #endif // QT_NO_STATUSBAR |
|
1758 |
|
1759 QWidget *QMainWindowLayout::centralWidget() const |
|
1760 { |
|
1761 return layoutState.centralWidget(); |
|
1762 } |
|
1763 |
|
1764 void QMainWindowLayout::setCentralWidget(QWidget *widget) |
|
1765 { |
|
1766 if (widget != 0) |
|
1767 addChildWidget(widget); |
|
1768 layoutState.setCentralWidget(widget); |
|
1769 if (savedState.isValid()) { |
|
1770 #ifndef QT_NO_DOCKWIDGET |
|
1771 savedState.dockAreaLayout.centralWidgetItem = layoutState.dockAreaLayout.centralWidgetItem; |
|
1772 #else |
|
1773 savedState.centralWidgetItem = layoutState.centralWidgetItem; |
|
1774 #endif |
|
1775 } |
|
1776 invalidate(); |
|
1777 } |
|
1778 |
|
1779 QLayoutItem *QMainWindowLayout::unplug(QWidget *widget) |
|
1780 { |
|
1781 QList<int> path = layoutState.indexOf(widget); |
|
1782 if (path.isEmpty()) |
|
1783 return 0; |
|
1784 |
|
1785 QLayoutItem *item = layoutState.item(path); |
|
1786 if (widget->isWindow()) |
|
1787 return item; |
|
1788 |
|
1789 QRect r = layoutState.itemRect(path); |
|
1790 savedState = layoutState; |
|
1791 |
|
1792 #ifndef QT_NO_DOCKWIDGET |
|
1793 if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) { |
|
1794 dw->d_func()->unplug(r); |
|
1795 } |
|
1796 #endif |
|
1797 #ifndef QT_NO_TOOLBAR |
|
1798 if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) { |
|
1799 tb->d_func()->unplug(r); |
|
1800 } |
|
1801 #endif |
|
1802 |
|
1803 |
|
1804 layoutState.unplug(path ,&savedState); |
|
1805 savedState.fitLayout(); |
|
1806 currentGapPos = path; |
|
1807 currentGapRect = r; |
|
1808 updateGapIndicator(); |
|
1809 |
|
1810 fixToolBarOrientation(item, currentGapPos.at(1)); |
|
1811 |
|
1812 return item; |
|
1813 } |
|
1814 |
|
1815 void QMainWindowLayout::updateGapIndicator() |
|
1816 { |
|
1817 #ifndef QT_NO_RUBBERBAND |
|
1818 gapIndicator->setVisible(!widgetAnimator.animating() && !currentGapPos.isEmpty()); |
|
1819 gapIndicator->setGeometry(currentGapRect); |
|
1820 #endif |
|
1821 } |
|
1822 |
|
1823 QList<int> QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos) |
|
1824 { |
|
1825 if (!parentWidget()->isVisible() || parentWidget()->isMinimized() |
|
1826 || pluggingWidget != 0 || widgetItem == 0) |
|
1827 return QList<int>(); |
|
1828 |
|
1829 QWidget *widget = widgetItem->widget(); |
|
1830 QPoint pos = parentWidget()->mapFromGlobal(mousePos); |
|
1831 |
|
1832 if (!savedState.isValid()) |
|
1833 savedState = layoutState; |
|
1834 |
|
1835 QList<int> path = savedState.gapIndex(widget, pos); |
|
1836 |
|
1837 if (!path.isEmpty()) { |
|
1838 bool allowed = false; |
|
1839 |
|
1840 #ifndef QT_NO_DOCKWIDGET |
|
1841 if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) |
|
1842 allowed = dw->isAreaAllowed(toDockWidgetArea(path.at(1))); |
|
1843 #endif |
|
1844 #ifndef QT_NO_TOOLBAR |
|
1845 if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) |
|
1846 allowed = tb->isAreaAllowed(toToolBarArea(path.at(1))); |
|
1847 #endif |
|
1848 |
|
1849 if (!allowed) |
|
1850 path.clear(); |
|
1851 } |
|
1852 |
|
1853 if (path == currentGapPos) |
|
1854 return currentGapPos; // the gap is already there |
|
1855 |
|
1856 currentGapPos = path; |
|
1857 if (path.isEmpty()) { |
|
1858 fixToolBarOrientation(widgetItem, 2); // 2 = top dock, ie. horizontal |
|
1859 restore(true); |
|
1860 return QList<int>(); |
|
1861 } |
|
1862 |
|
1863 fixToolBarOrientation(widgetItem, currentGapPos.at(1)); |
|
1864 |
|
1865 QMainWindowLayoutState newState = savedState; |
|
1866 |
|
1867 if (!newState.insertGap(path, widgetItem)) { |
|
1868 restore(true); // not enough space |
|
1869 return QList<int>(); |
|
1870 } |
|
1871 |
|
1872 QSize min = newState.minimumSize(); |
|
1873 QSize size = newState.rect.size(); |
|
1874 |
|
1875 if (min.width() > size.width() || min.height() > size.height()) { |
|
1876 restore(true); |
|
1877 return QList<int>(); |
|
1878 } |
|
1879 |
|
1880 newState.fitLayout(); |
|
1881 |
|
1882 currentGapRect = newState.gapRect(currentGapPos); |
|
1883 |
|
1884 #ifndef QT_NO_DOCKWIDGET |
|
1885 parentWidget()->update(layoutState.dockAreaLayout.separatorRegion()); |
|
1886 #endif |
|
1887 layoutState = newState; |
|
1888 applyState(layoutState); |
|
1889 |
|
1890 updateGapIndicator(); |
|
1891 |
|
1892 return path; |
|
1893 } |
|
1894 |
|
1895 void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animate) |
|
1896 { |
|
1897 #ifndef QT_NO_DOCKWIDGET |
|
1898 #ifndef QT_NO_TABBAR |
|
1899 QSet<QTabBar*> used = newState.dockAreaLayout.usedTabBars(); |
|
1900 QSet<QTabBar*> retired = usedTabBars - used; |
|
1901 usedTabBars = used; |
|
1902 foreach (QTabBar *tab_bar, retired) { |
|
1903 tab_bar->hide(); |
|
1904 while (tab_bar->count() > 0) |
|
1905 tab_bar->removeTab(0); |
|
1906 unusedTabBars.append(tab_bar); |
|
1907 } |
|
1908 |
|
1909 if (sep == 1) { |
|
1910 QSet<QWidget*> usedSeps = newState.dockAreaLayout.usedSeparatorWidgets(); |
|
1911 QSet<QWidget*> retiredSeps = usedSeparatorWidgets - usedSeps; |
|
1912 usedSeparatorWidgets = usedSeps; |
|
1913 foreach (QWidget *sepWidget, retiredSeps) { |
|
1914 unusedSeparatorWidgets.append(sepWidget); |
|
1915 } |
|
1916 } |
|
1917 |
|
1918 |
|
1919 #endif // QT_NO_TABBAR |
|
1920 #endif // QT_NO_DOCKWIDGET |
|
1921 newState.apply(dockOptions & QMainWindow::AnimatedDocks && animate); |
|
1922 } |
|
1923 |
|
1924 void QMainWindowLayout::saveState(QDataStream &stream) const |
|
1925 { |
|
1926 layoutState.saveState(stream); |
|
1927 } |
|
1928 |
|
1929 bool QMainWindowLayout::restoreState(QDataStream &stream) |
|
1930 { |
|
1931 savedState = layoutState; |
|
1932 layoutState.clear(); |
|
1933 layoutState.rect = savedState.rect; |
|
1934 |
|
1935 if (!layoutState.restoreState(stream, savedState)) { |
|
1936 layoutState.deleteAllLayoutItems(); |
|
1937 layoutState = savedState; |
|
1938 if (parentWidget()->isVisible()) |
|
1939 applyState(layoutState, false); // hides tabBars allocated by newState |
|
1940 return false; |
|
1941 } |
|
1942 |
|
1943 if (parentWidget()->isVisible()) { |
|
1944 layoutState.fitLayout(); |
|
1945 applyState(layoutState, false); |
|
1946 } |
|
1947 |
|
1948 savedState.deleteAllLayoutItems(); |
|
1949 savedState.clear(); |
|
1950 |
|
1951 #ifndef QT_NO_DOCKWIDGET |
|
1952 if (parentWidget()->isVisible()) { |
|
1953 #ifndef QT_NO_TABBAR |
|
1954 foreach (QTabBar *tab_bar, usedTabBars) |
|
1955 tab_bar->show(); |
|
1956 |
|
1957 #endif |
|
1958 } |
|
1959 #endif // QT_NO_DOCKWIDGET |
|
1960 |
|
1961 return true; |
|
1962 } |
|
1963 |
|
1964 |
|
1965 // Returns if this toolbar *should* be using HIToolbar. Won't work for all in between cases |
|
1966 // for example, you have a toolbar in the top area and then you suddenly turn on |
|
1967 // HIToolbar. |
|
1968 bool QMainWindowLayout::usesHIToolBar(QToolBar *toolbar) const |
|
1969 { |
|
1970 #ifndef Q_WS_MAC |
|
1971 Q_UNUSED(toolbar); |
|
1972 return false; |
|
1973 #else |
|
1974 return qtoolbarsInUnifiedToolbarList.contains(toolbar) |
|
1975 || ((toolBarArea(toolbar) == Qt::TopToolBarArea) |
|
1976 && layoutState.mainWindow->unifiedTitleAndToolBarOnMac()); |
|
1977 #endif |
|
1978 } |
|
1979 |
|
1980 void QMainWindowLayout::timerEvent(QTimerEvent *e) |
|
1981 { |
|
1982 #ifndef QT_NO_DOCKWIDGET |
|
1983 if (e->timerId() == separatorMoveTimer.timerId()) { |
|
1984 //let's move the separators |
|
1985 separatorMoveTimer.stop(); |
|
1986 if (movingSeparator.isEmpty()) |
|
1987 return; |
|
1988 if (movingSeparatorOrigin == movingSeparatorPos) |
|
1989 return; |
|
1990 |
|
1991 //when moving the separator, we need to update the previous position |
|
1992 parentWidget()->update(layoutState.dockAreaLayout.separatorRegion()); |
|
1993 |
|
1994 layoutState = savedState; |
|
1995 layoutState.dockAreaLayout.separatorMove(movingSeparator, movingSeparatorOrigin, |
|
1996 movingSeparatorPos); |
|
1997 movingSeparatorPos = movingSeparatorOrigin; |
|
1998 } |
|
1999 #endif |
|
2000 QLayout::timerEvent(e); |
|
2001 } |
|
2002 |
|
2003 |
|
2004 QT_END_NAMESPACE |
|
2005 |
|
2006 #endif // QT_NO_MAINWINDOW |