Qt 4.8
qdockarealayout.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui 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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "QtGui/qapplication.h"
43 #include "QtGui/qwidget.h"
44 #include "QtGui/qtabbar.h"
45 #include "QtGui/qstyle.h"
46 #include "QtGui/qdesktopwidget.h"
47 #include "QtCore/qvariant.h"
48 #include "qdockarealayout_p.h"
49 #include "qdockwidget.h"
50 #include "qmainwindow.h"
51 #include "qwidgetanimator_p.h"
52 #include "qmainwindowlayout_p.h"
53 #include "qdockwidget_p.h"
54 #include <private/qlayoutengine_p.h>
55 
56 #include <qpainter.h>
57 #include <qstyleoption.h>
58 
59 #ifndef QT_NO_DOCKWIDGET
60 
62 
63 // qmainwindow.cpp
65 
67 
68 /******************************************************************************
69 ** QPlaceHolderItem
70 */
71 
73 {
74  objectName = w->objectName();
75  hidden = w->isHidden();
76  window = w->isWindow();
77  if (window)
78  topLevelRect = w->geometry();
79 }
80 
81 /******************************************************************************
82 ** QDockAreaLayoutItem
83 */
84 
86  : widgetItem(_widgetItem), subinfo(0), placeHolderItem(0), pos(0), size(-1), flags(NoFlags)
87 {
88 }
89 
91  : widgetItem(0), subinfo(_subinfo), placeHolderItem(0), pos(0), size(-1), flags(NoFlags)
92 {
93 }
94 
96  : widgetItem(0), subinfo(0), placeHolderItem(_placeHolderItem), pos(0), size(-1), flags(NoFlags)
97 {
98 }
99 
101  : widgetItem(other.widgetItem), subinfo(0), placeHolderItem(0), pos(other.pos),
102  size(other.size), flags(other.flags)
103 {
104  if (other.subinfo != 0)
105  subinfo = new QDockAreaLayoutInfo(*other.subinfo);
106  else if (other.placeHolderItem != 0)
108 }
109 
111 {
112  delete subinfo;
113  delete placeHolderItem;
114 }
115 
117 {
118  if (placeHolderItem != 0)
119  return true;
120 
121  if (flags & GapItem)
122  return false;
123 
124  if (widgetItem != 0)
125  return widgetItem->isEmpty();
126 
127  if (subinfo != 0) {
128  for (int i = 0; i < subinfo->item_list.count(); ++i) {
129  if (!subinfo->item_list.at(i).skip())
130  return false;
131  }
132  }
133 
134  return true;
135 }
136 
138 {
139  if (widgetItem != 0) {
140  int left, top, right, bottom;
141  widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom);
142  return widgetItem->minimumSize() + QSize(left+right, top+bottom);
143  }
144  if (subinfo != 0)
145  return subinfo->minimumSize();
146  return QSize(0, 0);
147 }
148 
150 {
151  if (widgetItem != 0) {
152  int left, top, right, bottom;
153  widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom);
154  return widgetItem->maximumSize()+ QSize(left+right, top+bottom);
155  }
156  if (subinfo != 0)
157  return subinfo->maximumSize();
159 }
160 
162 {
163  return perp(o, minimumSize()) == perp(o, maximumSize());
164 }
165 
167 {
168  if ((flags & GapItem) || placeHolderItem != 0)
169  return false;
170  if (widgetItem != 0)
171  return ((widgetItem->expandingDirections() & o) == o);
172  if (subinfo != 0)
173  return subinfo->expansive(o);
174  return false;
175 }
176 
178 {
179  if (placeHolderItem != 0)
180  return QSize(0, 0);
181  if (widgetItem != 0) {
182  int left, top, right, bottom;
183  widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom);
184  return widgetItem->sizeHint() + QSize(left+right, top+bottom);
185  }
186  if (subinfo != 0)
187  return subinfo->sizeHint();
188  return QSize(-1, -1);
189 }
190 
193 {
194  widgetItem = other.widgetItem;
195  if (other.subinfo == 0)
196  subinfo = 0;
197  else
198  subinfo = new QDockAreaLayoutInfo(*other.subinfo);
199 
200  delete placeHolderItem;
201  if (other.placeHolderItem == 0)
202  placeHolderItem = 0;
203  else
205 
206  pos = other.pos;
207  size = other.size;
208  flags = other.flags;
209 
210  return *this;
211 }
212 
213 /******************************************************************************
214 ** QDockAreaLayoutInfo
215 */
216 
217 #ifndef QT_NO_TABBAR
218 static quintptr tabId(const QDockAreaLayoutItem &item)
219 {
220  if (item.widgetItem == 0)
221  return 0;
222  return reinterpret_cast<quintptr>(item.widgetItem->widget());
223 }
224 #endif
225 
226 static const int zero = 0;
227 
229  : sep(&zero), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
230 #ifndef QT_NO_TABBAR
231  , tabbed(false), tabBar(0), tabBarShape(QTabBar::RoundedSouth)
232 #endif
233 {
234 }
235 
237  Qt::Orientation _o, int tbshape,
239  : sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window)
240 #ifndef QT_NO_TABBAR
241  , tabbed(false), tabBar(0), tabBarShape(static_cast<QTabBar::Shape>(tbshape))
242 #endif
243 {
244 #ifdef QT_NO_TABBAR
245  Q_UNUSED(tbshape);
246 #endif
247 }
248 
250 {
251  return isEmpty() ? QSize(0, 0) : rect.size();
252 }
253 
255 {
256  item_list.clear();
257  rect = QRect();
258 #ifndef QT_NO_TABBAR
259  tabbed = false;
260  tabBar = 0;
261 #endif
262 }
263 
265 {
266  return next(-1) == -1;
267 }
268 
270 {
271  if (isEmpty())
272  return QSize(0, 0);
273 
274  int a = 0, b = 0;
275  bool first = true;
276  for (int i = 0; i < item_list.size(); ++i) {
277  const QDockAreaLayoutItem &item = item_list.at(i);
278  if (item.skip())
279  continue;
280 
281  QSize min_size = item.minimumSize();
282 #ifndef QT_NO_TABBAR
283  if (tabbed) {
284  a = qMax(a, pick(o, min_size));
285  } else
286 #endif
287  {
288  if (!first)
289  a += *sep;
290  a += pick(o, min_size);
291  }
292  b = qMax(b, perp(o, min_size));
293 
294  first = false;
295  }
296 
297  QSize result;
298  rpick(o, result) = a;
299  rperp(o, result) = b;
300 
301 #ifndef QT_NO_TABBAR
302  QSize tbm = tabBarMinimumSize();
303  if (!tbm.isNull()) {
304  switch (tabBarShape) {
309  result.rheight() += tbm.height();
310  result.rwidth() = qMax(tbm.width(), result.width());
311  break;
316  result.rheight() = qMax(tbm.height(), result.height());
317  result.rwidth() += tbm.width();
318  break;
319  default:
320  break;
321  }
322  }
323 #endif // QT_NO_TABBAR
324 
325  return result;
326 }
327 
329 {
330  if (isEmpty())
332 
333  int a = 0, b = QWIDGETSIZE_MAX;
334 #ifndef QT_NO_TABBAR
335  if (tabbed)
336  a = QWIDGETSIZE_MAX;
337 #endif
338 
339  int min_perp = 0;
340 
341  bool first = true;
342  for (int i = 0; i < item_list.size(); ++i) {
343  const QDockAreaLayoutItem &item = item_list.at(i);
344  if (item.skip())
345  continue;
346 
347  QSize max_size = item.maximumSize();
348  min_perp = qMax(min_perp, perp(o, item.minimumSize()));
349 
350 #ifndef QT_NO_TABBAR
351  if (tabbed) {
352  a = qMin(a, pick(o, max_size));
353  } else
354 #endif
355  {
356  if (!first)
357  a += *sep;
358  a += pick(o, max_size);
359  }
360  b = qMin(b, perp(o, max_size));
361 
362  a = qMin(a, int(QWIDGETSIZE_MAX));
363  b = qMin(b, int(QWIDGETSIZE_MAX));
364 
365  first = false;
366  }
367 
368  b = qMax(b, min_perp);
369 
370  QSize result;
371  rpick(o, result) = a;
372  rperp(o, result) = b;
373 
374 #ifndef QT_NO_TABBAR
375  QSize tbh = tabBarSizeHint();
376  if (!tbh.isNull()) {
377  switch (tabBarShape) {
380  result.rheight() += tbh.height();
381  break;
384  result.rwidth() += tbh.width();
385  break;
386  default:
387  break;
388  }
389  }
390 #endif // QT_NO_TABBAR
391 
392  return result;
393 }
394 
396 {
397  if (isEmpty())
398  return QSize(0, 0);
399 
400  int a = 0, b = 0;
401  int min_perp = 0;
402  int max_perp = QWIDGETSIZE_MAX;
403  const QDockAreaLayoutItem *previous = 0;
404  for (int i = 0; i < item_list.size(); ++i) {
405  const QDockAreaLayoutItem &item = item_list.at(i);
406  if (item.skip())
407  continue;
408 
409  bool gap = item.flags & QDockAreaLayoutItem::GapItem;
410 
411  QSize size_hint = item.sizeHint();
412  min_perp = qMax(min_perp, perp(o, item.minimumSize()));
413  max_perp = qMin(max_perp, perp(o, item.maximumSize()));
414 
415 #ifndef QT_NO_TABBAR
416  if (tabbed) {
417  a = qMax(a, gap ? item.size : pick(o, size_hint));
418  } else
419 #endif
420  {
421  if (previous && !gap && !(previous->flags & QDockAreaLayoutItem::GapItem)
422  && !previous->hasFixedSize(o)) {
423  a += *sep;
424  }
425  a += gap ? item.size : pick(o, size_hint);
426  }
427  b = qMax(b, perp(o, size_hint));
428 
429  previous = &item;
430  }
431 
432  max_perp = qMax(max_perp, min_perp);
433  b = qMax(b, min_perp);
434  b = qMin(b, max_perp);
435 
436  QSize result;
437  rpick(o, result) = a;
438  rperp(o, result) = b;
439 
440 #ifndef QT_NO_TABBAR
441  if (tabbed) {
442  QSize tbh = tabBarSizeHint();
443  switch (tabBarShape) {
448  result.rheight() += tbh.height();
449  result.rwidth() = qMax(tbh.width(), result.width());
450  break;
455  result.rheight() = qMax(tbh.height(), result.height());
456  result.rwidth() += tbh.width();
457  break;
458  default:
459  break;
460  }
461  }
462 #endif // QT_NO_TABBAR
463 
464  return result;
465 }
466 
468 {
469  for (int i = 0; i < item_list.size(); ++i) {
470  if (item_list.at(i).expansive(o))
471  return true;
472  }
473  return false;
474 }
475 
476 /* QDockAreaLayoutInfo::maximumSize() doesn't return the real max size. For example,
477  if the layout is empty, it returns QWIDGETSIZE_MAX. This is so that empty dock areas
478  don't constrain the size of the QMainWindow, but sometimes we really need to know the
479  maximum size. Also, these functions take into account widgets that want to keep their
480  size (f.ex. when they are hidden and then shown, they should not change size).
481 */
482 
484 {
485  int result = 0;
486  bool first = true;
487  for (int i = 0; i < info.item_list.size(); ++i) {
488  const QDockAreaLayoutItem &item = info.item_list.at(i);
489  if (item.skip())
490  continue;
491 
492  int min = 0;
493  if ((item.flags & QDockAreaLayoutItem::KeepSize) && item.size != -1)
494  min = item.size;
495  else
496  min = pick(info.o, item.minimumSize());
497 
498  if (!first)
499  result += *info.sep;
500  result += min;
501 
502  first = false;
503  }
504 
505  return result;
506 }
507 
509 {
510  int result = 0;
511  bool first = true;
512  for (int i = 0; i < info.item_list.size(); ++i) {
513  const QDockAreaLayoutItem &item = info.item_list.at(i);
514  if (item.skip())
515  continue;
516 
517  int max = 0;
518  if ((item.flags & QDockAreaLayoutItem::KeepSize) && item.size != -1)
519  max = item.size;
520  else
521  max = pick(info.o, item.maximumSize());
522 
523  if (!first)
524  result += *info.sep;
525  result += max;
526 
527  if (result >= QWIDGETSIZE_MAX)
528  return QWIDGETSIZE_MAX;
529 
530  first = false;
531  }
532 
533  return result;
534 }
535 
537 {
538 #ifndef QT_NO_TABBAR
539  if (tabbed) {
540  return;
541  }
542 #endif
543 
544  QVector<QLayoutStruct> layout_struct_list(item_list.size()*2);
545  int j = 0;
546 
547  int size = pick(o, rect.size());
548  int min_size = realMinSize(*this);
549  int max_size = realMaxSize(*this);
550  int last_index = -1;
551 
552  const QDockAreaLayoutItem *previous = 0;
553  for (int i = 0; i < item_list.size(); ++i) {
555  if (item.skip())
556  continue;
557 
558  bool gap = item.flags & QDockAreaLayoutItem::GapItem;
559  if (previous && !gap) {
560  if (!(previous->flags & QDockAreaLayoutItem::GapItem)) {
561  QLayoutStruct &ls = layout_struct_list[j++];
562  ls.init();
563  ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : *sep;
564  ls.empty = false;
565  }
566  }
567 
569  // Check if the item can keep its size, without violating size constraints
570  // of other items.
571 
572  if (size < min_size) {
573  // There is too little space to keep this widget's size
574  item.flags &= ~QDockAreaLayoutItem::KeepSize;
575  min_size -= item.size;
576  min_size += pick(o, item.minimumSize());
577  min_size = qMax(0, min_size);
578  } else if (size > max_size) {
579  // There is too much space to keep this widget's size
580  item.flags &= ~QDockAreaLayoutItem::KeepSize;
581  max_size -= item.size;
582  max_size += pick(o, item.maximumSize());
583  max_size = qMin<int>(QWIDGETSIZE_MAX, max_size);
584  }
585  }
586 
587  last_index = j;
588  QLayoutStruct &ls = layout_struct_list[j++];
589  ls.init();
590  ls.empty = false;
592  ls.minimumSize = ls.maximumSize = ls.sizeHint = item.size;
593  ls.expansive = false;
594  ls.stretch = 0;
595  } else {
596  ls.maximumSize = pick(o, item.maximumSize());
597  ls.expansive = item.expansive(o);
598  ls.minimumSize = pick(o, item.minimumSize());
599  ls.sizeHint = item.size == -1 ? pick(o, item.sizeHint()) : item.size;
600  ls.stretch = ls.expansive ? ls.sizeHint : 0;
601  }
602 
603  item.flags &= ~QDockAreaLayoutItem::KeepSize;
604  previous = &item;
605  }
606  layout_struct_list.resize(j);
607 
608  // If there is more space than the widgets can take (due to maximum size constraints),
609  // we detect it here and stretch the last widget to take up the rest of the space.
610  if (size > max_size && last_index != -1) {
611  layout_struct_list[last_index].maximumSize = QWIDGETSIZE_MAX;
612  layout_struct_list[last_index].expansive = true;
613  }
614 
615  qGeomCalc(layout_struct_list, 0, j, pick(o, rect.topLeft()), size, 0);
616 
617  j = 0;
618  bool prev_gap = false;
619  bool first = true;
620  for (int i = 0; i < item_list.size(); ++i) {
622  if (item.skip())
623  continue;
624 
625  bool gap = item.flags & QDockAreaLayoutItem::GapItem;
626  if (!first && !gap && !prev_gap)
627  ++j;
628 
629  const QLayoutStruct &ls = layout_struct_list.at(j++);
630  item.size = ls.size;
631  item.pos = ls.pos;
632 
633  if (item.subinfo != 0) {
634  item.subinfo->rect = itemRect(i);
635  item.subinfo->fitItems();
636  }
637 
638  prev_gap = gap;
639  first = false;
640  }
641 }
642 
645  bool nestingEnabled,
647 {
648  if (tabMode == QDockAreaLayoutInfo::ForceTabs)
649  return QInternal::DockCount;
650 
651  QPoint pos = _pos - rect.topLeft();
652 
653  int x = pos.x();
654  int y = pos.y();
655  int w = rect.width();
656  int h = rect.height();
657 
658  if (tabMode != QDockAreaLayoutInfo::NoTabs) {
659  // is it in the center?
660  if (nestingEnabled) {
661  /* 2/3
662  +--------------+
663  | |
664  | CCCCCCCC |
665  2/3 | CCCCCCCC |
666  | CCCCCCCC |
667  | |
668  +--------------+ */
669 
670  QRect center(w/6, h/6, 2*w/3, 2*h/3);
671  if (center.contains(pos))
672  return QInternal::DockCount;
673  } else if (o == Qt::Horizontal) {
674  /* 2/3
675  +--------------+
676  | CCCCCCCC |
677  | CCCCCCCC |
678  | CCCCCCCC |
679  | CCCCCCCC |
680  | CCCCCCCC |
681  +--------------+ */
682 
683  if (x > w/6 && x < w*5/6)
684  return QInternal::DockCount;
685  } else {
686  /*
687  +--------------+
688  | |
689  2/3 |CCCCCCCCCCCCCC|
690  |CCCCCCCCCCCCCC|
691  | |
692  +--------------+ */
693  if (y > h/6 && y < 5*h/6)
694  return QInternal::DockCount;
695  }
696  }
697 
698  // not in the center. which edge?
699  if (nestingEnabled) {
700  if (o == Qt::Horizontal) {
701  /* 1/3 1/3 1/3
702  +------------+ (we've already ruled out the center)
703  |LLLLTTTTRRRR|
704  |LLLLTTTTRRRR|
705  |LLLLBBBBRRRR|
706  |LLLLBBBBRRRR|
707  +------------+ */
708 
709  if (x < w/3)
710  return QInternal::LeftDock;
711  if (x > 2*w/3)
712  return QInternal::RightDock;
713  if (y < h/2)
714  return QInternal::TopDock;
715  return QInternal::BottomDock;
716  } else {
717  /* +------------+ (we've already ruled out the center)
718  1/3 |TTTTTTTTTTTT|
719  |LLLLLLRRRRRR|
720  1/3 |LLLLLLRRRRRR|
721  1/3 |BBBBBBBBBBBB|
722  +------------+ */
723 
724  if (y < h/3)
725  return QInternal::TopDock;
726  if (y > 2*h/3)
727  return QInternal::BottomDock;
728  if (x < w/2)
729  return QInternal::LeftDock;
730  return QInternal::RightDock;
731  }
732  } else {
733  if (o == Qt::Horizontal) {
734  return x < w/2
737  } else {
738  return y < h/2
741  }
742  }
743 }
744 
746  bool nestingEnabled, TabMode tabMode) const
747 {
748  QList<int> result;
749  QRect item_rect;
750  int item_index = 0;
751 
752 #ifndef QT_NO_TABBAR
753  if (tabbed) {
754  item_rect = tabContentRect();
755  } else
756 #endif
757  {
758  int pos = pick(o, _pos);
759 
760  int last = -1;
761  for (int i = 0; i < item_list.size(); ++i) {
762  const QDockAreaLayoutItem &item = item_list.at(i);
763  if (item.skip())
764  continue;
765 
766  last = i;
767 
768  if (item.pos + item.size < pos)
769  continue;
770 
771  if (item.subinfo != 0
772 #ifndef QT_NO_TABBAR
773  && !item.subinfo->tabbed
774 #endif
775  ) {
776  result = item.subinfo->gapIndex(_pos, nestingEnabled,
777  tabMode);
778  result.prepend(i);
779  return result;
780  }
781 
782  item_rect = itemRect(i);
783  item_index = i;
784  break;
785  }
786 
787  if (item_rect.isNull()) {
788  result.append(last + 1);
789  return result;
790  }
791  }
792 
793  Q_ASSERT(!item_rect.isNull());
794 
795  QInternal::DockPosition dock_pos
796  = dockPosHelper(item_rect, _pos, o, nestingEnabled, tabMode);
797 
798  switch (dock_pos) {
799  case QInternal::LeftDock:
800  if (o == Qt::Horizontal)
801  result << item_index;
802  else
803  result << item_index << 0; // this subinfo doesn't exist yet, but insertGap()
804  // handles this by inserting it
805  break;
807  if (o == Qt::Horizontal)
808  result << item_index + 1;
809  else
810  result << item_index << 1;
811  break;
812  case QInternal::TopDock:
813  if (o == Qt::Horizontal)
814  result << item_index << 0;
815  else
816  result << item_index;
817  break;
819  if (o == Qt::Horizontal)
820  result << item_index << 1;
821  else
822  result << item_index + 1;
823  break;
825  result << (-item_index - 1) << 0; // negative item_index means "on top of"
826  // -item_index - 1, insertGap()
827  // will insert a tabbed subinfo
828  break;
829  default:
830  break;
831  }
832 
833  return result;
834 }
835 
836 static inline int shrink(QLayoutStruct &ls, int delta)
837 {
838  if (ls.empty)
839  return 0;
840  int old_size = ls.size;
841  ls.size = qMax(ls.size - delta, ls.minimumSize);
842  return old_size - ls.size;
843 }
844 
845 static inline int grow(QLayoutStruct &ls, int delta)
846 {
847  if (ls.empty)
848  return 0;
849  int old_size = ls.size;
850  ls.size = qMin(ls.size + delta, ls.maximumSize);
851  return ls.size - old_size;
852 }
853 
854 static int separatorMoveHelper(QVector<QLayoutStruct> &list, int index, int delta, int sep)
855 {
856  // adjust sizes
857  int pos = -1;
858  for (int i = 0; i < list.size(); ++i) {
859  const QLayoutStruct &ls = list.at(i);
860  if (!ls.empty) {
861  pos = ls.pos;
862  break;
863  }
864  }
865  if (pos == -1)
866  return 0;
867 
868  if (delta > 0) {
869  int growlimit = 0;
870  for (int i = 0; i<=index; ++i) {
871  const QLayoutStruct &ls = list.at(i);
872  if (ls.empty)
873  continue;
874  if (ls.maximumSize == QLAYOUTSIZE_MAX) {
875  growlimit = QLAYOUTSIZE_MAX;
876  break;
877  }
878  growlimit += ls.maximumSize - ls.size;
879  }
880  if (delta > growlimit)
881  delta = growlimit;
882 
883  int d = 0;
884  for (int i = index + 1; d < delta && i < list.count(); ++i)
885  d += shrink(list[i], delta - d);
886  delta = d;
887  d = 0;
888  for (int i = index; d < delta && i >= 0; --i)
889  d += grow(list[i], delta - d);
890  } else if (delta < 0) {
891  int growlimit = 0;
892  for (int i = index + 1; i < list.count(); ++i) {
893  const QLayoutStruct &ls = list.at(i);
894  if (ls.empty)
895  continue;
896  if (ls.maximumSize == QLAYOUTSIZE_MAX) {
897  growlimit = QLAYOUTSIZE_MAX;
898  break;
899  }
900  growlimit += ls.maximumSize - ls.size;
901  }
902  if (-delta > growlimit)
903  delta = -growlimit;
904 
905  int d = 0;
906  for (int i = index; d < -delta && i >= 0; --i)
907  d += shrink(list[i], -delta - d);
908  delta = -d;
909  d = 0;
910  for (int i = index + 1; d < -delta && i < list.count(); ++i)
911  d += grow(list[i], -delta - d);
912  }
913 
914  // adjust positions
915  bool first = true;
916  for (int i = 0; i < list.size(); ++i) {
917  QLayoutStruct &ls = list[i];
918  if (ls.empty) {
919  ls.pos = pos + (first ? 0 : sep);
920  continue;
921  }
922  if (!first)
923  pos += sep;
924  ls.pos = pos;
925  pos += ls.size;
926  first = false;
927  }
928 
929  return delta;
930 }
931 
933 {
934 #ifndef QT_NO_TABBAR
935  Q_ASSERT(!tabbed);
936 #endif
937 
939  for (int i = 0; i < list.size(); ++i) {
940  const QDockAreaLayoutItem &item = item_list.at(i);
941  QLayoutStruct &ls = list[i];
943  if (item.skip()) {
944  ls.empty = true;
945  } else {
946  const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
947  ls.empty = false;
948  ls.pos = item.pos;
949  ls.size = item.size + separatorSpace;
950  ls.minimumSize = pick(o, item.minimumSize()) + separatorSpace;
951  ls.maximumSize = pick(o, item.maximumSize()) + separatorSpace;
952 
953  }
954  }
955 
956  //the separator space has been added to the size, so we pass 0 as a parameter
957  delta = separatorMoveHelper(list, index, delta, 0 /*separator*/);
958 
959  for (int i = 0; i < list.size(); ++i) {
961  if (item.skip())
962  continue;
963  QLayoutStruct &ls = list[i];
964  const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
965  item.size = ls.size - separatorSpace;
966  item.pos = ls.pos;
967  if (item.subinfo != 0) {
968  item.subinfo->rect = itemRect(i);
969  item.subinfo->fitItems();
970  }
971  }
972 
973  return delta;
974 }
975 
977 {
979  if (item.subinfo == 0)
980  return;
981  if (item.subinfo->item_list.count() > 1)
982  return;
983 
984  if (item.subinfo->item_list.count() == 0) {
985  item_list.removeAt(index);
986  } else if (item.subinfo->item_list.count() == 1) {
987  QDockAreaLayoutItem &child = item.subinfo->item_list.first();
988  if (child.widgetItem != 0) {
989  item.widgetItem = child.widgetItem;
990  delete item.subinfo;
991  item.subinfo = 0;
992  } else if (child.subinfo != 0) {
993  QDockAreaLayoutInfo *tmp = item.subinfo;
994  item.subinfo = child.subinfo;
995  child.subinfo = 0;
996  tmp->item_list.clear();
997  delete tmp;
998  }
999  }
1000 }
1001 
1003 {
1004  Q_ASSERT(!path.isEmpty());
1005 
1006  if (path.count() > 1) {
1007  const int index = path.first();
1009  Q_ASSERT(item.subinfo != 0);
1010  item.subinfo->remove(path.mid(1));
1011  unnest(index);
1012  } else {
1013  int index = path.first();
1014  item_list.removeAt(index);
1015  }
1016 }
1017 
1019 {
1020  Q_ASSERT(!path.isEmpty());
1021 
1022  int index = path.first();
1023  if (index < 0)
1024  index = -index - 1;
1025 
1026  if (path.count() > 1) {
1027  const QDockAreaLayoutItem &item = item_list.at(index);
1028  Q_ASSERT(item.subinfo != 0);
1029  return item.subinfo->plug(path.mid(1));
1030  }
1031 
1033 
1034  Q_ASSERT(item.widgetItem != 0);
1036  item.flags &= ~QDockAreaLayoutItem::GapItem;
1037 
1038  QRect result;
1039 
1040 #ifndef QT_NO_TABBAR
1041  if (tabbed) {
1042  } else
1043 #endif
1044  {
1045  int prev = this->prev(index);
1046  int next = this->next(index);
1047 
1048  if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
1049  item.pos += *sep;
1050  item.size -= *sep;
1051  }
1052  if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1053  item.size -= *sep;
1054 
1055  QPoint pos;
1056  rpick(o, pos) = item.pos;
1057  rperp(o, pos) = perp(o, rect.topLeft());
1058  QSize s;
1059  rpick(o, s) = item.size;
1060  rperp(o, s) = perp(o, rect.size());
1061  result = QRect(pos, s);
1062  }
1063 
1064  return item.widgetItem;
1065 }
1066 
1068 {
1069  Q_ASSERT(!path.isEmpty());
1070 
1071  const int index = path.first();
1072  if (path.count() > 1) {
1073  const QDockAreaLayoutItem &item = item_list.at(index);
1074  Q_ASSERT(item.subinfo != 0);
1075  return item.subinfo->unplug(path.mid(1));
1076  }
1077 
1079  int prev = this->prev(index);
1080  int next = this->next(index);
1081 
1084 
1085 #ifndef QT_NO_TABBAR
1086  if (tabbed) {
1087  } else
1088 #endif
1089  {
1090  if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
1091  item.pos -= *sep;
1092  item.size += *sep;
1093  }
1094  if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1095  item.size += *sep;
1096  }
1097 
1098  return item.widgetItem;
1099 }
1100 
1101 #ifndef QT_NO_TABBAR
1102 
1104 {
1105  if (!tabbed || tabBar == 0)
1106  return 0;
1107 
1108  int index = tabBar->currentIndex();
1109  if (index == -1)
1110  return 0;
1111 
1112  return qvariant_cast<quintptr>(tabBar->tabData(index));
1113 }
1114 
1116 {
1117  setCurrentTabId(reinterpret_cast<quintptr>(widget));
1118 }
1119 
1121 {
1122  if (!tabbed || tabBar == 0)
1123  return;
1124 
1125  for (int i = 0; i < tabBar->count(); ++i) {
1126  if (qvariant_cast<quintptr>(tabBar->tabData(i)) == id) {
1127  tabBar->setCurrentIndex(i);
1128  return;
1129  }
1130  }
1131 }
1132 
1133 #endif // QT_NO_TABBAR
1134 
1136 {
1137  int titleHeight = 0;
1138 
1140  = qobject_cast<QDockWidgetLayout*>(widget->layout());
1141  if(layout != 0 && layout->nativeWindowDeco())
1142  titleHeight = layout->titleHeight();
1143 
1144  QRect result = widget->geometry();
1145  result.adjust(0, -titleHeight, 0, 0);
1146  return result;
1147 }
1148 
1149 bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem)
1150 {
1151  Q_ASSERT(!path.isEmpty());
1152 
1153  bool insert_tabbed = false;
1154  int index = path.first();
1155  if (index < 0) {
1156  insert_tabbed = true;
1157  index = -index - 1;
1158  }
1159 
1160 // dump(qDebug() << "insertGap() before:" << index << tabIndex, *this, QString());
1161 
1162  if (path.count() > 1) {
1164 
1165  if (item.subinfo == 0
1166 #ifndef QT_NO_TABBAR
1167  || (item.subinfo->tabbed && !insert_tabbed)
1168 #endif
1169  ) {
1170 
1171  // this is not yet a nested layout - make it
1172 
1173  QDockAreaLayoutInfo *subinfo = item.subinfo;
1174  QLayoutItem *widgetItem = item.widgetItem;
1175  QPlaceHolderItem *placeHolderItem = item.placeHolderItem;
1176  QRect r = subinfo == 0 ? widgetItem ? dockedGeometry(widgetItem->widget()) : placeHolderItem->topLevelRect : subinfo->rect;
1177 
1179 #ifdef QT_NO_TABBAR
1180  const int tabBarShape = 0;
1181 #endif
1182  QDockAreaLayoutInfo *new_info
1184 
1185  //item become a new top-level
1186  item.subinfo = new_info;
1187  item.widgetItem = 0;
1188  item.placeHolderItem = 0;
1189 
1190  QDockAreaLayoutItem new_item
1191  = widgetItem == 0
1192  ? QDockAreaLayoutItem(subinfo)
1193  : widgetItem ? QDockAreaLayoutItem(widgetItem) : QDockAreaLayoutItem(placeHolderItem);
1194  new_item.size = pick(opposite, r.size());
1195  new_item.pos = pick(opposite, r.topLeft());
1196  new_info->item_list.append(new_item);
1197 #ifndef QT_NO_TABBAR
1198  if (insert_tabbed) {
1199  new_info->tabbed = true;
1200  }
1201 #endif
1202  }
1203 
1204  return item.subinfo->insertGap(path.mid(1), dockWidgetItem);
1205  }
1206 
1207  // create the gap item
1208  QDockAreaLayoutItem gap_item;
1209  gap_item.flags |= QDockAreaLayoutItem::GapItem;
1210  gap_item.widgetItem = dockWidgetItem; // so minimumSize(), maximumSize() and
1211  // sizeHint() will work
1212 #ifndef QT_NO_TABBAR
1213  if (!tabbed)
1214 #endif
1215  {
1216  int prev = this->prev(index);
1217  int next = this->next(index - 1);
1218  // find out how much space we have in the layout
1219  int space = 0;
1220  if (isEmpty()) {
1221  // I am an empty dock area, therefore I am a top-level dock area.
1222  switch (dockPos) {
1223  case QInternal::LeftDock:
1224  case QInternal::RightDock:
1225  if (o == Qt::Vertical) {
1226  // the "size" is the height of the dock area (remember we are empty)
1227  space = pick(Qt::Vertical, rect.size());
1228  } else {
1229  space = pick(Qt::Horizontal, dockWidgetItem->widget()->size());
1230  }
1231  break;
1232  case QInternal::TopDock:
1233  case QInternal::BottomDock:
1234  default:
1235  if (o == Qt::Horizontal) {
1236  // the "size" is width of the dock area
1237  space = pick(Qt::Horizontal, rect.size());
1238  } else {
1239  space = pick(Qt::Vertical, dockWidgetItem->widget()->size());
1240  }
1241  break;
1242  }
1243  } else {
1244  for (int i = 0; i < item_list.count(); ++i) {
1245  const QDockAreaLayoutItem &item = item_list.at(i);
1246  if (item.skip())
1247  continue;
1249  space += item.size - pick(o, item.minimumSize());
1250  }
1251  }
1252 
1253  // find the actual size of the gap
1254  int gap_size = 0;
1255  int sep_size = 0;
1256  if (isEmpty()) {
1257  gap_size = space;
1258  sep_size = 0;
1259  } else {
1260  QRect r = dockedGeometry(dockWidgetItem->widget());
1261  gap_size = pick(o, r.size());
1262  if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem))
1263  sep_size += *sep;
1264  if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1265  sep_size += *sep;
1266  }
1267  if (gap_size + sep_size > space)
1268  gap_size = pick(o, gap_item.minimumSize());
1269  gap_item.size = gap_size + sep_size;
1270  }
1271 
1272  // finally, insert the gap
1273  item_list.insert(index, gap_item);
1274 
1275 // dump(qDebug() << "insertGap() after:" << index << tabIndex, *this, QString());
1276 
1277  return true;
1278 }
1279 
1281 {
1282  for (int i = 0; i < item_list.count(); ++i) {
1283  const QDockAreaLayoutItem &item = item_list.at(i);
1284  if (item.skip())
1285  continue;
1286 
1287 #ifndef QT_NO_TABBAR
1288  if (tabbed && widget == tabBar)
1289  return this;
1290 #endif
1291 
1292  if (item.widgetItem != 0 && item.widgetItem->widget() == widget)
1293  return this;
1294 
1295  if (item.subinfo != 0) {
1296  if (QDockAreaLayoutInfo *result = item.subinfo->info(widget))
1297  return result;
1298  }
1299  }
1300 
1301  return 0;
1302 }
1303 
1305 {
1306  int index = path.first();
1307  if (index < 0)
1308  index = -index - 1;
1309  if (index >= item_list.count())
1310  return this;
1311  if (path.count() == 1 || item_list[index].subinfo == 0)
1312  return this;
1313  return item_list[index].subinfo->info(path.mid(1));
1314 }
1315 
1317 {
1318  const QDockAreaLayoutItem &item = item_list.at(index);
1319 
1320  if (item.skip())
1321  return QRect();
1322 
1323  QRect result;
1324 
1325 #ifndef QT_NO_TABBAR
1326  if (tabbed) {
1327  if (tabId(item) == currentTabId())
1328  result = tabContentRect();
1329  } else
1330 #endif
1331  {
1332  QPoint pos;
1333  rpick(o, pos) = item.pos;
1334  rperp(o, pos) = perp(o, rect.topLeft());
1335  QSize s;
1336  rpick(o, s) = item.size;
1337  rperp(o, s) = perp(o, rect.size());
1338  result = QRect(pos, s);
1339  }
1340 
1341  return result;
1342 }
1343 
1345 {
1346  Q_ASSERT(!path.isEmpty());
1347 
1348  const int index = path.first();
1349  if (path.count() > 1) {
1350  const QDockAreaLayoutItem &item = item_list.at(index);
1351  Q_ASSERT(item.subinfo != 0);
1352  return item.subinfo->itemRect(path.mid(1));
1353  }
1354 
1355  return itemRect(index);
1356 }
1357 
1359 {
1360 #ifndef QT_NO_TABBAR
1361  if (tabbed)
1362  return QRect();
1363 #endif
1364 
1365  const QDockAreaLayoutItem &item = item_list.at(index);
1366  if (item.skip())
1367  return QRect();
1368 
1369  QPoint pos = rect.topLeft();
1370  rpick(o, pos) = item.pos + item.size;
1371  QSize s = rect.size();
1372  rpick(o, s) = *sep;
1373 
1374  return QRect(pos, s);
1375 }
1376 
1378 {
1379  Q_ASSERT(!path.isEmpty());
1380 
1381  const int index = path.first();
1382  if (path.count() > 1) {
1383  const QDockAreaLayoutItem &item = item_list.at(index);
1384  Q_ASSERT(item.subinfo != 0);
1385  return item.subinfo->separatorRect(path.mid(1));
1386  }
1387  return separatorRect(index);
1388 }
1389 
1391 {
1392 #ifndef QT_NO_TABBAR
1393  if (tabbed)
1394  return QList<int>();
1395 #endif
1396 
1397  int pos = pick(o, _pos);
1398 
1399  for (int i = 0; i < item_list.size(); ++i) {
1400  const QDockAreaLayoutItem &item = item_list.at(i);
1401  if (item.skip() || (item.flags & QDockAreaLayoutItem::GapItem))
1402  continue;
1403 
1404  if (item.pos + item.size > pos) {
1405  if (item.subinfo != 0) {
1406  QList<int> result = item.subinfo->findSeparator(_pos);
1407  if (!result.isEmpty()) {
1408  result.prepend(i);
1409  return result;
1410  } else {
1411  return QList<int>();
1412  }
1413  }
1414  }
1415 
1416  int next = this->next(i);
1417  if (next == -1 || (item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
1418  continue;
1419 
1420  QRect sepRect = separatorRect(i);
1421  if (!sepRect.isNull() && *sep == 1)
1422  sepRect.adjust(-2, -2, 2, 2);
1423  //we also make sure we don't find a separator that's not there
1424  if (sepRect.contains(_pos) && !item.hasFixedSize(o)) {
1425  return QList<int>() << i;
1426  }
1427 
1428  }
1429 
1430  return QList<int>();
1431 }
1432 
1434 {
1435  for (int i = 0; i < item_list.size(); ++i) {
1436  const QDockAreaLayoutItem &item = item_list.at(i);
1437 
1438  if (item.subinfo != 0) {
1439  QList<int> result = item.subinfo->indexOfPlaceHolder(objectName);
1440  if (!result.isEmpty()) {
1441  result.prepend(i);
1442  return result;
1443  }
1444  continue;
1445  }
1446 
1447  if (item.placeHolderItem != 0 && item.placeHolderItem->objectName == objectName) {
1448  QList<int> result;
1449  result << i;
1450  return result;
1451  }
1452  }
1453 
1454  return QList<int>();
1455 }
1456 
1458 {
1459  for (int i = 0; i < item_list.size(); ++i) {
1460  const QDockAreaLayoutItem &item = item_list.at(i);
1461 
1462  if (item.placeHolderItem != 0)
1463  continue;
1464 
1465  if (item.subinfo != 0) {
1466  QList<int> result = item.subinfo->indexOf(widget);
1467  if (!result.isEmpty()) {
1468  result.prepend(i);
1469  return result;
1470  }
1471  continue;
1472  }
1473 
1474  if (!(item.flags & QDockAreaLayoutItem::GapItem) && item.widgetItem->widget() == widget) {
1475  QList<int> result;
1476  result << i;
1477  return result;
1478  }
1479  }
1480 
1481  return QList<int>();
1482 }
1483 
1485 {
1487  Q_ASSERT(result != 0);
1488  return result;
1489 }
1490 
1492 {
1493  return perp(o, minimumSize()) == perp(o, maximumSize());
1494 }
1495 
1496 
1497 void QDockAreaLayoutInfo::apply(bool animate)
1498 {
1499  QWidgetAnimator &widgetAnimator = mainWindowLayout()->widgetAnimator;
1500 
1501 #ifndef QT_NO_TABBAR
1502  if (tabbed) {
1503  QRect tab_rect;
1504  QSize tbh = tabBarSizeHint();
1505 
1506  if (!tbh.isNull()) {
1507  switch (tabBarShape) {
1508  case QTabBar::RoundedNorth:
1510  tab_rect = QRect(rect.left(), rect.top(), rect.width(), tbh.height());
1511  break;
1512  case QTabBar::RoundedSouth:
1514  tab_rect = QRect(rect.left(), rect.bottom() - tbh.height() + 1,
1515  rect.width(), tbh.height());
1516  break;
1517  case QTabBar::RoundedEast:
1519  tab_rect = QRect(rect.right() - tbh.width() + 1, rect.top(),
1520  tbh.width(), rect.height());
1521  break;
1522  case QTabBar::RoundedWest:
1524  tab_rect = QRect(rect.left(), rect.top(),
1525  tbh.width(), rect.height());
1526  break;
1527  default:
1528  break;
1529  }
1530  }
1531 
1532  widgetAnimator.animate(tabBar, tab_rect, animate);
1533  }
1534 #endif // QT_NO_TABBAR
1535 
1536  for (int i = 0; i < item_list.size(); ++i) {
1538 
1540  continue;
1541 
1542  if (item.subinfo != 0) {
1543  item.subinfo->apply(animate);
1544  continue;
1545  }
1546 
1547  if (item.skip())
1548  continue;
1549 
1550  Q_ASSERT(item.widgetItem);
1551  QRect r = itemRect(i);
1552  QWidget *w = item.widgetItem->widget();
1553 
1554  QRect geo = w->geometry();
1555  widgetAnimator.animate(w, r, animate);
1556  if (!w->isHidden() && w->window()->isVisible()) {
1558  if (!r.isValid() && geo.right() >= 0 && geo.bottom() >= 0) {
1559  dw->lower();
1560  emit dw->visibilityChanged(false);
1561  } else if (r.isValid()
1562  && (geo.right() < 0 || geo.bottom() < 0)) {
1563  emit dw->visibilityChanged(true);
1564  }
1565  }
1566  }
1567 #ifndef QT_NO_TABBAR
1568  if (*sep == 1)
1570 #endif //QT_NO_TABBAR
1571 }
1572 
1573 static void paintSep(QPainter *p, QWidget *w, const QRect &r, Qt::Orientation o, bool mouse_over)
1574 {
1575  QStyleOption opt(0);
1576  opt.state = QStyle::State_None;
1577  if (w->isEnabled())
1579  if (o != Qt::Horizontal)
1581  if (mouse_over)
1583  opt.rect = r;
1584  opt.palette = w->palette();
1585 
1587 }
1588 
1590 {
1591  QRegion result;
1592 
1593  if (isEmpty())
1594  return result;
1595 #ifndef QT_NO_TABBAR
1596  if (tabbed)
1597  return result;
1598 #endif
1599 
1600  for (int i = 0; i < item_list.count(); ++i) {
1601  const QDockAreaLayoutItem &item = item_list.at(i);
1602 
1603  if (item.skip())
1604  continue;
1605 
1606  int next = this->next(i);
1607 
1608  if (item.subinfo)
1609  result |= item.subinfo->separatorRegion();
1610 
1611  if (next == -1)
1612  break;
1613  result |= separatorRect(i);
1614  }
1615 
1616  return result;
1617 }
1618 
1620  const QRegion &clip,
1621  const QPoint &mouse) const
1622 {
1623  if (isEmpty())
1624  return;
1625 #ifndef QT_NO_TABBAR
1626  if (tabbed)
1627  return;
1628 #endif
1629 
1630  for (int i = 0; i < item_list.count(); ++i) {
1631  const QDockAreaLayoutItem &item = item_list.at(i);
1632 
1633  if (item.skip())
1634  continue;
1635 
1636  int next = this->next(i);
1637  if ((item.flags & QDockAreaLayoutItem::GapItem)
1638  || (next != -1 && (item_list.at(next).flags & QDockAreaLayoutItem::GapItem)))
1639  continue;
1640 
1641  if (item.subinfo) {
1642  if (clip.contains(item.subinfo->rect))
1643  item.subinfo->paintSeparators(p, widget, clip, mouse);
1644  }
1645 
1646  if (next == -1)
1647  break;
1648  QRect r = separatorRect(i);
1649  if (clip.contains(r) && !item.hasFixedSize(o))
1650  paintSep(p, widget, r, o, r.contains(mouse));
1651  }
1652 }
1653 
1655 {
1656  for (int i = index + 1; i < item_list.size(); ++i) {
1657  if (!item_list.at(i).skip())
1658  return i;
1659  }
1660  return -1;
1661 }
1662 
1664 {
1665  for (int i = index - 1; i >= 0; --i) {
1666  if (!item_list.at(i).skip())
1667  return i;
1668  }
1669  return -1;
1670 }
1671 
1672 void QDockAreaLayoutInfo::tab(int index, QLayoutItem *dockWidgetItem)
1673 {
1674 #ifdef QT_NO_TABBAR
1675  Q_UNUSED(index);
1676  Q_UNUSED(dockWidgetItem);
1677 #else
1678  if (tabbed) {
1679  item_list.append(QDockAreaLayoutItem(dockWidgetItem));
1680  updateTabBar();
1681  setCurrentTab(dockWidgetItem->widget());
1682  } else {
1683  QDockAreaLayoutInfo *new_info
1685  item_list[index].subinfo = new_info;
1686  new_info->item_list.append(item_list.at(index).widgetItem);
1687  item_list[index].widgetItem = 0;
1688  new_info->item_list.append(dockWidgetItem);
1689  new_info->tabbed = true;
1690  new_info->updateTabBar();
1691  new_info->setCurrentTab(dockWidgetItem->widget());
1692  }
1693 #endif // QT_NO_TABBAR
1694 }
1695 
1697  QLayoutItem *dockWidgetItem)
1698 {
1699  if (orientation == o) {
1700  item_list.insert(index + 1, QDockAreaLayoutItem(dockWidgetItem));
1701  } else {
1702 #ifdef QT_NO_TABBAR
1703  const int tabBarShape = 0;
1704 #endif
1705  QDockAreaLayoutInfo *new_info
1706  = new QDockAreaLayoutInfo(sep, dockPos, orientation, tabBarShape, mainWindow);
1707  item_list[index].subinfo = new_info;
1708  new_info->item_list.append(item_list.at(index).widgetItem);
1709  item_list[index].widgetItem = 0;
1710  new_info->item_list.append(dockWidgetItem);
1711  }
1712 }
1713 
1715 {
1716  Q_ASSERT(!path.isEmpty());
1717  const int index = path.first();
1718  if (path.count() > 1) {
1720  Q_ASSERT(item.subinfo != 0);
1721  return item.subinfo->item(path.mid(1));
1722  }
1723  return item_list[index];
1724 }
1725 
1727 {
1728  for (int i = 0; i < item_list.count(); ++i) {
1729  const QDockAreaLayoutItem &item = item_list.at(i);
1730  if (item.placeHolderItem != 0)
1731  continue;
1732  if (item.subinfo) {
1733  if (QLayoutItem *ret = item.subinfo->itemAt(x, index))
1734  return ret;
1735  } else if (item.widgetItem) {
1736  if ((*x)++ == index)
1737  return item.widgetItem;
1738  }
1739  }
1740  return 0;
1741 }
1742 
1744 {
1745  for (int i = 0; i < item_list.count(); ++i) {
1747  if (item.placeHolderItem != 0)
1748  continue;
1749  else if (item.subinfo) {
1750  if (QLayoutItem *ret = item.subinfo->takeAt(x, index)) {
1751  unnest(i);
1752  return ret;
1753  }
1754  } else if (item.widgetItem) {
1755  if ((*x)++ == index) {
1756  item.placeHolderItem = new QPlaceHolderItem(item.widgetItem->widget());
1757  QLayoutItem *ret = item.widgetItem;
1758  item.widgetItem = 0;
1759  if (item.size != -1)
1761  return ret;
1762  }
1763  }
1764  }
1765  return 0;
1766 }
1767 
1769 {
1770  for (int i = 0; i < item_list.count(); ++i) {
1772  if (item.subinfo) {
1773  item.subinfo->deleteAllLayoutItems();
1774  } else {
1775  delete item.widgetItem;
1776  item.widgetItem = 0;
1777  }
1778  }
1779 }
1780 
1782 {
1783 #ifndef QT_NO_TABBAR
1784  if (tabbed) {
1785  stream << (uchar) TabMarker;
1786 
1787  // write the index in item_list of the widget that's currently on top.
1788  quintptr id = currentTabId();
1789  int index = -1;
1790  for (int i = 0; i < item_list.count(); ++i) {
1791  if (tabId(item_list.at(i)) == id) {
1792  index = i;
1793  break;
1794  }
1795  }
1796  stream << index;
1797  } else
1798 #endif // QT_NO_TABBAR
1799  {
1800  stream << (uchar) SequenceMarker;
1801  }
1802 
1803  stream << (uchar) o << item_list.count();
1804 
1805  for (int i = 0; i < item_list.count(); ++i) {
1806  const QDockAreaLayoutItem &item = item_list.at(i);
1807  if (item.widgetItem != 0) {
1808  stream << (uchar) WidgetMarker;
1809  QWidget *w = item.widgetItem->widget();
1810  QString name = w->objectName();
1811  if (name.isEmpty()) {
1812  qWarning("QMainWindow::saveState(): 'objectName' not set for QDockWidget %p '%s;",
1813  w, qPrintable(w->windowTitle()));
1814  }
1815  stream << name;
1816 
1817  uchar flags = 0;
1818  if (!w->isHidden())
1819  flags |= StateFlagVisible;
1820  if (w->isWindow())
1821  flags |= StateFlagFloating;
1822  stream << flags;
1823 
1824  if (w->isWindow()) {
1825  stream << w->x() << w->y() << w->width() << w->height();
1826  } else {
1827  stream << item.pos << item.size << pick(o, item.minimumSize())
1828  << pick(o, item.maximumSize());
1829  }
1830  } else if (item.placeHolderItem != 0) {
1831  stream << (uchar) WidgetMarker;
1832  stream << item.placeHolderItem->objectName;
1833  uchar flags = 0;
1834  if (!item.placeHolderItem->hidden)
1835  flags |= StateFlagVisible;
1836  if (item.placeHolderItem->window)
1837  flags |= StateFlagFloating;
1838  stream << flags;
1839  if (item.placeHolderItem->window) {
1841  stream << r.x() << r.y() << r.width() << r.height();
1842  } else {
1843  stream << item.pos << item.size << (int)0 << (int)0;
1844  }
1845  } else if (item.subinfo != 0) {
1846  stream << (uchar) SequenceMarker << item.pos << item.size << pick(o, item.minimumSize()) << pick(o, item.maximumSize());
1847  item.subinfo->saveState(stream);
1848  }
1849  }
1850 }
1851 
1853 {
1854  switch (pos) {
1859  default: break;
1860  }
1861  return Qt::NoDockWidgetArea;
1862 }
1863 
1864 static QRect constrainedRect(QRect rect, const QRect &desktop)
1865 {
1866  if (desktop.isValid()) {
1867  rect.setWidth(qMin(rect.width(), desktop.width()));
1868  rect.setHeight(qMin(rect.height(), desktop.height()));
1869  rect.moveLeft(qMax(rect.left(), desktop.left()));
1870  rect.moveTop(qMax(rect.top(), desktop.top()));
1871  rect.moveRight(qMin(rect.right(), desktop.right()));
1872  rect.moveBottom(qMin(rect.bottom(), desktop.bottom()));
1873  }
1874 
1875  return rect;
1876 }
1877 
1879 {
1880  uchar marker;
1881  stream >> marker;
1882  if (marker != TabMarker && marker != SequenceMarker)
1883  return false;
1884 
1885 #ifndef QT_NO_TABBAR
1886  tabbed = marker == TabMarker;
1887 
1888  int index = -1;
1889  if (tabbed)
1890  stream >> index;
1891 #endif
1892 
1893  uchar orientation;
1894  stream >> orientation;
1895  o = static_cast<Qt::Orientation>(orientation);
1896 
1897  int cnt;
1898  stream >> cnt;
1899 
1900  for (int i = 0; i < cnt; ++i) {
1901  uchar nextMarker;
1902  stream >> nextMarker;
1903  if (nextMarker == WidgetMarker) {
1904  QString name;
1905  uchar flags;
1906  stream >> name >> flags;
1907  if (name.isEmpty()) {
1908  int dummy;
1909  stream >> dummy >> dummy >> dummy >> dummy;
1910  continue;
1911  }
1912 
1913  QDockWidget *widget = 0;
1914  for (int j = 0; j < widgets.count(); ++j) {
1915  if (widgets.at(j)->objectName() == name) {
1916  widget = widgets.takeAt(j);
1917  break;
1918  }
1919  }
1920 
1921  if (widget == 0) {
1922  QPlaceHolderItem *placeHolder = new QPlaceHolderItem;
1923  QDockAreaLayoutItem item(placeHolder);
1924 
1925  placeHolder->objectName = name;
1926  placeHolder->window = flags & StateFlagFloating;
1927  placeHolder->hidden = !(flags & StateFlagVisible);
1928  if (placeHolder->window) {
1929  int x, y, w, h;
1930  stream >> x >> y >> w >> h;
1931  placeHolder->topLevelRect = QRect(x, y, w, h);
1932  } else {
1933  int dummy;
1934  stream >> item.pos >> item.size >> dummy >> dummy;
1935  }
1936  if (item.size != -1)
1938  if (!testing)
1939  item_list.append(item);
1940  } else {
1942  if (flags & StateFlagFloating) {
1943  bool drawer = false;
1944 #ifdef Q_WS_MAC // drawer support
1945  extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
1946  extern bool qt_mac_set_drawer_preferred_edge(QWidget *, Qt::DockWidgetArea); //qwidget_mac.cpp
1947  drawer = qt_mac_is_macdrawer(widget);
1948 #endif
1949 
1950  if (!testing) {
1951  widget->hide();
1952  if (!drawer)
1953  widget->setFloating(true);
1954  }
1955 
1956  int x, y, w, h;
1957  stream >> x >> y >> w >> h;
1958 
1959 #ifdef Q_WS_MAC // drawer support
1960  if (drawer) {
1962  widget->window()->createWinId();
1964  } else
1965 #endif
1966  if (!testing) {
1967  QRect r(x, y, w, h);
1969  if (desktop->isVirtualDesktop())
1970  r = constrainedRect(r, desktop->screenGeometry(desktop->screenNumber(r.topLeft())));
1971  else
1972  r = constrainedRect(r, desktop->screenGeometry(widget));
1973  widget->move(r.topLeft());
1974  widget->resize(r.size());
1975  }
1976 
1977  if (!testing) {
1978  widget->setVisible(flags & StateFlagVisible);
1979  item_list.append(item);
1980  }
1981  } else {
1982  int dummy;
1983  stream >> item.pos >> item.size >> dummy >> dummy;
1984  if (!testing) {
1985  item_list.append(item);
1986  widget->setFloating(false);
1987  widget->setVisible(flags & StateFlagVisible);
1989  }
1990  }
1991  if (testing) {
1992  //was it is not really added to the layout, we need to delete the object here
1993  delete item.widgetItem;
1994  }
1995  }
1996  } else if (nextMarker == SequenceMarker) {
1997  int dummy;
1998 #ifdef QT_NO_TABBAR
1999  const int tabBarShape = 0;
2000 #endif
2002  tabBarShape, mainWindow));
2003  stream >> item.pos >> item.size >> dummy >> dummy;
2004  //we need to make sure the element is in the list so the dock widget can eventually be docked correctly
2005  if (!testing)
2006  item_list.append(item);
2007 
2008  //here we need to make sure we change the item in the item_list
2009  QDockAreaLayoutItem &lastItem = testing ? item : item_list.last();
2010 
2011  if (!lastItem.subinfo->restoreState(stream, widgets, testing))
2012  return false;
2013 
2014  } else {
2015  return false;
2016  }
2017  }
2018 
2019 #ifndef QT_NO_TABBAR
2020  if (!testing && tabbed && index >= 0 && index < item_list.count()) {
2021  updateTabBar();
2022  setCurrentTabId(tabId(item_list.at(index)));
2023  }
2024  if (!testing && *sep == 1)
2026 #endif
2027 
2028  return true;
2029 }
2030 
2031 #ifndef QT_NO_TABBAR
2033 {
2034  if (tabbed) {
2036  return;
2037  }
2038 
2039  int j = 0;
2040  for (int i = 0; i < item_list.count(); ++i) {
2041  const QDockAreaLayoutItem &item = item_list.at(i);
2042 
2043  if (item.skip())
2044  continue;
2045 
2046  int next = this->next(i);
2047  if ((item.flags & QDockAreaLayoutItem::GapItem)
2048  || (next != -1 && (item_list.at(next).flags & QDockAreaLayoutItem::GapItem)))
2049  continue;
2050 
2051  if (item.subinfo) {
2053  }
2054 
2055  if (next == -1)
2056  break;
2057 
2058  QWidget *sepWidget;
2059  if (j < separatorWidgets.size() && separatorWidgets.at(j)) {
2060  sepWidget = separatorWidgets.at(j);
2061  } else {
2062  sepWidget = mainWindowLayout()->getSeparatorWidget();
2063  separatorWidgets.append(sepWidget);
2064  }
2065  j++;
2066 
2067 #ifndef QT_MAC_USE_COCOA
2068  sepWidget->raise();
2069 #endif
2070  QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
2071  sepWidget->setGeometry(sepRect);
2072  sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
2073  sepWidget->show();
2074  }
2075 
2076  for (int k = j; k < separatorWidgets.size(); ++k) {
2077  separatorWidgets[k]->hide();
2078  }
2080  Q_ASSERT(separatorWidgets.size() == j);
2081 }
2082 #endif //QT_NO_TABBAR
2083 
2084 #ifndef QT_NO_TABBAR
2085 //returns whether the tabbar is visible or not
2087 {
2088  if (!tabbed)
2089  return false;
2090 
2091  QDockAreaLayoutInfo *that = const_cast<QDockAreaLayoutInfo*>(this);
2092 
2093  if (that->tabBar == 0) {
2094  that->tabBar = mainWindowLayout()->getTabBar();
2095  that->tabBar->setShape(static_cast<QTabBar::Shape>(tabBarShape));
2096  that->tabBar->setDrawBase(true);
2097  }
2098 
2099  bool blocked = tabBar->blockSignals(true);
2100  bool gap = false;
2101 
2102  int tab_idx = 0;
2103  for (int i = 0; i < item_list.count(); ++i) {
2104  const QDockAreaLayoutItem &item = item_list.at(i);
2105  if (item.skip())
2106  continue;
2107  if (item.flags & QDockAreaLayoutItem::GapItem) {
2108  gap = true;
2109  continue;
2110  }
2111  if (item.widgetItem == 0)
2112  continue;
2113 
2115  QString title = dw->d_func()->fixedWindowTitle;
2116  quintptr id = tabId(item);
2117  if (tab_idx == tabBar->count()) {
2118  tabBar->insertTab(tab_idx, title);
2119 #ifndef QT_NO_TOOLTIP
2120  tabBar->setTabToolTip(tab_idx, title);
2121 #endif
2122  tabBar->setTabData(tab_idx, id);
2123  } else if (qvariant_cast<quintptr>(tabBar->tabData(tab_idx)) != id) {
2124  if (tab_idx + 1 < tabBar->count()
2125  && qvariant_cast<quintptr>(tabBar->tabData(tab_idx + 1)) == id)
2126  tabBar->removeTab(tab_idx);
2127  else {
2128  tabBar->insertTab(tab_idx, title);
2129 #ifndef QT_NO_TOOLTIP
2130  tabBar->setTabToolTip(tab_idx, title);
2131 #endif
2132  tabBar->setTabData(tab_idx, id);
2133  }
2134  }
2135 
2136  if (title != tabBar->tabText(tab_idx)) {
2137  tabBar->setTabText(tab_idx, title);
2138 #ifndef QT_NO_TOOLTIP
2139  tabBar->setTabToolTip(tab_idx, title);
2140 #endif
2141  }
2142 
2143  ++tab_idx;
2144  }
2145 
2146  while (tab_idx < tabBar->count()) {
2147  tabBar->removeTab(tab_idx);
2148  }
2149 
2150  tabBar->blockSignals(blocked);
2151 
2152  //returns if the tabbar is visible or not
2153  return ( (gap ? 1 : 0) + tabBar->count()) > 1;
2154 }
2155 
2157 {
2158  if (shape == tabBarShape)
2159  return;
2160  tabBarShape = shape;
2161  if (tabBar != 0)
2162  tabBar->setShape(static_cast<QTabBar::Shape>(shape));
2163 
2164  for (int i = 0; i < item_list.count(); ++i) {
2166  if (item.subinfo != 0)
2167  item.subinfo->setTabBarShape(shape);
2168  }
2169 }
2170 
2172 {
2173  if (!updateTabBar())
2174  return QSize(0, 0);
2175 
2176  return tabBar->minimumSizeHint();
2177 }
2178 
2180 {
2181  if (!updateTabBar())
2182  return QSize(0, 0);
2183 
2184  return tabBar->sizeHint();
2185 }
2186 
2188 {
2189  QSet<QTabBar*> result;
2190 
2191  if (tabbed) {
2192  updateTabBar();
2193  result.insert(tabBar);
2194  }
2195 
2196  for (int i = 0; i < item_list.count(); ++i) {
2197  const QDockAreaLayoutItem &item = item_list.at(i);
2198  if (item.subinfo != 0)
2199  result += item.subinfo->usedTabBars();
2200  }
2201 
2202  return result;
2203 }
2204 
2205 // returns a set of all used separator widgets for this dockarelayout info
2206 // and all subinfos
2208 {
2209  QSet<QWidget*> result;
2210 
2211  for (int i = 0; i < separatorWidgets.count(); ++i)
2212  result << separatorWidgets.at(i);
2213 
2214  for (int i = 0; i < item_list.count(); ++i) {
2215  const QDockAreaLayoutItem &item = item_list.at(i);
2216  if (item.subinfo != 0)
2217  result += item.subinfo->usedSeparatorWidgets();
2218  }
2219 
2220  return result;
2221 }
2222 
2224 {
2225  if (!tabbed)
2226  return QRect();
2227 
2228  QRect result = rect;
2229  QSize tbh = tabBarSizeHint();
2230 
2231  if (!tbh.isNull()) {
2232  switch (tabBarShape) {
2233  case QTabBar::RoundedNorth:
2235  result.adjust(0, tbh.height(), 0, 0);
2236  break;
2237  case QTabBar::RoundedSouth:
2239  result.adjust(0, 0, 0, -tbh.height());
2240  break;
2241  case QTabBar::RoundedEast:
2243  result.adjust(0, 0, -tbh.width(), 0);
2244  break;
2245  case QTabBar::RoundedWest:
2247  result.adjust(tbh.width(), 0, 0, 0);
2248  break;
2249  default:
2250  break;
2251  }
2252  }
2253 
2254  return result;
2255 }
2256 #endif // QT_NO_TABBAR
2257 
2258 /******************************************************************************
2259 ** QDockAreaLayout
2260 */
2261 
2262 QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : fallbackToSizeHints(true)
2263 {
2264  mainWindow = win;
2266 #ifndef QT_NO_TABBAR
2267  const int tabShape = QTabBar::RoundedSouth;
2268 #else
2269  const int tabShape = 0;
2270 #endif
2279  centralWidgetItem = 0;
2280 
2281 
2286 }
2287 
2289 {
2290  return rect.isValid();
2291 }
2292 
2294 {
2295  stream << (uchar) DockWidgetStateMarker;
2296  int cnt = 0;
2297  for (int i = 0; i < QInternal::DockCount; ++i) {
2298  if (!docks[i].item_list.isEmpty())
2299  ++cnt;
2300  }
2301  stream << cnt;
2302  for (int i = 0; i < QInternal::DockCount; ++i) {
2303  if (docks[i].item_list.isEmpty())
2304  continue;
2305  stream << i << docks[i].rect.size();
2306  docks[i].saveState(stream);
2307  }
2308 
2309  stream << centralWidgetRect.size();
2310 
2311  for (int i = 0; i < 4; ++i)
2312  stream << static_cast<int>(corners[i]);
2313 }
2314 
2315 bool QDockAreaLayout::restoreState(QDataStream &stream, const QList<QDockWidget*> &_dockwidgets, bool testing)
2316 {
2317  QList<QDockWidget*> dockwidgets = _dockwidgets;
2318 
2319  int cnt;
2320  stream >> cnt;
2321  for (int i = 0; i < cnt; ++i) {
2322  int pos;
2323  stream >> pos;
2324  QSize size;
2325  stream >> size;
2326  if (!testing) {
2327  docks[pos].rect = QRect(QPoint(0, 0), size);
2328  }
2329  if (!docks[pos].restoreState(stream, dockwidgets, testing)) {
2331  return false;
2332  }
2333  }
2334 
2335  QSize size;
2336  stream >> size;
2337  centralWidgetRect = QRect(QPoint(0, 0), size);
2338 
2339  bool ok = stream.status() == QDataStream::Ok;
2340 
2341  if (ok) {
2342  int cornerData[4];
2343  for (int i = 0; i < 4; ++i)
2344  stream >> cornerData[i];
2345  if (stream.status() == QDataStream::Ok) {
2346  for (int i = 0; i < 4; ++i)
2347  corners[i] = static_cast<Qt::DockWidgetArea>(cornerData[i]);
2348  }
2349 
2350  if (!testing)
2351  fallbackToSizeHints = false;
2352  }
2353 
2354  return ok;
2355 }
2356 
2358 {
2359  for (int i = 0; i < QInternal::DockCount; ++i) {
2360  QList<int> result = docks[i].indexOfPlaceHolder(objectName);
2361  if (!result.isEmpty()) {
2362  result.prepend(i);
2363  return result;
2364  }
2365  }
2366  return QList<int>();
2367 }
2368 
2370 {
2371  for (int i = 0; i < QInternal::DockCount; ++i) {
2372  QList<int> result = docks[i].indexOf(dockWidget);
2373  if (!result.isEmpty()) {
2374  result.prepend(i);
2375  return result;
2376  }
2377  }
2378  return QList<int>();
2379 }
2380 
2382 {
2383  QMainWindow::DockOptions opts = mainWindow->dockOptions();
2384  bool nestingEnabled = opts & QMainWindow::AllowNestedDocks;
2386 #ifndef QT_NO_TABBAR
2388  || opts & QMainWindow::VerticalTabs)
2390  if (opts & QMainWindow::ForceTabbedDocks)
2392 
2393  if (tabMode == QDockAreaLayoutInfo::ForceTabs)
2394  nestingEnabled = false;
2395 #endif
2396 
2397 
2398  for (int i = 0; i < QInternal::DockCount; ++i) {
2399  const QDockAreaLayoutInfo &info = docks[i];
2400 
2401  if (!info.isEmpty() && info.rect.contains(pos)) {
2402  QList<int> result
2403  = docks[i].gapIndex(pos, nestingEnabled, tabMode);
2404  if (!result.isEmpty())
2405  result.prepend(i);
2406  return result;
2407  }
2408  }
2409 
2410  for (int i = 0; i < QInternal::DockCount; ++i) {
2411  const QDockAreaLayoutInfo &info = docks[i];
2412 
2413  if (info.isEmpty()) {
2414  QRect r;
2415  switch (i) {
2416  case QInternal::LeftDock:
2418  break;
2419  case QInternal::RightDock:
2422  break;
2423  case QInternal::TopDock:
2425  break;
2426  case QInternal::BottomDock:
2429  break;
2430  }
2431  if (r.contains(pos)) {
2432  if (opts & QMainWindow::ForceTabbedDocks && !info.item_list.isEmpty()) {
2433  //in case of ForceTabbedDocks, we pass -1 in order to force the gap to be tabbed
2434  //it mustn't be completely empty otherwise it won't work
2435  return QList<int>() << i << -1 << 0;
2436  } else {
2437  return QList<int>() << i << 0;
2438  }
2439  }
2440  }
2441  }
2442 
2443  return QList<int>();
2444 }
2445 
2447 {
2448  QList<int> result;
2449  for (int i = 0; i < QInternal::DockCount; ++i) {
2450  const QDockAreaLayoutInfo &info = docks[i];
2451  if (info.isEmpty())
2452  continue;
2453  QRect rect = separatorRect(i);
2454  if (!rect.isNull() && sep == 1)
2455  rect.adjust(-2, -2, 2, 2);
2456  if (rect.contains(pos) && !info.hasFixedSize()) {
2457  result << i;
2458  break;
2459  } else if (info.rect.contains(pos)) {
2460  result = docks[i].findSeparator(pos);
2461  if (!result.isEmpty()) {
2462  result.prepend(i);
2463  break;
2464  }
2465  }
2466  }
2467 
2468  return result;
2469 }
2470 
2472 {
2473  for (int i = 0; i < QInternal::DockCount; ++i) {
2474  if (QDockAreaLayoutInfo *result = docks[i].info(widget))
2475  return result;
2476  }
2477 
2478  return 0;
2479 }
2480 
2482 {
2483  Q_ASSERT(!path.isEmpty());
2484  const int index = path.first();
2485  Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2486 
2487  if (path.count() == 1)
2488  return &docks[index];
2489 
2490  return docks[index].info(path.mid(1));
2491 }
2492 
2494 {
2495  return const_cast<QDockAreaLayout*>(this)->info(path);
2496 }
2497 
2499 {
2500  Q_ASSERT(!path.isEmpty());
2501  const int index = path.first();
2502  Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2503  return docks[index].item(path.mid(1));
2504 }
2505 
2507 {
2508  Q_ASSERT(!path.isEmpty());
2509  const int index = path.first();
2510  Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2511  return docks[index].itemRect(path.mid(1));
2512 }
2513 
2515 {
2516  const QDockAreaLayoutInfo &dock = docks[index];
2517  if (dock.isEmpty())
2518  return QRect();
2519  QRect r = dock.rect;
2520  switch (index) {
2521  case QInternal::LeftDock:
2522  return QRect(r.right() + 1, r.top(), sep, r.height());
2523  case QInternal::RightDock:
2524  return QRect(r.left() - sep, r.top(), sep, r.height());
2525  case QInternal::TopDock:
2526  return QRect(r.left(), r.bottom() + 1, r.width(), sep);
2527  case QInternal::BottomDock:
2528  return QRect(r.left(), r.top() - sep, r.width(), sep);
2529  default:
2530  break;
2531  }
2532  return QRect();
2533 }
2534 
2536 {
2537  Q_ASSERT(!path.isEmpty());
2538 
2539  const int index = path.first();
2540  Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2541 
2542  if (path.count() == 1)
2543  return separatorRect(index);
2544  else
2545  return docks[index].separatorRect(path.mid(1));
2546 }
2547 
2548 bool QDockAreaLayout::insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem)
2549 {
2550  Q_ASSERT(!path.isEmpty());
2551  const int index = path.first();
2552  Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2553  return docks[index].insertGap(path.mid(1), dockWidgetItem);
2554 }
2555 
2557 {
2558  Q_ASSERT(!path.isEmpty());
2559  const int index = path.first();
2560  Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2561  return docks[index].plug(path.mid(1));
2562 }
2563 
2565 {
2566  Q_ASSERT(!path.isEmpty());
2567  const int index = path.first();
2568  Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2569  return docks[index].unplug(path.mid(1));
2570 }
2571 
2573 {
2574  Q_ASSERT(!path.isEmpty());
2575  const int index = path.first();
2576  Q_ASSERT(index >= 0 && index < QInternal::DockCount);
2577  docks[index].remove(path.mid(1));
2578 }
2579 
2580 static inline int qMin(int i1, int i2, int i3) { return qMin(i1, qMin(i2, i3)); }
2581 static inline int qMax(int i1, int i2, int i3) { return qMax(i1, qMax(i2, i3)); }
2582 
2584  QVector<QLayoutStruct> *_hor_struct_list)
2585 {
2586  QSize center_hint(0, 0);
2587  QSize center_min(0, 0);
2588  const bool have_central = centralWidgetItem != 0 && !centralWidgetItem->isEmpty();
2589  if (have_central) {
2590  center_hint = centralWidgetRect.size();
2591  if (!center_hint.isValid())
2592  center_hint = centralWidgetItem->sizeHint();
2593  center_min = centralWidgetItem->minimumSize();
2594  }
2595 
2596  QRect center_rect = rect;
2598  center_rect.setLeft(rect.left() + docks[QInternal::LeftDock].rect.width() + sep);
2600  center_rect.setTop(rect.top() + docks[QInternal::TopDock].rect.height() + sep);
2602  center_rect.setRight(rect.right() - docks[QInternal::RightDock].rect.width() - sep);
2605 
2606  QSize left_hint = docks[QInternal::LeftDock].size();
2607  if (left_hint.isNull() || fallbackToSizeHints)
2608  left_hint = docks[QInternal::LeftDock].sizeHint();
2611  left_hint = left_hint.boundedTo(left_max).expandedTo(left_min);
2612 
2613  QSize right_hint = docks[QInternal::RightDock].size();
2614  if (right_hint.isNull() || fallbackToSizeHints)
2615  right_hint = docks[QInternal::RightDock].sizeHint();
2618  right_hint = right_hint.boundedTo(right_max).expandedTo(right_min);
2619 
2620  QSize top_hint = docks[QInternal::TopDock].size();
2621  if (top_hint.isNull() || fallbackToSizeHints)
2622  top_hint = docks[QInternal::TopDock].sizeHint();
2625  top_hint = top_hint.boundedTo(top_max).expandedTo(top_min);
2626 
2627  QSize bottom_hint = docks[QInternal::BottomDock].size();
2628  if (bottom_hint.isNull() || fallbackToSizeHints)
2629  bottom_hint = docks[QInternal::BottomDock].sizeHint();
2630  QSize bottom_min = docks[QInternal::BottomDock].minimumSize();
2631  QSize bottom_max = docks[QInternal::BottomDock].maximumSize();
2632  bottom_hint = bottom_hint.boundedTo(bottom_max).expandedTo(bottom_min);
2633 
2634  fallbackToSizeHints = false;
2635 
2636  if (_ver_struct_list != 0) {
2637  QVector<QLayoutStruct> &ver_struct_list = *_ver_struct_list;
2638  ver_struct_list.resize(3);
2639 
2640  // top --------------------------------------------------
2641  ver_struct_list[0].init();
2642  ver_struct_list[0].stretch = 0;
2643  ver_struct_list[0].sizeHint = top_hint.height();
2644  ver_struct_list[0].minimumSize = top_min.height();
2645  ver_struct_list[0].maximumSize = top_max.height();
2646  ver_struct_list[0].expansive = false;
2647  ver_struct_list[0].empty = docks[QInternal::TopDock].isEmpty();
2648  ver_struct_list[0].pos = docks[QInternal::TopDock].rect.top();
2649  ver_struct_list[0].size = docks[QInternal::TopDock].rect.height();
2650 
2651  // center --------------------------------------------------
2652  ver_struct_list[1].init();
2653  ver_struct_list[1].stretch = center_hint.height();
2654 
2655  bool tl_significant = corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
2657  bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
2659  bool tr_significant = corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
2661  bool br_significant = corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
2663 
2664  int left = (tl_significant && bl_significant) ? left_hint.height() : 0;
2665  int right = (tr_significant && br_significant) ? right_hint.height() : 0;
2666  ver_struct_list[1].sizeHint = qMax(left, center_hint.height(), right);
2667 
2668  left = (tl_significant && bl_significant) ? left_min.height() : 0;
2669  right = (tr_significant && br_significant) ? right_min.height() : 0;
2670  ver_struct_list[1].minimumSize = qMax(left, center_min.height(), right);
2671  ver_struct_list[1].maximumSize = have_central ? QWIDGETSIZE_MAX : 0;
2672  ver_struct_list[1].expansive = have_central;
2673  ver_struct_list[1].empty = docks[QInternal::LeftDock].isEmpty()
2674  && !have_central
2676  ver_struct_list[1].pos = center_rect.top();
2677  ver_struct_list[1].size = center_rect.height();
2678 
2679  // bottom --------------------------------------------------
2680  ver_struct_list[2].init();
2681  ver_struct_list[2].stretch = 0;
2682  ver_struct_list[2].sizeHint = bottom_hint.height();
2683  ver_struct_list[2].minimumSize = bottom_min.height();
2684  ver_struct_list[2].maximumSize = bottom_max.height();
2685  ver_struct_list[2].expansive = false;
2686  ver_struct_list[2].empty = docks[QInternal::BottomDock].isEmpty();
2687  ver_struct_list[2].pos = docks[QInternal::BottomDock].rect.top();
2688  ver_struct_list[2].size = docks[QInternal::BottomDock].rect.height();
2689 
2690  for (int i = 0; i < 3; ++i) {
2691  ver_struct_list[i].sizeHint
2692  = qMax(ver_struct_list[i].sizeHint, ver_struct_list[i].minimumSize);
2693  }
2694  }
2695 
2696  if (_hor_struct_list != 0) {
2697  QVector<QLayoutStruct> &hor_struct_list = *_hor_struct_list;
2698  hor_struct_list.resize(3);
2699 
2700  // left --------------------------------------------------
2701  hor_struct_list[0].init();
2702  hor_struct_list[0].stretch = 0;
2703  hor_struct_list[0].sizeHint = left_hint.width();
2704  hor_struct_list[0].minimumSize = left_min.width();
2705  hor_struct_list[0].maximumSize = left_max.width();
2706  hor_struct_list[0].expansive = false;
2707  hor_struct_list[0].empty = docks[QInternal::LeftDock].isEmpty();
2708  hor_struct_list[0].pos = docks[QInternal::LeftDock].rect.left();
2709  hor_struct_list[0].size = docks[QInternal::LeftDock].rect.width();
2710 
2711  // center --------------------------------------------------
2712  hor_struct_list[1].init();
2713  hor_struct_list[1].stretch = center_hint.width();
2714 
2715  bool tl_significant = corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
2717  bool tr_significant = corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
2719  bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
2721  bool br_significant = corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
2723 
2724  int top = (tl_significant && tr_significant) ? top_hint.width() : 0;
2725  int bottom = (bl_significant && br_significant) ? bottom_hint.width() : 0;
2726  hor_struct_list[1].sizeHint = qMax(top, center_hint.width(), bottom);
2727 
2728  top = (tl_significant && tr_significant) ? top_min.width() : 0;
2729  bottom = (bl_significant && br_significant) ? bottom_min.width() : 0;
2730  hor_struct_list[1].minimumSize = qMax(top, center_min.width(), bottom);
2731 
2732  hor_struct_list[1].maximumSize = have_central ? QWIDGETSIZE_MAX : 0;
2733  hor_struct_list[1].expansive = have_central;
2734  hor_struct_list[1].empty = !have_central;
2735  hor_struct_list[1].pos = center_rect.left();
2736  hor_struct_list[1].size = center_rect.width();
2737 
2738  // right --------------------------------------------------
2739  hor_struct_list[2].init();
2740  hor_struct_list[2].stretch = 0;
2741  hor_struct_list[2].sizeHint = right_hint.width();
2742  hor_struct_list[2].minimumSize = right_min.width();
2743  hor_struct_list[2].maximumSize = right_max.width();
2744  hor_struct_list[2].expansive = false;
2745  hor_struct_list[2].empty = docks[QInternal::RightDock].isEmpty();
2746  hor_struct_list[2].pos = docks[QInternal::RightDock].rect.left();
2747  hor_struct_list[2].size = docks[QInternal::RightDock].rect.width();
2748 
2749  for (int i = 0; i < 3; ++i) {
2750  hor_struct_list[i].sizeHint
2751  = qMax(hor_struct_list[i].sizeHint, hor_struct_list[i].minimumSize);
2752  }
2753  }
2754 }
2755 
2757  QVector<QLayoutStruct> *hor_struct_list)
2758 {
2759 
2760  // top ---------------------------------------------------
2761 
2762  if (!docks[QInternal::TopDock].isEmpty()) {
2764  if (hor_struct_list != 0) {
2767  ? rect.left() : hor_struct_list->at(1).pos);
2770  ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
2771  }
2772  if (ver_struct_list != 0) {
2773  r.setTop(rect.top());
2774  r.setBottom(ver_struct_list->at(1).pos - sep - 1);
2775  }
2778  }
2779 
2780  // bottom ---------------------------------------------------
2781 
2784  if (hor_struct_list != 0) {
2787  ? rect.left() : hor_struct_list->at(1).pos);
2790  ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
2791  }
2792  if (ver_struct_list != 0) {
2793  r.setTop(ver_struct_list->at(2).pos);
2794  r.setBottom(rect.bottom());
2795  }
2798  }
2799 
2800  // left ---------------------------------------------------
2801 
2802  if (!docks[QInternal::LeftDock].isEmpty()) {
2804  if (hor_struct_list != 0) {
2805  r.setLeft(rect.left());
2806  r.setRight(hor_struct_list->at(1).pos - sep - 1);
2807  }
2808  if (ver_struct_list != 0) {
2811  ? rect.top() : ver_struct_list->at(1).pos);
2814  ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
2815  }
2818  }
2819 
2820  // right ---------------------------------------------------
2821 
2824  if (hor_struct_list != 0) {
2825  r.setLeft(hor_struct_list->at(2).pos);
2826  r.setRight(rect.right());
2827  }
2828  if (ver_struct_list != 0) {
2831  ? rect.top() : ver_struct_list->at(1).pos);
2834  ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
2835  }
2838  }
2839 
2840  // center ---------------------------------------------------
2841 
2842  if (hor_struct_list != 0) {
2843  centralWidgetRect.setLeft(hor_struct_list->at(1).pos);
2844  centralWidgetRect.setWidth(hor_struct_list->at(1).size);
2845  }
2846  if (ver_struct_list != 0) {
2847  centralWidgetRect.setTop(ver_struct_list->at(1).pos);
2848  centralWidgetRect.setHeight(ver_struct_list->at(1).size);
2849  }
2850 }
2851 
2853 {
2854  QVector<QLayoutStruct> ver_struct_list(3);
2855  QVector<QLayoutStruct> hor_struct_list(3);
2856  getGrid(&ver_struct_list, &hor_struct_list);
2857 
2858  qGeomCalc(ver_struct_list, 0, 3, rect.top(), rect.height(), sep);
2859  qGeomCalc(hor_struct_list, 0, 3, rect.left(), rect.width(), sep);
2860 
2861  setGrid(&ver_struct_list, &hor_struct_list);
2862 }
2863 
2865 {
2866  for (int i = 0; i < QInternal::DockCount; ++i)
2867  docks[i].clear();
2868 
2869  rect = QRect();
2871 }
2872 
2874 {
2875  int left_sep = 0;
2876  int right_sep = 0;
2877  int top_sep = 0;
2878  int bottom_sep = 0;
2879 
2880  if (centralWidgetItem != 0) {
2881  left_sep = docks[QInternal::LeftDock].isEmpty() ? 0 : sep;
2882  right_sep = docks[QInternal::RightDock].isEmpty() ? 0 : sep;
2883  top_sep = docks[QInternal::TopDock].isEmpty() ? 0 : sep;
2884  bottom_sep = docks[QInternal::BottomDock].isEmpty() ? 0 : sep;
2885  }
2886 
2887  QSize left = docks[QInternal::LeftDock].sizeHint() + QSize(left_sep, 0);
2888  QSize right = docks[QInternal::RightDock].sizeHint() + QSize(right_sep, 0);
2889  QSize top = docks[QInternal::TopDock].sizeHint() + QSize(0, top_sep);
2890  QSize bottom = docks[QInternal::BottomDock].sizeHint() + QSize(0, bottom_sep);
2892 
2893  int row1 = top.width();
2894  int row2 = left.width() + center.width() + right.width();
2895  int row3 = bottom.width();
2896  int col1 = left.height();
2897  int col2 = top.height() + center.height() + bottom.height();
2898  int col3 = right.height();
2899 
2901  row1 += left.width();
2902  else
2903  col1 += top.height();
2904 
2906  row1 += right.width();
2907  else
2908  col3 += top.height();
2909 
2911  row3 += left.width();
2912  else
2913  col1 += bottom.height();
2914 
2916  row3 += right.width();
2917  else
2918  col3 += bottom.height();
2919 
2920  return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
2921 }
2922 
2924 {
2925  int left_sep = 0;
2926  int right_sep = 0;
2927  int top_sep = 0;
2928  int bottom_sep = 0;
2929 
2930  if (centralWidgetItem != 0) {
2931  left_sep = docks[QInternal::LeftDock].isEmpty() ? 0 : sep;
2932  right_sep = docks[QInternal::RightDock].isEmpty() ? 0 : sep;
2933  top_sep = docks[QInternal::TopDock].isEmpty() ? 0 : sep;
2934  bottom_sep = docks[QInternal::BottomDock].isEmpty() ? 0 : sep;
2935  }
2936 
2937  QSize left = docks[QInternal::LeftDock].minimumSize() + QSize(left_sep, 0);
2938  QSize right = docks[QInternal::RightDock].minimumSize() + QSize(right_sep, 0);
2939  QSize top = docks[QInternal::TopDock].minimumSize() + QSize(0, top_sep);
2940  QSize bottom = docks[QInternal::BottomDock].minimumSize() + QSize(0, bottom_sep);
2942 
2943  int row1 = top.width();
2944  int row2 = left.width() + center.width() + right.width();
2945  int row3 = bottom.width();
2946  int col1 = left.height();
2947  int col2 = top.height() + center.height() + bottom.height();
2948  int col3 = right.height();
2949 
2951  row1 += left.width();
2952  else
2953  col1 += top.height();
2954 
2956  row1 += right.width();
2957  else
2958  col3 += top.height();
2959 
2961  row3 += left.width();
2962  else
2963  col1 += bottom.height();
2964 
2966  row3 += right.width();
2967  else
2968  col3 += bottom.height();
2969 
2970  return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
2971 }
2972 
2974 {
2975  QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
2976  if (index.isEmpty())
2977  return false;
2978 
2979  QDockAreaLayoutItem &item = this->item(index);
2980  QPlaceHolderItem *placeHolder = item.placeHolderItem;
2981  Q_ASSERT(placeHolder != 0);
2982 
2983  item.widgetItem = new QDockWidgetItem(dockWidget);
2984 
2985  if (placeHolder->window) {
2986  QDesktopWidget desktop;
2987  QRect r = constrainedRect(placeHolder->topLevelRect, desktop.screenGeometry(dockWidget));
2988  dockWidget->d_func()->setWindowState(true, true, r);
2989  }
2990  dockWidget->setVisible(!placeHolder->hidden);
2991 #ifdef Q_WS_X11
2992  if (placeHolder->window) // gets rid of the X11BypassWindowManager window flag
2993  dockWidget->d_func()->setWindowState(true);
2994 #endif
2995 
2996  item.placeHolderItem = 0;
2997  delete placeHolder;
2998 
2999  return true;
3000 }
3001 
3003  Qt::Orientation orientation)
3004 {
3005  QLayoutItem *dockWidgetItem = new QDockWidgetItem(dockWidget);
3006  QDockAreaLayoutInfo &info = docks[pos];
3007  if (orientation == info.o || info.item_list.count() <= 1) {
3008  // empty dock areas, or dock areas containing exactly one widget can have their orientation
3009  // switched.
3010  info.o = orientation;
3011 
3012  QDockAreaLayoutItem new_item(dockWidgetItem);
3013  info.item_list.append(new_item);
3014 #ifndef QT_NO_TABBAR
3015  if (info.tabbed && !new_item.skip()) {
3016  info.updateTabBar();
3017  info.setCurrentTabId(tabId(new_item));
3018  }
3019 #endif
3020  } else {
3021 #ifndef QT_NO_TABBAR
3022  int tbshape = info.tabBarShape;
3023 #else
3024  int tbshape = 0;
3025 #endif
3026  QDockAreaLayoutInfo new_info(&sep, pos, orientation, tbshape, mainWindow);
3027  new_info.item_list.append(new QDockAreaLayoutInfo(info));
3028  new_info.item_list.append(dockWidgetItem);
3029  info = new_info;
3030  }
3031 
3032  QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
3033  if (!index.isEmpty())
3034  remove(index);
3035 }
3036 
3038 {
3039  QList<int> path = indexOf(first);
3040  if (path.isEmpty())
3041  return;
3042 
3043  QDockAreaLayoutInfo *info = this->info(path);
3044  Q_ASSERT(info != 0);
3045  info->tab(path.last(), new QDockWidgetItem(second));
3046 
3048  if (!index.isEmpty())
3049  remove(index);
3050 }
3051 
3053  QDockWidget *dockWidget,
3054  Qt::Orientation orientation)
3055 {
3056  QList<int> path = indexOf(after);
3057  if (path.isEmpty())
3058  return;
3059 
3060  QDockAreaLayoutInfo *info = this->info(path);
3061  Q_ASSERT(info != 0);
3062  info->split(path.last(), orientation, new QDockWidgetItem(dockWidget));
3063 
3064  QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
3065  if (!index.isEmpty())
3066  remove(index);
3067 }
3068 
3069 void QDockAreaLayout::apply(bool animate)
3070 {
3072 
3073  for (int i = 0; i < QInternal::DockCount; ++i)
3074  docks[i].apply(animate);
3075  if (centralWidgetItem != 0 && !centralWidgetItem->isEmpty()) {
3077  animate);
3078  }
3079 #ifndef QT_NO_TABBAR
3080  if (sep == 1)
3082 #endif //QT_NO_TABBAR
3083 }
3084 
3086  const QRegion &clip,
3087  const QPoint &mouse) const
3088 {
3089  for (int i = 0; i < QInternal::DockCount; ++i) {
3090  const QDockAreaLayoutInfo &dock = docks[i];
3091  if (dock.isEmpty())
3092  continue;
3093  QRect r = separatorRect(i);
3094  if (clip.contains(r) && !dock.hasFixedSize()) {
3095  Qt::Orientation opposite = dock.o == Qt::Horizontal
3097  paintSep(p, widget, r, opposite, r.contains(mouse));
3098  }
3099  if (clip.contains(dock.rect))
3100  dock.paintSeparators(p, widget, clip, mouse);
3101  }
3102 }
3103 
3105 {
3106  QRegion result;
3107 
3108  for (int i = 0; i < QInternal::DockCount; ++i) {
3109  const QDockAreaLayoutInfo &dock = docks[i];
3110  if (dock.isEmpty())
3111  continue;
3112  result |= separatorRect(i);
3113  result |= dock.separatorRegion();
3114  }
3115 
3116  return result;
3117 }
3118 
3119 int QDockAreaLayout::separatorMove(const QList<int> &separator, const QPoint &origin,
3120  const QPoint &dest)
3121 {
3122  int delta = 0;
3123  int index = separator.last();
3124 
3125  if (separator.count() > 1) {
3126  QDockAreaLayoutInfo *info = this->info(separator);
3127  delta = pick(info->o, dest - origin);
3128  if (delta != 0)
3129  delta = info->separatorMove(index, delta);
3130  info->apply(false);
3131  return delta;
3132  }
3133 
3135 
3136  if (index == QInternal::LeftDock || index == QInternal::RightDock)
3137  getGrid(0, &list);
3138  else
3139  getGrid(&list, 0);
3140 
3141  int sep_index = index == QInternal::LeftDock || index == QInternal::TopDock
3142  ? 0 : 1;
3144  ? Qt::Horizontal
3145  : Qt::Vertical;
3146 
3147  delta = pick(o, dest - origin);
3148  delta = separatorMoveHelper(list, sep_index, delta, sep);
3149 
3150  if (index == QInternal::LeftDock || index == QInternal::RightDock)
3151  setGrid(0, &list);
3152  else
3153  setGrid(&list, 0);
3154 
3155  apply(false);
3156 
3157  return delta;
3158 }
3159 
3160 #ifndef QT_NO_TABBAR
3161 // Sets the correct positions for the separator widgets
3162 // Allocates new sepearator widgets with getSeparatorWidget
3164 {
3165  int j = 0;
3166 
3167  for (int i = 0; i < QInternal::DockCount; ++i) {
3168  const QDockAreaLayoutInfo &dock = docks[i];
3169  if (dock.isEmpty())
3170  continue;
3171 
3172  QWidget *sepWidget;
3173  if (j < separatorWidgets.size()) {
3174  sepWidget = separatorWidgets.at(j);
3175  } else {
3177  separatorWidgets.append(sepWidget);
3178  }
3179  j++;
3180 
3181 #ifndef QT_MAC_USE_COCOA
3182  sepWidget->raise();
3183 #endif
3184  QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
3185  sepWidget->setGeometry(sepRect);
3186  sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
3187  sepWidget->show();
3188  }
3189  for (int i = j; i < separatorWidgets.size(); ++i)
3190  separatorWidgets.at(i)->hide();
3191 
3193 }
3194 #endif //QT_NO_TABBAR
3195 
3197 {
3198  Q_ASSERT(x != 0);
3199 
3200  for (int i = 0; i < QInternal::DockCount; ++i) {
3201  const QDockAreaLayoutInfo &dock = docks[i];
3202  if (QLayoutItem *ret = dock.itemAt(x, index))
3203  return ret;
3204  }
3205 
3206  if (centralWidgetItem && (*x)++ == index)
3207  return centralWidgetItem;
3208 
3209  return 0;
3210 }
3211 
3213 {
3214  Q_ASSERT(x != 0);
3215 
3216  for (int i = 0; i < QInternal::DockCount; ++i) {
3217  QDockAreaLayoutInfo &dock = docks[i];
3218  if (QLayoutItem *ret = dock.takeAt(x, index))
3219  return ret;
3220  }
3221 
3222  if (centralWidgetItem && (*x)++ == index) {
3224  centralWidgetItem = 0;
3225  return ret;
3226  }
3227 
3228  return 0;
3229 }
3230 
3232 {
3233  for (int i = 0; i < QInternal::DockCount; ++i)
3235 }
3236 
3237 #ifndef QT_NO_TABBAR
3239 {
3240  QSet<QTabBar*> result;
3241  for (int i = 0; i < QInternal::DockCount; ++i) {
3242  const QDockAreaLayoutInfo &dock = docks[i];
3243  result += dock.usedTabBars();
3244  }
3245  return result;
3246 }
3247 
3248 // Returns the set of all used separator widgets
3250 {
3251  QSet<QWidget*> result;
3252 
3253  for (int i = 0; i < separatorWidgets.count(); ++i)
3254  result << separatorWidgets.at(i);
3255  for (int i = 0; i < QInternal::DockCount; ++i) {
3256  const QDockAreaLayoutInfo &dock = docks[i];
3257  result += dock.usedSeparatorWidgets();
3258  }
3259  return result;
3260 }
3261 #endif
3262 
3264 {
3265  const QDockAreaLayoutInfo *info = this->info(path);
3266  if (info == 0)
3267  return QRect();
3268  const QList<QDockAreaLayoutItem> &item_list = info->item_list;
3269  Qt::Orientation o = info->o;
3270  int index = path.last();
3271  if (index < 0 || index >= item_list.count())
3272  return QRect();
3273  const QDockAreaLayoutItem &item = item_list.at(index);
3274  if (!(item.flags & QDockAreaLayoutItem::GapItem))
3275  return QRect();
3276 
3277  QRect result;
3278 
3279 #ifndef QT_NO_TABBAR
3280  if (info->tabbed) {
3281  result = info->tabContentRect();
3282  } else
3283 #endif
3284  {
3285  int pos = item.pos;
3286  int size = item.size;
3287 
3288  int prev = info->prev(index);
3289  int next = info->next(index);
3290 
3291  if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
3292  pos += sep;
3293  size -= sep;
3294  }
3295  if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
3296  size -= sep;
3297 
3298  QPoint p;
3299  rpick(o, p) = pos;
3300  rperp(o, p) = perp(o, info->rect.topLeft());
3301  QSize s;
3302  rpick(o, s) = size;
3303  rperp(o, s) = perp(o, info->rect.size());
3304 
3305  result = QRect(p, s);
3306  }
3307 
3308  return result;
3309 }
3310 
3312 {
3313  QList<int> path = indexOf(w);
3314  if (path.isEmpty())
3315  return;
3316  QDockAreaLayoutItem &item = this->item(path);
3317  if (item.size != -1)
3319 }
3320 
3322 {
3324  if (isValid())
3325  fitLayout();
3326 }
3327 
3329 
3330 #endif // QT_NO_DOCKWIDGET
void setDrawBase(bool drawTheBase)
Definition: qtabbar.cpp:800
T qobject_cast(QObject *object)
Definition: qobject.h:375
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
double d
Definition: qnumeric_p.h:62
Status status() const
Returns the status of the data stream.
QList< int > indexOf(QWidget *widget) const
QPalette palette
the widget&#39;s palette
Definition: qwidget.h:180
DockOptions dockOptions
the docking behavior of QMainWindow
Definition: qmainwindow.h:81
QSet< QTabBar * > usedTabBars() const
QLayoutItem * unplug(const QList< int > &path)
bool blockSignals(bool b)
If block is true, signals emitted by this object are blocked (i.e., emitting a signal will not invoke...
Definition: qobject.cpp:1406
QList< QDockAreaLayoutItem > item_list
static int separatorMoveHelper(QVector< QLayoutStruct > &list, int index, int delta, int sep)
QRect adjusted(int x1, int y1, int x2, int y2) const
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition: qrect.h:431
bool isNull() const
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition: qrect.h:231
void setHeight(int h)
Sets the height of the rectangle to the given height.
Definition: qrect.h:445
static int realMaxSize(const QDockAreaLayoutInfo &info)
QIntegerForSizeof< void * >::Unsigned quintptr
Definition: qglobal.h:986
void setBottom(int pos)
Sets the bottom edge of the rectangle to the given y coordinate.
Definition: qrect.h:267
static int qMax(int i1, int i2, int i3)
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QPointer< QWidget > widget
QWidget * getSeparatorWidget()
void setWindowState(Qt::WindowStates state)
Sets the window state to windowState.
void moveLeft(int pos)
Moves the rectangle horizontally, leaving the rectangle&#39;s left edge at the given x coordinate...
Definition: qrect.h:350
The QDockWidget class provides a widget that can be docked inside a QMainWindow or floated as a top-l...
Definition: qdockwidget.h:60
QStyle::State state
the style flags that are used when drawing the control
Definition: qstyleoption.h:88
void saveState(QDataStream &stream) const
bool isWindow() const
Returns true if the widget is an independent window, otherwise returns false.
Definition: qwidget.h:945
void tab(int index, QLayoutItem *dockWidgetItem)
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Definition: qvector.h:742
bool expansive(Qt::Orientation o) const
QVector< QWidget * > separatorWidgets
void visibilityChanged(bool visible)
This signal is emitted when the dock widget becomes visible (or invisible).
virtual bool isEmpty() const =0
Implemented in subclasses to return whether this item is empty, i.
bool isVisible() const
Definition: qwidget.h:1005
void init(int stretchFactor=0, int minSize=0)
void dockLocationChanged(Qt::DockWidgetArea area)
This signal is emitted when the dock widget is moved to another dock area, or is moved to a different...
QVariant tabData(int index) const
Returns the data of the tab at position index, or a null variant if index is out of range...
Definition: qtabbar.cpp:1167
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option=0, const QWidget *widget=0) const =0
Returns the value of the given pixel metric.
QSize minimumSizeHint() const
Definition: qtabbar.cpp:1331
QList< int > indexOfPlaceHolder(const QString &objectName) const
int prev(int idx) const
static int & rpick(Qt::Orientation o, QPoint &pos)
#define QWIDGETSIZE_MAX
Defines the maximum size for a QWidget object.
Definition: qwidget.h:1087
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
void moveRight(int pos)
Moves the rectangle horizontally, leaving the rectangle&#39;s right edge at the given x coordinate...
Definition: qrect.h:356
virtual Qt::Orientations expandingDirections() const =0
Returns whether this layout item can make use of more space than sizeHint().
QSize expandedTo(const QSize &) const
Returns a size holding the maximum width and height of this size and the given otherSize.
Definition: qsize.h:187
int left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:240
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
void insert(int i, const T &t)
Inserts value at index position i in the list.
Definition: qlist.h:575
void setCurrentIndex(int index)
Definition: qtabbar.cpp:1238
void remove(const QList< int > &path)
static int grow(QLayoutStruct &ls, int delta)
long ASN1_INTEGER_get ASN1_INTEGER * a
void setStatus(Status status)
Sets the status of the data stream to the status given.
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
The QTabBar class provides a tab bar, e.g.
Definition: qtabbar.h:59
QPlaceHolderItem * placeHolderItem
void setGeometry(int x, int y, int w, int h)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qwidget.h:1017
static int qMin(int i1, int i2, int i3)
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
virtual QSize minimumSize() const =0
Implemented in subclasses to return the minimum size of this item.
int bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:249
The QString class provides a Unicode character string.
Definition: qstring.h:83
void addDockWidget(QInternal::DockPosition pos, QDockWidget *dockWidget, Qt::Orientation orientation)
QRect tabContentRect() const
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
bool empty() const
This function is provided for STL compatibility.
Definition: qvector.h:285
QSize sizeHint() const
em>Reimplemented Function
Definition: qtabbar.cpp:1317
void removeTab(int index)
Removes the tab at position index.
Definition: qtabbar.cpp:902
void moveBottom(int pos)
Moves the rectangle vertically, leaving the rectangle&#39;s bottom edge at the given y coordinate...
Definition: qrect.h:362
static QInternal::DockPosition dockPosHelper(const QRect &rect, const QPoint &_pos, Qt::Orientation o, bool nestingEnabled, QDockAreaLayoutInfo::TabMode tabMode)
QRect separatorRect(int index) const
QSize boundedTo(const QSize &) const
Returns a size holding the minimum width and height of this size and the given otherSize.
Definition: qsize.h:192
int next(int idx) const
Q_CORE_EXPORT QTextStream & right(QTextStream &s)
void setTabText(int index, const QString &text)
Sets the text of the tab at position index to text.
Definition: qtabbar.cpp:1021
quintptr currentTabId() const
bool isValid() const
void updateSeparatorWidgets() const
QList< int > findSeparator(const QPoint &pos) const
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
void resize(int size)
Sets the size of the vector to size.
Definition: qvector.h:342
QStyle * style() const
Definition: qwidget.cpp:2742
QList< T > mid(int pos, int length=-1) const
Returns a list whose elements are copied from this list, starting at position pos.
Definition: qlist.h:637
QSize maximumSize() const
void apply(bool animate)
bool restoreState(QDataStream &stream, QList< QDockWidget *> &widgets, bool testing)
void unnest(int index)
QRect itemRect(int index) const
QSet< QWidget * > usedSeparatorWidgets() const
bool isHidden() const
Returns true if the widget is hidden, otherwise returns false.
Definition: qwidget.h:1008
bool expansive(Qt::Orientation o) const
QLayoutItem * centralWidgetItem
void updateSeparatorWidgets() const
void setCurrentTabId(quintptr id)
QMainWindowLayout * mainWindowLayout() const
QMainWindow * mainWindow
unsigned char uchar
Definition: qglobal.h:994
NSWindow * window
int width() const
Returns the width.
Definition: qsize.h:126
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QRect gapRect(const QList< int > &path) const
The QLayoutItem class provides an abstract item that a QLayout manipulates.
Definition: qlayoutitem.h:64
static quintptr tabId(const QDockAreaLayoutItem &item)
void lower()
Lowers the widget to the bottom of the parent widget&#39;s stack.
Definition: qwidget.cpp:11939
static FILE * stream
static bool isEmpty(const char *str)
QLayoutItem * takeAt(int *x, int index)
static int shrink(QLayoutStruct &ls, int delta)
void setTabToolTip(int index, const QString &tip)
Sets the tool tip of the tab at position index to tip.
Definition: qtabbar.cpp:1097
void setCurrentTab(QWidget *widget)
QSize sizeHint() const
void getContentsMargins(int *left, int *top, int *right, int *bottom) const
Returns the widget&#39;s contents margins for left, top, right, and bottom.
Definition: qwidget.cpp:7509
void clear()
Removes all the elements from the vector and releases the memory used by the vector.
Definition: qvector.h:347
The QStyleOption class stores the parameters used by QStyle functions.
Definition: qstyleoption.h:67
void raise()
Raises this widget to the top of the parent widget&#39;s stack.
Definition: qwidget.cpp:11901
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
void setTop(int pos)
Sets the top edge of the rectangle to the given y coordinate.
Definition: qrect.h:261
void getGrid(QVector< QLayoutStruct > *ver_struct_list, QVector< QLayoutStruct > *hor_struct_list)
const char * name
int insertTab(int index, const QString &text)
Inserts a new tab with text text at position index.
Definition: qtabbar.cpp:843
QSet< QWidget * > usedSeparatorWidgets() const
void prepend(const T &t)
Inserts value at the beginning of the list.
Definition: qlist.h:541
QSize size() const
Returns the size of the rectangle.
Definition: qrect.h:309
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
const char * layout
void adjust(int x1, int y1, int x2, int y2)
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
Definition: qrect.h:434
void setRight(int pos)
Sets the right edge of the rectangle to the given x coordinate.
Definition: qrect.h:264
bool isVirtualDesktop() const
void setShape(Shape shape)
Definition: qtabbar.cpp:778
void append(const T &t)
Inserts value at the end of the vector.
Definition: qvector.h:573
virtual void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w=0) const =0
Draws the given primitive element with the provided painter using the style options specified by opti...
QDockAreaLayoutInfo * info(const QList< int > &path)
Q_CORE_EXPORT void qWarning(const char *,...)
const_iterator insert(const T &value)
Definition: qset.h:179
bool contains(const QPoint &p) const
Returns true if the region contains the point p; otherwise returns false.
Definition: qregion.cpp:4104
void setTabBarShape(int shape)
QRegion separatorRegion() const
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
QLayoutItem * takeAt(int *x, int index)
int titleHeight() const
QSize size
the size of the widget excluding any window frame
Definition: qwidget.h:165
static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
static void paintSep(QPainter *p, QWidget *w, const QRect &r, Qt::Orientation o, bool mouse_over)
QLayoutItem * itemAt(int *x, int index) const
void clear()
Removes all items from the list.
Definition: qlist.h:764
QList< int > indexOf(QWidget *dockWidget) const
void show()
Shows the widget and its child widgets.
bool restoreDockWidget(QDockWidget *dockWidget)
void setMask(const QBitmap &)
Causes only the pixels of the widget for which bitmap has a corresponding 1 bit to be visible...
Definition: qwidget.cpp:13309
bool contains(const QPoint &p, bool proper=false) const
Returns true if the given point is inside or on the edge of the rectangle, otherwise returns false...
Definition: qrect.cpp:1101
bool isEnabled() const
Definition: qwidget.h:948
virtual void setVisible(bool visible)
Definition: qwidget.cpp:7991
void hide()
Hides the widget.
Definition: qwidget.h:501
QSize maximumSize() const
void saveState(QDataStream &stream) const
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
static int perp(bool vertical, const QSize &size)
QDockAreaLayoutInfo * info(const QList< int > &path)
Q_CORE_EXPORT QTextStream & center(QTextStream &s)
static QDesktopWidget * desktop()
Returns the desktop widget (also called the root window).
void qGeomCalc(QVector< QLayoutStruct > &chain, int start, int count, int pos, int space, int spacer)
QSize tabBarMinimumSize() const
T & first()
Returns a reference to the first item in the list.
Definition: qlist.h:282
QPalette palette
the palette that should be used when painting the control
Definition: qstyleoption.h:92
void setTabData(int index, const QVariant &data)
Sets the data of the tab at position index to data.
Definition: qtabbar.cpp:1156
DockWidgetArea
Definition: qnamespace.h:1337
QLayoutItem * unplug(const QList< int > &path)
bool insertGap(const QList< int > &path, QLayoutItem *dockWidgetItem)
QDockAreaLayoutInfo docks[4]
int top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:243
void keepSize(QDockWidget *w)
const QRect screenGeometry(int screen=-1) const
QVector< QWidget * > separatorWidgets
int right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:246
bool restoreState(QDataStream &stream, const QList< QDockWidget *> &widgets, bool testing=false)
void tabifyDockWidget(QDockWidget *first, QDockWidget *second)
QList< int > findSeparator(const QPoint &pos) const
void resize(int w, int h)
This corresponds to resize(QSize(w, h)).
Definition: qwidget.h:1014
int count
the number of tabs in the tab bar
Definition: qtabbar.h:66
static int realMinSize(const QDockAreaLayoutInfo &info)
QString tabText(int index) const
Returns the text of the tab at position index, or an empty string if index is out of range...
Definition: qtabbar.cpp:1010
void setLeft(int pos)
Sets the left edge of the rectangle to the given x coordinate.
Definition: qrect.h:258
QRect separatorRect(int index) const
void setFloating(bool floating)
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
static QRect constrainedRect(QRect rect, const QRect &desktop)
bool nativeWindowDeco() const
virtual QSize sizeHint() const =0
Implemented in subclasses to return the preferred size of this item.
void paintSeparators(QPainter *p, QWidget *widget, const QRegion &clip, const QPoint &mouse) const
static QRect dockedGeometry(QWidget *widget)
int separatorMove(const QList< int > &separator, const QPoint &origin, const QPoint &dest)
QDockAreaLayoutItem(QLayoutItem *_widgetItem=0)
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
bool hasFixedSize(Qt::Orientation o) const
virtual QSize maximumSize() const =0
Implemented in subclasses to return the maximum size of this item.
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
T & last()
Returns a reference to the last item in the list.
Definition: qlist.h:284
QDockAreaLayoutInfo * subinfo
The QMainWindow class provides a main application window.
Definition: qmainwindow.h:63
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
QMainWindow * mainWindow
void apply(bool animate)
QDockAreaLayoutItem & item(const QList< int > &path)
void splitDockWidget(QDockWidget *after, QDockWidget *dockWidget, Qt::Orientation orientation)
void setWidth(int w)
Sets the width of the rectangle to the given width.
Definition: qrect.h:442
int & rheight()
Returns a reference to the height.
Definition: qsize.h:144
QString objectName() const
int separatorMove(int index, int delta)
int height() const
Returns the height.
Definition: qsize.h:129
if(void) toggleToolbarShown
static const int zero
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
QLayoutItem * itemAt(int *x, int index) const
bool isValid() const
Returns true if both the width and height is equal to or greater than 0; otherwise returns false...
Definition: qsize.h:123
Definition: qnamespace.h:54
QSize minimumSize() const
bool qt_mac_set_drawer_preferred_edge(QWidget *w, Qt::DockWidgetArea where)
Definition: qwidget_mac.mm:321
T qvariant_cast(const QVariant &)
Definition: qvariant.h:571
T takeAt(int i)
Removes the item at index position i and returns it.
Definition: qlist.h:484
QDockAreaLayoutItem & operator=(const QDockAreaLayoutItem &other)
QDockAreaLayout(QMainWindow *win)
QList< int > indexOfPlaceHolder(const QString &objectName) const
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
quint16 index
QWidget * window() const
Returns the window for this widget, i.e.
Definition: qwidget.cpp:4492
void setGrid(QVector< QLayoutStruct > *ver_struct_list, QVector< QLayoutStruct > *hor_struct_list)
QList< int > gapIndex(const QPoint &pos) const
static int pick(bool vertical, const QSize &size)
virtual QWidget * widget()
If this item is a QWidget, it is returned as a QWidget; otherwise 0 is returned.
QWidgetAnimator widgetAnimator
bool isNull() const
Returns true if both the width and height is 0; otherwise returns false.
Definition: qsize.h:117
void createWinId()
Definition: qwidget.cpp:2626
QMainWindowLayout * qt_mainwindow_layout(const QMainWindow *window)
QLayout * layout() const
Returns the layout manager that is installed on this widget, or 0 if no layout manager is installed...
Definition: qwidget.cpp:10073
void paintSeparators(QPainter *p, QWidget *widget, const QRegion &clip, const QPoint &mouse) const
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
int screenNumber(const QWidget *widget=0) const
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:71
static int & rperp(Qt::Orientation o, QPoint &pos)
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
bool insertGap(const QList< int > &path, QLayoutItem *dockWidgetItem)
void moveTop(int pos)
Moves the rectangle vertically, leaving the rectangle&#39;s top edge at the given y coordinate.
Definition: qrect.h:353
QSize tabBarSizeHint() const
bool isValid() const
Returns true if the rectangle is valid, otherwise returns false.
Definition: qrect.h:237
QLayoutItem * plug(const QList< int > &path)
static const int QLAYOUTSIZE_MAX
Definition: qlayoutitem.h:56
QDockAreaLayoutItem & item(const QList< int > &path)
void remove(const QList< int > &path)
QRect itemRect(const QList< int > &path) const
Orientation
Definition: qnamespace.h:174
#define qPrintable(string)
Definition: qglobal.h:1750
Q_CORE_EXPORT QTextStream & left(QTextStream &s)
void split(int index, Qt::Orientation orientation, QLayoutItem *dockWidgetItem)
bool qt_mac_is_macdrawer(const QWidget *w)
Definition: qwidget_mac.mm:306
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition: qwidget.h:158
QRegion separatorRegion() const
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
QRect rect
the area that should be used for various calculations and painting
Definition: qstyleoption.h:90
QInternal::DockPosition dockPos
QLayoutItem * plug(const QList< int > &path)
QSet< QTabBar * > usedTabBars() const
Qt::DockWidgetArea corners[4]
int currentIndex
the index of the tab bar&#39;s visible tab
Definition: qtabbar.h:65
#define QT_NO_TABBAR
int & rwidth()
Returns a reference to the width.
Definition: qsize.h:141
void move(int x, int y)
This corresponds to move(QPoint(x, y)).
Definition: qwidget.h:1011
QList< int > gapIndex(const QPoint &pos, bool nestingEnabled, TabMode tabMode) const
void animate(QWidget *widget, const QRect &final_geometry, bool animate)
QLayoutItem * widgetItem
QPoint topLeft() const
Returns the position of the rectangle&#39;s top-left corner.
Definition: qrect.h:288
QSize minimumSize() const
QSize minimumSize() const
void removeAt(int i)
Removes the item at index position i.
Definition: qlist.h:480