00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "QtGui/qwidget.h"
00025 #include "QtGui/qtabbar.h"
00026 #include "QtGui/qstyle.h"
00027 #include "QtCore/qvariant.h"
00028 #include "qdockwidgetlayout_p.h"
00029 #include "qdockwidget.h"
00030 #include "qmainwindow.h"
00031 #include "qwidgetanimator_p.h"
00032 #include "qmainwindowlayout_p.h"
00033 #include "private/qlayoutengine_p.h"
00034 #include <qdebug.h>
00035
00036 #include <qpainter.h>
00037 #include <qstyleoption.h>
00038
00039 #ifndef QT_NO_DOCKWIDGET
00040
00041 enum { StateFlagVisible = 1, StateFlagFloating = 2 };
00042
00043 static void checkLayoutInfo(const QDockAreaLayoutInfo &info)
00044 {
00045 return;
00046 int pos = pick(info.o, info.rect.topLeft());
00047 bool prev_gap = false;
00048 bool first = true;
00049 for (int i = 0; i < info.item_list.size(); ++i) {
00050 const QDockAreaLayoutItem &item = info.item_list.at(i);
00051 if (item.skip())
00052 continue;
00053
00054 bool gap = item.gap;
00055 if (!first && !gap && !prev_gap)
00056 pos += info.sep;
00057
00058 if (item.pos != pos) {
00059 qDebug() << "##### checkLayoutInfo(): incorrect pos:"
00060 << i << item.pos << pos;
00061 }
00062
00063 pos += item.size;
00064
00065 prev_gap = gap;
00066 first = false;
00067 }
00068
00069 int bottom = pick(info.o, info.rect.bottomRight());
00070 --pos;
00071 if (pos != bottom) {
00072 qDebug() << "##### checkLayoutInfo(): incorrect bottom pos:"
00073 << bottom << pos;
00074 }
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 QDockAreaLayoutItem::QDockAreaLayoutItem(QWidgetItem *_widgetItem)
00133 : widgetItem(_widgetItem), subinfo(0), pos(0), size(-1), gap(false),
00134 keep_size(false)
00135 {
00136 }
00137
00138 QDockAreaLayoutItem::QDockAreaLayoutItem(QDockAreaLayoutInfo *_subinfo)
00139 : widgetItem(0), subinfo(_subinfo), pos(0), size(-1), gap(false),
00140 keep_size(false)
00141 {
00142 }
00143
00144 QDockAreaLayoutItem::QDockAreaLayoutItem(const QDockAreaLayoutItem &other)
00145 : widgetItem(other.widgetItem), subinfo(0), pos(other.pos),
00146 size(other.size), gap(other.gap), keep_size(other.keep_size)
00147 {
00148 if (other.subinfo != 0)
00149 subinfo = new QDockAreaLayoutInfo(*other.subinfo);
00150 Q_ASSERT(widgetItem == 0 || subinfo == 0);
00151 }
00152
00153 QDockAreaLayoutItem::~QDockAreaLayoutItem()
00154 {
00155 delete subinfo;
00156 }
00157
00158 bool QDockAreaLayoutItem::skip() const
00159 {
00160 if (gap)
00161 return false;
00162
00163 if (widgetItem != 0) {
00164 QWidget *widget = widgetItem->widget();
00165 return widget->isWindow() || widget->isHidden();
00166 }
00167
00168 if (subinfo != 0) {
00169 for (int i = 0; i < subinfo->item_list.count(); ++i) {
00170 if (!subinfo->item_list.at(i).skip())
00171 return false;
00172 }
00173 }
00174
00175 return true;
00176 }
00177
00178 static QSize adjustForFrame(QWidget *widget)
00179 {
00180 if (widget->isWindow())
00181 return QSize(0, 0);
00182 int fw = widget->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth);
00183 QSize result(2*fw, fw);
00184 #ifdef Q_OS_WIN
00185 result += QSize(0, 3);
00186 #endif
00187 return result;
00188 }
00189
00190 QSize QDockAreaLayoutItem::minimumSize() const
00191 {
00192 if (widgetItem != 0)
00193 return qSmartMinSize(widgetItem) + adjustForFrame(widgetItem->widget());
00194 if (subinfo != 0)
00195 return subinfo->minimumSize();
00196 return QSize(0, 0);
00197 }
00198
00199 QSize QDockAreaLayoutItem::maximumSize() const
00200 {
00201 if (widgetItem != 0)
00202 return qSmartMaxSize(widgetItem);
00203 if (subinfo != 0)
00204 return subinfo->maximumSize();
00205 return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
00206 }
00207
00208 bool QDockAreaLayoutItem::expansive(Qt::Orientation o) const
00209 {
00210 if (gap)
00211 return false;
00212 if (widgetItem != 0)
00213 return ((widgetItem->expandingDirections() & o) == o);
00214 if (subinfo != 0)
00215 return subinfo->expansive(o);
00216 return false;
00217 }
00218
00219 QSize QDockAreaLayoutItem::sizeHint() const
00220 {
00221 if (widgetItem != 0) {
00222 QWidget *w = widgetItem->widget();
00223 QSize s = w->sizeHint().expandedTo(w->minimumSizeHint());
00224 if (w->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
00225 s.setWidth(0);
00226 if (w->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
00227 s.setHeight(0);
00228 s = s.boundedTo(w->maximumSize())
00229 .expandedTo(w->minimumSize());
00230
00231 s += adjustForFrame(w);
00232 return s;
00233 }
00234 if (subinfo != 0)
00235 return subinfo->sizeHint();
00236 return QSize(-1, -1);
00237 }
00238
00239 QDockAreaLayoutItem
00240 &QDockAreaLayoutItem::operator = (const QDockAreaLayoutItem &other)
00241 {
00242 widgetItem = other.widgetItem;
00243 if (other.subinfo == 0)
00244 subinfo = 0;
00245 else
00246 subinfo = new QDockAreaLayoutInfo(*other.subinfo);
00247 pos = other.pos;
00248 size = other.size;
00249 gap = other.gap;
00250
00251 return *this;
00252 }
00253
00254
00255
00256
00257
00258 static quintptr tabId(const QDockAreaLayoutItem &item)
00259 {
00260 if (item.widgetItem == 0)
00261 return 0;
00262 return reinterpret_cast<quintptr>(item.widgetItem->widget());
00263 }
00264
00265 QDockAreaLayoutInfo::QDockAreaLayoutInfo()
00266 : sep(0), o(Qt::Horizontal), rect(0, 0, -1, -1), mainWindow(0)
00267 #ifndef QT_NO_TABBAR
00268 , tabbed(false), tabBar(0), tabBarShape(-1)
00269 #endif
00270 {
00271 }
00272
00273 QDockAreaLayoutInfo::QDockAreaLayoutInfo(int _sep, Qt::Orientation _o, int tbshape,
00274 QMainWindow *window)
00275 : sep(_sep), o(_o), rect(0, 0, -1, -1), mainWindow(window)
00276 #ifndef QT_NO_TABBAR
00277 , tabbed(false), tabBar(0), tabBarShape(tbshape)
00278 #endif
00279 {
00280 #ifdef QT_NO_TABBAR
00281 Q_UNUSED(tbshape);
00282 #endif
00283 }
00284
00285 QSize QDockAreaLayoutInfo::size() const
00286 {
00287 return isEmpty() ? QSize(0, 0) : rect.size();
00288 }
00289
00290 void QDockAreaLayoutInfo::clear()
00291 {
00292 item_list.clear();
00293 rect = QRect(0, 0, -1, -1);
00294 #ifndef QT_NO_TABBAR
00295 tabbed = false;
00296 tabBar = 0;
00297 #endif
00298 }
00299
00300 bool QDockAreaLayoutInfo::isEmpty() const
00301 {
00302 return next(-1) == -1;
00303 }
00304
00305 QSize QDockAreaLayoutInfo::minimumSize() const
00306 {
00307 if (isEmpty())
00308 return QSize(0, 0);
00309
00310 int a = 0, b = 0;
00311 bool first = true;
00312 for (int i = 0; i < item_list.size(); ++i) {
00313 const QDockAreaLayoutItem &item = item_list.at(i);
00314 if (item.skip())
00315 continue;
00316
00317 QSize min_size = item.minimumSize();
00318 #ifndef QT_NO_TABBAR
00319 if (tabbed) {
00320 a = qMax(a, pick(o, min_size));
00321 } else
00322 #endif
00323 {
00324 if (!first)
00325 a += sep;
00326 a += pick(o, min_size);
00327 }
00328 b = qMax(b, perp(o, min_size));
00329
00330 first = false;
00331 }
00332
00333 QSize result;
00334 rpick(o, result) = a;
00335 rperp(o, result) = b;
00336
00337 #ifndef QT_NO_TABBAR
00338 if (tabbed) {
00339 QSize tbm = tabBarMinimumSize();
00340 switch (tabBarShape) {
00341 case QTabBar::RoundedNorth:
00342 case QTabBar::RoundedSouth:
00343 result.rheight() += tbm.height();
00344 result.rwidth() = qMax(tbm.width(), result.width());
00345 break;
00346 case QTabBar::RoundedEast:
00347 case QTabBar::RoundedWest:
00348 result.rheight() = qMax(tbm.height(), result.height());
00349 result.rwidth() += tbm.width();
00350 break;
00351 default:
00352 break;
00353 }
00354 }
00355 #endif // QT_NO_TABBAR
00356
00357 return result;
00358 }
00359
00360 QSize QDockAreaLayoutInfo::maximumSize() const
00361 {
00362 if (isEmpty())
00363 return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
00364
00365 int a = 0, b = QWIDGETSIZE_MAX;
00366 #ifndef QT_NO_TABBAR
00367 if (tabbed)
00368 a = QWIDGETSIZE_MAX;
00369 #endif
00370
00371 bool first = true;
00372 for (int i = 0; i < item_list.size(); ++i) {
00373 const QDockAreaLayoutItem &item = item_list.at(i);
00374 if (item.skip())
00375 continue;
00376
00377
00378 QSize max_size = item.maximumSize();
00379
00380 #ifndef QT_NO_TABBAR
00381 if (tabbed) {
00382 a = qMin(a, pick(o, max_size));
00383 } else
00384 #endif
00385 {
00386 if (!first)
00387 a += sep;
00388 a += pick(o, max_size);
00389 }
00390 b = qMin(b, perp(o, max_size));
00391
00392 a = qMin(a, int(QWIDGETSIZE_MAX));
00393 b = qMin(b, int(QWIDGETSIZE_MAX));
00394
00395 first = false;
00396 }
00397
00398 QSize result;
00399 rpick(o, result) = a;
00400 rperp(o, result) = b;
00401
00402 #ifndef QT_NO_TABBAR
00403 if (tabbed) {
00404 QSize tbh = tabBarSizeHint();
00405 switch (tabBarShape) {
00406 case QTabBar::RoundedNorth:
00407 case QTabBar::RoundedSouth:
00408 result.rheight() += tbh.height();
00409 break;
00410 case QTabBar::RoundedEast:
00411 case QTabBar::RoundedWest:
00412 result.rwidth() += tbh.width();
00413 break;
00414 default:
00415 break;
00416 }
00417 }
00418 #endif // QT_NO_TABBAR
00419
00420 return result;
00421 }
00422
00423 QSize QDockAreaLayoutInfo::sizeHint() const
00424 {
00425 if (isEmpty())
00426 return QSize(0, 0);
00427
00428 int a = 0, b = 0;
00429 bool prev_gap = false;
00430 bool first = true;
00431 for (int i = 0; i < item_list.size(); ++i) {
00432 const QDockAreaLayoutItem &item = item_list.at(i);
00433 if (item.skip())
00434 continue;
00435
00436 bool gap = item.gap;
00437
00438 QSize size_hint = item.sizeHint();
00439
00440 #ifndef QT_NO_TABBAR
00441 if (tabbed) {
00442 a = qMax(a, gap ? item.size : pick(o, size_hint));
00443 } else
00444 #endif
00445 {
00446 if (!first && !gap && !prev_gap)
00447 a += sep;
00448 a += gap ? item.size : pick(o, size_hint);
00449 }
00450 b = qMax(b, perp(o, size_hint));
00451
00452 prev_gap = gap;
00453 first = false;
00454 }
00455
00456 QSize result;
00457 rpick(o, result) = a;
00458 rperp(o, result) = b;
00459
00460 #ifndef QT_NO_TABBAR
00461 if (tabbed) {
00462 QSize tbh = tabBarSizeHint();
00463 switch (tabBarShape) {
00464 case QTabBar::RoundedNorth:
00465 case QTabBar::RoundedSouth:
00466 result.rheight() += tbh.height();
00467 result.rwidth() = qMax(tbh.width(), result.width());
00468 break;
00469 case QTabBar::RoundedEast:
00470 case QTabBar::RoundedWest:
00471 result.rheight() = qMax(tbh.height(), result.height());
00472 result.rwidth() += tbh.width();
00473 break;
00474 default:
00475 break;
00476 }
00477 }
00478 #endif // QT_NO_TABBAR
00479
00480 return result;
00481 }
00482
00483 bool QDockAreaLayoutInfo::expansive(Qt::Orientation o) const
00484 {
00485 for (int i = 0; i < item_list.size(); ++i) {
00486 if (item_list.at(i).expansive(o))
00487 return true;
00488 }
00489 return false;
00490 }
00491
00492 void QDockAreaLayoutInfo::fitItems()
00493 {
00494 #ifndef QT_NO_TABBAR
00495 if (tabbed) {
00496 return;
00497 }
00498 #endif
00499
00500 QVector<QLayoutStruct> layout_struct_list(item_list.size()*2);
00501 int j = 0;
00502
00503 int size = pick(o, rect.size());
00504 int min_size = pick(o, minimumSize());
00505
00506 bool prev_gap = false;
00507 bool first = true;
00508 for (int i = 0; i < item_list.size(); ++i) {
00509 QDockAreaLayoutItem &item = item_list[i];
00510 if (item.skip())
00511 continue;
00512
00513 bool gap = item.gap;
00514 if (!first && !gap && !prev_gap) {
00515 QLayoutStruct &ls = layout_struct_list[j++];
00516 ls.empty = false;
00517 ls.init();
00518 ls.minimumSize = sep;
00519 ls.maximumSize = sep;
00520 ls.sizeHint = sep;
00521 }
00522
00523 if (item.keep_size) {
00524 int d = item.size - pick(o, item.minimumSize());
00525 if (min_size + d <= size)
00526 min_size -= d;
00527 else
00528 item.keep_size = false;
00529 }
00530
00531 QLayoutStruct &ls = layout_struct_list[j++];
00532 ls.init();
00533 ls.empty = false;
00534 if (gap || item.keep_size) {
00535 ls.minimumSize = ls.maximumSize = ls.sizeHint = item.size;
00536 ls.expansive = false;
00537 ls.stretch = 0;
00538 } else {
00539 ls.minimumSize = pick(o, item.minimumSize());
00540 ls.maximumSize = pick(o, item.maximumSize());
00541 ls.expansive = item.expansive(o);
00542 if (ls.expansive) {
00543 ls.sizeHint = ls.minimumSize;
00544 ls.stretch = item.size == -1 ? pick(o, item.sizeHint()) : item.size;
00545 } else {
00546 ls.sizeHint = item.size == -1 ? pick(o, item.sizeHint()) : item.size;
00547 }
00548 }
00549
00550 item.keep_size = false;
00551 prev_gap = gap;
00552 first = false;
00553 }
00554 layout_struct_list.resize(j);
00555
00556 qGeomCalc(layout_struct_list, 0, j, pick(o, rect.topLeft()), size, 0);
00557
00558 j = 0;
00559 prev_gap = false;
00560 first = true;
00561 for (int i = 0; i < item_list.size(); ++i) {
00562 QDockAreaLayoutItem &item = item_list[i];
00563 if (item.skip())
00564 continue;
00565
00566 bool gap = item.gap;
00567 if (!first && !gap && !prev_gap)
00568 ++j;
00569
00570 const QLayoutStruct &ls = layout_struct_list.at(j++);
00571 item.size = ls.size;
00572 item.pos = ls.pos;
00573
00574 if (item.subinfo != 0) {
00575 item.subinfo->rect = itemRect(i);
00576 item.subinfo->fitItems();
00577 }
00578
00579 prev_gap = gap;
00580 first = false;
00581 }
00582
00583 checkLayoutInfo(*this);
00584 }
00585
00586 static QDockWidgetLayout::DockPos dockPos(const QRect &rect, const QPoint &_pos,
00587 Qt::Orientation o, bool nestingEnabled)
00588 {
00589 QPoint pos = _pos - rect.topLeft();
00590
00591 int x = pos.x();
00592 int y = pos.y();
00593 int w = rect.width();
00594 int h = rect.height();
00595
00596
00597 if (nestingEnabled) {
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 QRect center(w/6, h/6, 2*w/3, 2*h/3);
00608 if (center.contains(pos))
00609 return QDockWidgetLayout::CenterPos;
00610 } else if (o == Qt::Horizontal) {
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 if (x > w/6 && x < w*5/6)
00621 return QDockWidgetLayout::CenterPos;
00622 } else {
00623
00624
00625
00626
00627
00628
00629
00630 if (y > h/6 && y < 5*h/6)
00631 return QDockWidgetLayout::CenterPos;
00632 }
00633
00634
00635 if (nestingEnabled) {
00636 if (o == Qt::Horizontal) {
00637
00638
00639
00640
00641
00642
00643
00644
00645 if (x < w/3)
00646 return QDockWidgetLayout::LeftPos;
00647 if (x > 2*w/3)
00648 return QDockWidgetLayout::RightPos;
00649 if (y < h/2)
00650 return QDockWidgetLayout::TopPos;
00651 return QDockWidgetLayout::BottomPos;
00652 } else {
00653
00654
00655
00656
00657
00658
00659
00660 if (y < h/3)
00661 return QDockWidgetLayout::TopPos;
00662 if (y > 2*h/3)
00663 return QDockWidgetLayout::BottomPos;
00664 if (x < w/2)
00665 return QDockWidgetLayout::LeftPos;
00666 return QDockWidgetLayout::RightPos;
00667 }
00668 } else {
00669 if (o == Qt::Horizontal) {
00670 return x < w/2
00671 ? QDockWidgetLayout::LeftPos
00672 : QDockWidgetLayout::RightPos;
00673 } else {
00674 return y < h/2
00675 ? QDockWidgetLayout::TopPos
00676 : QDockWidgetLayout::BottomPos;
00677 }
00678 }
00679 }
00680
00681 QList<int> QDockAreaLayoutInfo::gapIndex(const QPoint& _pos, bool nestingEnabled) const
00682 {
00683 QList<int> result;
00684 QRect item_rect;
00685 int item_index = 0;
00686
00687 #ifndef QT_NO_TABBAR
00688 if (tabbed) {
00689 item_rect = tabContentRect();
00690 } else
00691 #endif
00692 {
00693 int pos = pick(o, _pos);
00694
00695 int last = -1;
00696 for (int i = 0; i < item_list.size(); ++i) {
00697 const QDockAreaLayoutItem &item = item_list.at(i);
00698 if (item.skip())
00699 continue;
00700
00701 last = i;
00702
00703 if (item.pos + item.size < pos)
00704 continue;
00705
00706 if (item.subinfo != 0
00707 #ifndef QT_NO_TABBAR
00708 && !item.subinfo->tabbed
00709 #endif
00710 ) {
00711 result = item.subinfo->gapIndex(_pos, nestingEnabled);
00712 result.prepend(i);
00713 return result;
00714 }
00715
00716 item_rect = itemRect(i);
00717 item_index = i;
00718 break;
00719 }
00720
00721 if (item_rect.isNull()) {
00722 result.append(last + 1);
00723 return result;
00724 }
00725 }
00726
00727 Q_ASSERT(!item_rect.isNull());
00728
00729 QDockWidgetLayout::DockPos dock_pos
00730 = dockPos(item_rect, _pos, o, nestingEnabled);
00731
00732 switch (dock_pos) {
00733 case QDockWidgetLayout::LeftPos:
00734 if (o == Qt::Horizontal)
00735 result << item_index;
00736 else
00737 result << item_index << 0;
00738
00739 break;
00740 case QDockWidgetLayout::RightPos:
00741 if (o == Qt::Horizontal)
00742 result << item_index + 1;
00743 else
00744 result << item_index << 1;
00745 break;
00746 case QDockWidgetLayout::TopPos:
00747 if (o == Qt::Horizontal)
00748 result << item_index << 0;
00749 else
00750 result << item_index;
00751 break;
00752 case QDockWidgetLayout::BottomPos:
00753 if (o == Qt::Horizontal)
00754 result << item_index << 1;
00755 else
00756 result << item_index + 1;
00757 break;
00758 case QDockWidgetLayout::CenterPos:
00759 result << (-item_index - 1) << 0;
00760
00761
00762 break;
00763 default:
00764 break;
00765 }
00766
00767 return result;
00768 }
00769
00770 static inline int shrink(QLayoutStruct &ls, int delta)
00771 {
00772 if (ls.empty)
00773 return 0;
00774 int old_size = ls.size;
00775 ls.size = qMax(ls.size - delta, ls.minimumSize);
00776 return old_size - ls.size;
00777 }
00778
00779 static inline int grow(QLayoutStruct &ls, int delta)
00780 {
00781 if (ls.empty)
00782 return 0;
00783 int old_size = ls.size;
00784 ls.size = qMin(ls.size + delta, ls.maximumSize);
00785 return ls.size - old_size;
00786 }
00787
00788 static int separatorMove(QVector<QLayoutStruct> &list, int index, int delta, int sep)
00789 {
00790
00791 int pos = -1;
00792 for (int i = 0; i < list.size(); ++i) {
00793 const QLayoutStruct &ls = list.at(i);
00794 if (!ls.empty) {
00795 pos = ls.pos;
00796 break;
00797 }
00798 }
00799 if (pos == -1)
00800 return 0;
00801
00802 if (delta > 0) {
00803 int growlimit = 0;
00804 for (int i = 0; i<=index; ++i) {
00805 const QLayoutStruct &ls = list.at(i);
00806 if (ls.empty)
00807 continue;
00808 if (ls.maximumSize == QLAYOUTSIZE_MAX) {
00809 growlimit = QLAYOUTSIZE_MAX;
00810 break;
00811 }
00812 growlimit += ls.maximumSize - ls.size;
00813 }
00814 if (delta > growlimit)
00815 delta = growlimit;
00816
00817 int d = 0;
00818 for (int i = index + 1; d < delta && i < list.count(); ++i)
00819 d += shrink(list[i], delta - d);
00820 delta = d;
00821 d = 0;
00822 for (int i = index; d < delta && i >= 0; --i)
00823 d += grow(list[i], delta - d);
00824 } else if (delta < 0) {
00825 int growlimit = 0;
00826 for (int i = index + 1; i < list.count(); ++i) {
00827 const QLayoutStruct &ls = list.at(i);
00828 if (ls.empty)
00829 continue;
00830 if (ls.maximumSize == QLAYOUTSIZE_MAX) {
00831 growlimit = QLAYOUTSIZE_MAX;
00832 break;
00833 }
00834 growlimit += ls.maximumSize - ls.size;
00835 }
00836 if (-delta > growlimit)
00837 delta = -growlimit;
00838
00839 int d = 0;
00840 for (int i = index; d < -delta && i >= 0; --i)
00841 d += shrink(list[i], -delta - d);
00842 delta = -d;
00843 d = 0;
00844 for (int i = index + 1; d < -delta && i < list.count(); ++i)
00845 d += grow(list[i], -delta - d);
00846 }
00847
00848
00849 bool first = true;
00850 for (int i = 0; i < list.size(); ++i) {
00851 QLayoutStruct &ls = list[i];
00852 if (ls.empty)
00853 continue;
00854 if (!first)
00855 pos += sep;
00856 ls.pos = pos;
00857 pos += ls.size;
00858 first = false;
00859 }
00860
00861 return delta;
00862 }
00863
00864 int QDockAreaLayoutInfo::separatorMove(int index, int delta, QVector<QLayoutStruct> *cache)
00865 {
00866 Q_ASSERT(!tabbed);
00867
00868 if (cache->isEmpty()) {
00869 QVector<QLayoutStruct> &list = *cache;
00870 list.resize(item_list.size());
00871 for (int i = 0; i < item_list.size(); ++i) {
00872 const QDockAreaLayoutItem &item = item_list.at(i);
00873 QLayoutStruct &ls = list[i];
00874 Q_ASSERT(!item.gap);
00875 if (item.skip()) {
00876 ls.empty = true;
00877 } else {
00878 ls.empty = false;
00879 ls.pos = item.pos;
00880 ls.size = item.size;
00881 ls.minimumSize = pick(o, item.minimumSize());
00882 ls.maximumSize = pick(o, item.maximumSize());
00883 }
00884 }
00885 }
00886
00887 QVector<QLayoutStruct> list = *cache;
00888
00889 delta = ::separatorMove(list, index, delta, sep);
00890
00891 for (int i = 0; i < item_list.size(); ++i) {
00892 QDockAreaLayoutItem &item = item_list[i];
00893 if (item.skip())
00894 continue;
00895 QLayoutStruct &ls = list[i];
00896 item.size = ls.size;
00897 item.pos = ls.pos;
00898
00899 if (item.subinfo != 0) {
00900 item.subinfo->rect = itemRect(i);
00901 item.subinfo->fitItems();
00902 }
00903 }
00904
00905 return delta;
00906 }
00907
00908 void QDockAreaLayoutInfo::unnest(int index)
00909 {
00910 QDockAreaLayoutItem &item = item_list[index];
00911 if (item.subinfo == 0)
00912 return;
00913 if (item.subinfo->item_list.count() > 1)
00914 return;
00915 Q_ASSERT(item.subinfo->item_list.count() != 0);
00916
00917 if (item.subinfo->item_list.count() == 1) {
00918 QDockAreaLayoutItem &child = item.subinfo->item_list.first();
00919 if (child.widgetItem != 0) {
00920 item.widgetItem = child.widgetItem;
00921 delete item.subinfo;
00922 item.subinfo = 0;
00923 } else if (child.subinfo != 0) {
00924 QDockAreaLayoutInfo *tmp = item.subinfo;
00925 item.subinfo = child.subinfo;
00926 child.subinfo = 0;
00927 tmp->item_list.clear();
00928 delete tmp;
00929 }
00930 }
00931 }
00932
00933 void QDockAreaLayoutInfo::remove(QList<int> path)
00934 {
00935 Q_ASSERT(!path.isEmpty());
00936
00937 if (path.count() > 1) {
00938 int index = path.takeFirst();
00939 QDockAreaLayoutItem &item = item_list[index];
00940 Q_ASSERT(item.subinfo != 0);
00941 item.subinfo->remove(path);
00942 unnest(index);
00943 } else {
00944 int index = path.first();
00945 item_list.removeAt(index);
00946 }
00947 }
00948
00949 QRect QDockAreaLayoutInfo::convertToWidget(QList<int> path, QWidgetItem *dockWidgetItem)
00950 {
00951 Q_ASSERT(!path.isEmpty());
00952
00953 int index = path.takeFirst();
00954 if (index < 0)
00955 index = -index - 1;
00956
00957 if (!path.isEmpty()) {
00958 const QDockAreaLayoutItem &item = item_list.at(index);
00959 Q_ASSERT(item.subinfo != 0);
00960 return item.subinfo->convertToWidget(path, dockWidgetItem);
00961 }
00962
00963 QDockAreaLayoutItem &item = item_list[index];
00964
00965 Q_ASSERT(item.gap);
00966 item.gap = false;
00967 Q_ASSERT(item.widgetItem == dockWidgetItem);
00968
00969 QRect result;
00970
00971 #ifndef QT_NO_TABBAR
00972 if (tabbed) {
00973 result = tabContentRect();
00974 } else
00975 #endif
00976 {
00977 int prev = this->prev(index);
00978 int next = this->next(index);
00979
00980 if (prev != -1 && !item_list.at(prev).gap) {
00981 item.pos += sep;
00982 item.size -= sep;
00983 }
00984 if (next != -1 && !item_list.at(next).gap)
00985 item.size -= sep;
00986
00987 QPoint pos;
00988 rpick(o, pos) = item.pos;
00989 rperp(o, pos) = perp(o, rect.topLeft());
00990 QSize s;
00991 rpick(o, s) = item.size;
00992 rperp(o, s) = perp(o, rect.size());
00993 result = QRect(pos, s);
00994 }
00995
00996 return result;
00997 }
00998
00999 QWidgetItem *QDockAreaLayoutInfo::convertToGap(QList<int> path)
01000 {
01001 Q_ASSERT(!path.isEmpty());
01002
01003 if (path.count() > 1) {
01004 int index = path.takeFirst();
01005 const QDockAreaLayoutItem &item = item_list.at(index);
01006 Q_ASSERT(item.subinfo != 0);
01007 QWidgetItem *result = item.subinfo->convertToGap(path);
01008 return result;
01009 }
01010
01011 int index = path.first();
01012 QDockAreaLayoutItem &item = item_list[index];
01013 int prev = this->prev(index);
01014 int next = this->next(index);
01015
01016 Q_ASSERT(!item.gap);
01017 item.gap = true;
01018
01019 #ifndef QT_NO_TABBAR
01020 if (tabbed) {
01021 } else
01022 #endif
01023 {
01024 if (prev != -1 && !item_list.at(prev).gap) {
01025 item.pos -= sep;
01026 item.size += sep;
01027 }
01028 if (next != -1 && !item_list.at(next).gap)
01029 item.size += sep;
01030 }
01031
01032 return item.widgetItem;
01033 }
01034
01035 #ifndef QT_NO_TABBAR
01036
01037 quintptr QDockAreaLayoutInfo::currentTabId() const
01038 {
01039 if (!tabbed || tabBar == 0)
01040 return 0;
01041
01042 int index = tabBar->currentIndex();
01043 if (index == -1)
01044 return 0;
01045
01046 return qvariant_cast<quintptr>(tabBar->tabData(index));
01047 }
01048
01049 void QDockAreaLayoutInfo::setCurrentTab(QWidget *widget)
01050 {
01051 setCurrentTabId(reinterpret_cast<quintptr>(widget));
01052 }
01053
01054 void QDockAreaLayoutInfo::setCurrentTabId(quintptr id)
01055 {
01056 if (!tabbed || tabBar == 0)
01057 return;
01058
01059 for (int i = 0; i < tabBar->count(); ++i) {
01060 if (qvariant_cast<quintptr>(tabBar->tabData(i)) == id) {
01061 tabBar->setCurrentIndex(i);
01062 return;
01063 }
01064 }
01065
01066 qDebug("QDockAreaLayoutInfo::setCurrentTabId(): not found!");
01067 }
01068
01069 #endif // QT_NO_TABBAR
01070
01071 bool QDockAreaLayoutInfo::insertGap(QList<int> path, QWidgetItem *dockWidgetItem)
01072 {
01073 Q_ASSERT(!path.isEmpty());
01074
01075 bool insert_tabbed = false;
01076 int index = path.takeFirst();
01077 if (index < 0) {
01078 insert_tabbed = true;
01079 index = -index - 1;
01080 }
01081
01082
01083
01084 if (!path.isEmpty()) {
01085 QDockAreaLayoutItem &item = item_list[index];
01086
01087 if (item.subinfo == 0
01088 #ifndef QT_NO_TABBAR
01089 || item.subinfo->tabbed && !insert_tabbed
01090 #endif
01091 ) {
01092
01093
01094 QDockAreaLayoutInfo *subinfo = item.subinfo;
01095 QWidgetItem *widgetItem = item.widgetItem;
01096 QRect r = subinfo == 0 ? widgetItem->geometry() : subinfo->rect;
01097
01098 Qt::Orientation opposite = o == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal;
01099 #ifdef QT_NO_TABBAR
01100 const int tabBarShape = 0;
01101 #endif
01102 QDockAreaLayoutInfo *new_info
01103 = new QDockAreaLayoutInfo(sep, opposite, tabBarShape, mainWindow);
01104
01105 item.subinfo = new_info;
01106 item.widgetItem = 0;
01107
01108 QDockAreaLayoutItem new_item
01109 = widgetItem == 0
01110 ? QDockAreaLayoutItem(subinfo)
01111 : QDockAreaLayoutItem(widgetItem);
01112 new_item.size = pick(opposite, r.size());
01113 new_item.pos = pick(opposite, r.topLeft());
01114 new_info->item_list.append(new_item);
01115 #ifndef QT_NO_TABBAR
01116 if (insert_tabbed) {
01117 new_info->tabbed = true;
01118 }
01119 #endif
01120 }
01121
01122 bool result = item.subinfo->insertGap(path, dockWidgetItem);
01123 return result;
01124 }
01125
01126
01127 QDockAreaLayoutItem gap_item;
01128 gap_item.gap = true;
01129 gap_item.widgetItem = dockWidgetItem;
01130
01131 #ifndef QT_NO_TABBAR
01132 if (!tabbed)
01133 #endif
01134 {
01135 int prev = this->prev(index);
01136 int next = this->next(index - 1);
01137
01138 int space = 0;
01139 if (isEmpty()) {
01140 space = pick(o, rect.size());
01141 } else {
01142 for (int i = 0; i < item_list.count(); ++i) {
01143 const QDockAreaLayoutItem &item = item_list.at(i);
01144 if (item.skip())
01145 continue;
01146 Q_ASSERT(!item.gap);
01147 space += item.size - pick(o, item.minimumSize());
01148 }
01149 }
01150
01151
01152 int gap_size = 0;
01153 int sep_size = 0;
01154 if (isEmpty()) {
01155 gap_size = space;
01156 sep_size = 0;
01157 } else {
01158 gap_size = pick(o, dockWidgetItem->geometry().size());
01159 if (prev != -1 && !item_list.at(prev).gap)
01160 sep_size += sep;
01161 if (next != -1 && !item_list.at(next).gap)
01162 sep_size += sep;
01163 }
01164 if (gap_size + sep_size > space)
01165 gap_size = pick(o, gap_item.minimumSize());
01166 gap_item.size = gap_size + sep_size;
01167 }
01168
01169
01170 item_list.insert(index, gap_item);
01171
01172
01173
01174 return true;
01175 }
01176
01177 QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(QWidget *widget)
01178 {
01179 for (int i = 0; i < item_list.count(); ++i) {
01180 const QDockAreaLayoutItem &item = item_list.at(i);
01181 if (item.skip())
01182 continue;
01183
01184 #ifndef QT_NO_TABBAR
01185 if (tabbed && widget == tabBar)
01186 return this;
01187 #endif
01188
01189 if (item.widgetItem != 0 && item.widgetItem->widget() == widget)
01190 return this;
01191
01192 if (item.subinfo != 0) {
01193 if (QDockAreaLayoutInfo *result = item.subinfo->info(widget))
01194 return result;
01195 }
01196 }
01197
01198 return 0;
01199 }
01200
01201 QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(QList<int> path)
01202 {
01203 int index = path.takeFirst();
01204 if (index < 0)
01205 index = -index - 1;
01206 if (index >= item_list.count())
01207 return this;
01208 if (path.isEmpty() || item_list.at(index).subinfo == 0)
01209 return this;
01210 return item_list.at(index).subinfo->info(path);
01211 }
01212
01213 QRect QDockAreaLayoutInfo::itemRect(int index) const
01214 {
01215 const QDockAreaLayoutItem &item = item_list.at(index);
01216
01217 if (item.skip())
01218 return QRect();
01219
01220 QRect result;
01221
01222 #ifndef QT_NO_TABBAR
01223 if (tabbed) {
01224 if (tabId(item) == currentTabId())
01225 result = tabContentRect();
01226 } else
01227 #endif
01228 {
01229 QPoint pos;
01230 rpick(o, pos) = item.pos;
01231 rperp(o, pos) = perp(o, rect.topLeft());
01232 QSize s;
01233 rpick(o, s) = item.size;
01234 rperp(o, s) = perp(o, rect.size());
01235 result = QRect(pos, s);
01236 }
01237
01238 return result;
01239 }
01240
01241 QRect QDockAreaLayoutInfo::itemRect(QList<int> path) const
01242 {
01243 Q_ASSERT(!path.isEmpty());
01244
01245 if (path.count() > 1) {
01246 const QDockAreaLayoutItem &item = item_list.at(path.takeFirst());
01247 Q_ASSERT(item.subinfo != 0);
01248 return item.subinfo->itemRect(path);
01249 }
01250
01251 return itemRect(path.first());
01252 }
01253
01254 QRect QDockAreaLayoutInfo::separatorRect(int index) const
01255 {
01256 #ifndef QT_NO_TABBAR
01257 if (tabbed)
01258 return QRect();
01259 #endif
01260
01261 const QDockAreaLayoutItem &item = item_list.at(index);
01262 if (item.skip())
01263 return QRect();
01264
01265 QPoint pos = rect.topLeft();
01266 rpick(o, pos) = item.pos + item.size;
01267 QSize s = rect.size();
01268 rpick(o, s) = sep;
01269
01270 return QRect(pos, s);
01271 }
01272
01273 QRect QDockAreaLayoutInfo::separatorRect(QList<int> path) const
01274 {
01275 Q_ASSERT(!path.isEmpty());
01276
01277 if (path.count() > 1) {
01278 const QDockAreaLayoutItem &item = item_list.at(path.takeFirst());
01279 Q_ASSERT(item.subinfo != 0);
01280 return item.subinfo->separatorRect(path);
01281 }
01282 return separatorRect(path.first());
01283 }
01284
01285 QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const
01286 {
01287 #ifndef QT_NO_TABBAR
01288 if (tabbed)
01289 return QList<int>();
01290 #endif
01291
01292 int pos = pick(o, _pos);
01293
01294 for (int i = 0; i < item_list.size(); ++i) {
01295 const QDockAreaLayoutItem &item = item_list.at(i);
01296 if (item.skip() || item.gap)
01297 continue;
01298
01299 if (item.pos + item.size > pos) {
01300 if (item.subinfo != 0) {
01301 QList<int> result = item.subinfo->findSeparator(_pos);
01302 if (!result.isEmpty()) {
01303 result.prepend(i);
01304 return result;
01305 } else {
01306 return QList<int>();
01307 }
01308 }
01309 }
01310
01311 int next = this->next(i);
01312 if (next == -1 || item_list.at(next).gap)
01313 continue;
01314
01315 if (pos > item.pos + item.size && item.pos + item.size + sep > pos) {
01316 QList<int> result;
01317 result.append(i);
01318 return result;
01319 }
01320 }
01321
01322 return QList<int>();
01323 }
01324
01325 QList<int> QDockAreaLayoutInfo::indexOf(QWidget *widget, IndexOfFlag flag) const
01326 {
01327 for (int i = 0; i < item_list.size(); ++i) {
01328 const QDockAreaLayoutItem &item = item_list.at(i);
01329
01330 if (item.subinfo != 0) {
01331 QList<int> result = item.subinfo->indexOf(widget, flag);
01332 if (!result.isEmpty()) {
01333 result.prepend(i);
01334 return result;
01335 }
01336 continue;
01337 }
01338
01339 if (flag != IndexOfFindsAll) {
01340 if ((flag == IndexOfFindsVisible) == item.skip())
01341 continue;
01342 }
01343
01344 if (item.widgetItem->widget() == widget) {
01345 QList<int> result;
01346 result << i;
01347 return result;
01348 }
01349 }
01350
01351 return QList<int>();
01352 }
01353
01354 QMainWindowLayout *QDockAreaLayoutInfo::mainWindowLayout() const
01355 {
01356 QMainWindowLayout *result = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
01357 Q_ASSERT(result != 0);
01358 return result;
01359 }
01360
01361 void QDockAreaLayoutInfo::apply(bool animate)
01362 {
01363 QWidgetAnimator *widgetAnimator = mainWindowLayout()->widgetAnimator;
01364
01365 #ifndef QT_NO_TABBAR
01366 if (tabbed) {
01367 QRect tab_rect;
01368 QSize tbh = tabBarSizeHint();
01369
01370 if (tabBarVisible) {
01371 switch (tabBarShape) {
01372 case QTabBar::RoundedNorth:
01373 tab_rect = QRect(rect.left(), rect.top(), rect.width(), tbh.height());
01374 break;
01375 case QTabBar::RoundedSouth:
01376 tab_rect = QRect(rect.left(), rect.bottom() - tbh.height() + 1,
01377 rect.width(), tbh.height());
01378 break;
01379 case QTabBar::RoundedEast:
01380 tab_rect = QRect(rect.right() - tbh.width() + 1, rect.top(),
01381 tbh.width(), rect.height());
01382 break;
01383 case QTabBar::RoundedWest:
01384 tab_rect = QRect(rect.left(), rect.top(),
01385 tbh.width(), rect.height());
01386 break;
01387 default:
01388 break;
01389 }
01390 }
01391
01392 if (tab_rect != tabBar->geometry())
01393 widgetAnimator->animate(tabBar, tab_rect, animate);
01394
01395 }
01396 #endif // QT_NO_TABBAR
01397
01398 for (int i = 0; i < item_list.size(); ++i) {
01399 QDockAreaLayoutItem &item = item_list[i];
01400 if (item.gap || item.skip())
01401 continue;
01402 if (item.subinfo) {
01403 item.subinfo->apply(animate);
01404 } else {
01405 Q_ASSERT(item.widgetItem);
01406 QRect r = itemRect(i);
01407 QWidget *w = item.widgetItem->widget();
01408 widgetAnimator->animate(w, r, animate);
01409 }
01410 }
01411 }
01412
01413 static void paintSep(QPainter *p, QWidget *w, const QRect &r, Qt::Orientation o, bool mouse_over)
01414 {
01415 QStyleOption opt(0);
01416 opt.state = QStyle::State_None;
01417 if (w->isEnabled())
01418 opt.state |= QStyle::State_Enabled;
01419 if (o != Qt::Horizontal)
01420 opt.state |= QStyle::State_Horizontal;
01421 if (mouse_over)
01422 opt.state |= QStyle::State_MouseOver;
01423 opt.rect = r;
01424 opt.palette = w->palette();
01425
01426 w->style()->drawPrimitive(QStyle::PE_IndicatorDockWidgetResizeHandle, &opt, p, w);
01427 }
01428
01429 QRegion QDockAreaLayoutInfo::separatorRegion() const
01430 {
01431 QRegion result;
01432
01433 if (isEmpty())
01434 return result;
01435 #ifndef QT_NO_TABBAR
01436 if (tabbed)
01437 return result;
01438 #endif
01439
01440 for (int i = 0; i < item_list.count(); ++i) {
01441 const QDockAreaLayoutItem &item = item_list.at(i);
01442
01443 if (item.skip())
01444 continue;
01445
01446 int next = this->next(i);
01447
01448 if (item.subinfo)
01449 result |= item.subinfo->separatorRegion();
01450
01451 if (next == -1)
01452 break;
01453 result |= separatorRect(i);
01454 }
01455
01456 return result;
01457 }
01458
01459 void QDockAreaLayoutInfo::paintSeparators(QPainter *p, QWidget *widget,
01460 const QRegion &clip,
01461 const QPoint &mouse) const
01462 {
01463 if (isEmpty())
01464 return;
01465 #ifndef QT_NO_TABBAR
01466 if (tabbed)
01467 return;
01468 #endif
01469
01470 for (int i = 0; i < item_list.count(); ++i) {
01471 const QDockAreaLayoutItem &item = item_list.at(i);
01472
01473 if (item.skip())
01474 continue;
01475
01476 int next = this->next(i);
01477 if (item.gap || next != -1 && item_list.at(next).gap)
01478 continue;
01479
01480 if (item.subinfo) {
01481 if (clip.contains(item.subinfo->rect))
01482 item.subinfo->paintSeparators(p, widget, clip, mouse);
01483 }
01484
01485 if (next == -1)
01486 break;
01487 QRect r = separatorRect(i);
01488 if (clip.contains(r))
01489 paintSep(p, widget, r, o, r.contains(mouse));
01490 }
01491 }
01492
01493 int QDockAreaLayoutInfo::next(int index) const
01494 {
01495 for (int i = index + 1; i < item_list.size(); ++i) {
01496 if (!item_list.at(i).skip())
01497 return i;
01498 }
01499 return -1;
01500 }
01501
01502 int QDockAreaLayoutInfo::prev(int index) const
01503 {
01504 for (int i = index - 1; i >= 0; --i) {
01505 if (!item_list.at(i).skip())
01506 return i;
01507 }
01508 return -1;
01509 }
01510
01511 void QDockAreaLayoutInfo::tab(int index, QWidgetItem *dockWidgetItem)
01512 {
01513 #ifndef QT_NO_TABBAR
01514 if (tabbed) {
01515 item_list.append(QDockAreaLayoutItem(dockWidgetItem));
01516 } else {
01517 QDockAreaLayoutInfo *new_info
01518 = new QDockAreaLayoutInfo(sep, o, tabBarShape, mainWindow);
01519 item_list[index].subinfo = new_info;
01520 new_info->item_list.append(item_list.at(index).widgetItem);
01521 item_list[index].widgetItem = 0;
01522 new_info->item_list.append(dockWidgetItem);
01523 new_info->tabbed = true;
01524 }
01525 #endif // QT_NO_TABBAR
01526 }
01527
01528 void QDockAreaLayoutInfo::split(int index, Qt::Orientation orientation,
01529 QWidgetItem *dockWidgetItem)
01530 {
01531 if (orientation == o) {
01532 item_list.insert(index + 1, QDockAreaLayoutItem(dockWidgetItem));
01533 } else {
01534 #ifdef QT_NO_TABBAR
01535 const int tabBarShape = 0;
01536 #endif
01537 QDockAreaLayoutInfo *new_info
01538 = new QDockAreaLayoutInfo(sep, orientation, tabBarShape, mainWindow);
01539 item_list[index].subinfo = new_info;
01540 new_info->item_list.append(item_list.at(index).widgetItem);
01541 item_list[index].widgetItem = 0;
01542 new_info->item_list.append(dockWidgetItem);
01543 }
01544 }
01545
01546 QDockAreaLayoutItem &QDockAreaLayoutInfo::item(QList<int> path)
01547 {
01548 Q_ASSERT(!path.isEmpty());
01549 if (path.count() > 1) {
01550 QDockAreaLayoutItem &item = item_list[path.takeFirst()];
01551 Q_ASSERT(item.subinfo != 0);
01552 return item.subinfo->item(path);
01553 }
01554 return item_list[path.first()];
01555 }
01556
01557 QLayoutItem *QDockAreaLayoutInfo::itemAt(int *x, int index) const
01558 {
01559 for (int i = 0; i < item_list.count(); ++i) {
01560 const QDockAreaLayoutItem &item = item_list.at(i);
01561 if (item.subinfo) {
01562 if (QLayoutItem *ret = item.subinfo->itemAt(x, index))
01563 return ret;
01564 } else if (item.widgetItem) {
01565 if ((*x)++ == index)
01566 return item.widgetItem;
01567 }
01568 }
01569 return 0;
01570 }
01571
01572 QLayoutItem *QDockAreaLayoutInfo::takeAt(int *x, int index)
01573 {
01574 for (int i = 0; i < item_list.count(); ++i) {
01575 const QDockAreaLayoutItem &item = item_list.at(i);
01576 if (item.subinfo) {
01577 if (QLayoutItem *ret = item.subinfo->takeAt(x, index)) {
01578 unnest(i);
01579 return ret;
01580 }
01581 } else if (item.widgetItem) {
01582 if ((*x)++ == index) {
01583 QLayoutItem *ret = item.widgetItem;
01584 item_list.removeAt(i);
01585 return ret;
01586 }
01587 }
01588 }
01589 return 0;
01590 }
01591
01592 void QDockAreaLayoutInfo::deleteAllLayoutItems()
01593 {
01594 for (int i = 0; i < item_list.count(); ++i) {
01595 QDockAreaLayoutItem &item= item_list[i];
01596 if (item.subinfo) {
01597 item.subinfo->deleteAllLayoutItems();
01598 } else {
01599 delete item.widgetItem;
01600 item.widgetItem = 0;
01601 }
01602 }
01603 }
01604
01605 void QDockAreaLayoutInfo::saveState(QDataStream &stream) const
01606 {
01607 #ifndef QT_NO_TABBAR
01608 if (tabbed) {
01609 stream << (uchar) TabMarker;
01610
01611
01612 quintptr id = currentTabId();
01613 int index = -1;
01614 for (int i = 0; i < item_list.count(); ++i) {
01615 if (tabId(item_list.at(i)) == id) {
01616 index = i;
01617 break;
01618 }
01619 }
01620 stream << index;
01621 } else
01622 #endif // QT_NO_TABBAR
01623 {
01624 stream << (uchar) SequenceMarker;
01625 }
01626
01627 stream << (uchar) o << item_list.count();
01628
01629 for (int i = 0; i < item_list.count(); ++i) {
01630 const QDockAreaLayoutItem &item = item_list.at(i);
01631 if (item.widgetItem != 0) {
01632 stream << (uchar) WidgetMarker;
01633 QWidget *w = item.widgetItem->widget();
01634 QString name = w->objectName();
01635 if (name.isEmpty()) {
01636 qWarning("QMainWindow::saveState(): 'objectName' not set for QDockWidget %p '%s;",
01637 w, qPrintable(w->windowTitle()));
01638 }
01639 stream << name;
01640
01641 uchar flags = 0;
01642 if (!w->isHidden())
01643 flags |= StateFlagVisible;
01644 if (w->isWindow())
01645 flags |= StateFlagFloating;
01646 stream << flags;
01647
01648 if (w->isWindow()) {
01649 stream << w->x() << w->y() << w->width() << w->height();
01650 } else {
01651 stream << item.pos << item.size << pick(o, item.minimumSize())
01652 << pick(o, item.maximumSize());
01653 }
01654 } else if (item.subinfo != 0) {
01655 stream << (uchar) SequenceMarker << item.pos << item.size << pick(o, item.minimumSize()) << pick(o, item.maximumSize());
01656 item.subinfo->saveState(stream);
01657 }
01658 }
01659 }
01660
01661 bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, const QList<QDockWidget*> &widgets)
01662 {
01663 uchar marker;
01664 stream >> marker;
01665 if (marker != TabMarker && marker != SequenceMarker)
01666 return false;
01667
01668 #ifndef QT_NO_TABBAR
01669 tabbed = marker == TabMarker;
01670
01671 int index = -1;
01672 if (tabbed)
01673 stream >> index;
01674 #endif
01675
01676 uchar orientation;
01677 stream >> orientation;
01678 o = static_cast<Qt::Orientation>(orientation);
01679
01680 int cnt;
01681 stream >> cnt;
01682
01683 for (int i = 0; i < cnt; ++i) {
01684 uchar nextMarker;
01685 stream >> nextMarker;
01686 if (nextMarker == WidgetMarker) {
01687 QString name;
01688 uchar flags;
01689 stream >> name >> flags;
01690 if (name.isEmpty()) {
01691 qWarning("QMainWindow::restoreState: Cannot restore "
01692 "a QDockWidget with an empty 'objectName'");
01693 int dummy;
01694 stream >> dummy >> dummy >> dummy >> dummy;
01695 continue;
01696 }
01697
01698 QDockWidget *widget = 0;
01699 for (int j = 0; j < widgets.count(); ++j) {
01700 if (widgets.at(j)->objectName() == name) {
01701 widget = widgets.at(j);
01702 break;
01703 }
01704 }
01705 if (widget == 0) {
01706 qWarning("QMainWindow::restoreState(): cannot find a QDockWidget with "
01707 "matching 'objectName' (looking for \"%s\").",
01708 qPrintable(name));
01709 int dummy;
01710 stream >> dummy >> dummy >> dummy >> dummy;
01711 continue;
01712 }
01713
01714 QDockAreaLayoutItem item(new QWidgetItem(widget));
01715 if (flags & StateFlagFloating) {
01716 widget->hide();
01717 widget->setFloating(true);
01718 int x, y, w, h;
01719 stream >> x >> y >> w >> h;
01720 widget->move(x, y);
01721 widget->resize(w, h);
01722 widget->setVisible(flags & StateFlagVisible);
01723 } else {
01724 int dummy;
01725 stream >> item.pos >> item.size >> dummy >> dummy;
01726 widget->setFloating(false);
01727 widget->setVisible(flags & StateFlagVisible);
01728 }
01729
01730 item_list.append(item);
01731 } else if (nextMarker == SequenceMarker) {
01732 int dummy;
01733 #ifdef QT_NO_TABBAR
01734 const int tabBarShape = 0;
01735 #endif
01736 QDockAreaLayoutInfo *info = new QDockAreaLayoutInfo(sep, o,
01737 tabBarShape, mainWindow);
01738 QDockAreaLayoutItem item(info);
01739 stream >> item.pos >> item.size >> dummy >> dummy;
01740 if (!info->restoreState(stream, widgets))
01741 return false;
01742
01743 item_list.append(item);
01744 } else {
01745 return false;
01746 }
01747 }
01748
01749 #ifndef QT_NO_TABBAR
01750 if (tabbed && index >= 0 && index < item_list.count()) {
01751 updateTabBar();
01752 setCurrentTabId(tabId(item_list.at(index)));
01753 }
01754 #endif
01755
01756 return true;
01757 }
01758
01759 #ifndef QT_NO_TABBAR
01760 void QDockAreaLayoutInfo::updateTabBar() const
01761 {
01762 if (!tabbed)
01763 return;
01764
01765 QDockAreaLayoutInfo *that = const_cast<QDockAreaLayoutInfo*>(this);
01766
01767 if (tabBar == 0) {
01768 that->tabBar = mainWindowLayout()->getTabBar();
01769 that->tabBar->setShape(static_cast<QTabBar::Shape>(tabBarShape));
01770 }
01771
01772 bool blocked = tabBar->blockSignals(true);
01773 bool gap = false;
01774
01775 int tab_idx = 0;
01776 bool changed = false;
01777 for (int i = 0; i < item_list.count(); ++i) {
01778 const QDockAreaLayoutItem &item = item_list.at(i);
01779 if (item.skip())
01780 continue;
01781 if (item.gap) {
01782 gap = true;
01783 continue;
01784 }
01785 if (item.widgetItem == 0)
01786 continue;
01787
01788 QString title = item.widgetItem->widget()->windowTitle();
01789 quintptr id = tabId(item);
01790 if (tab_idx == tabBar->count()) {
01791 tabBar->insertTab(tab_idx, title);
01792 #ifndef QT_NO_TOOLTIP
01793 tabBar->setTabToolTip(tab_idx, title);
01794 #endif
01795 tabBar->setTabData(tab_idx, id);
01796 changed = true;
01797 } else if (qvariant_cast<quintptr>(tabBar->tabData(tab_idx)) != id) {
01798 if (tab_idx + 1 < tabBar->count()
01799 && qvariant_cast<quintptr>(tabBar->tabText(tab_idx + 1)) == id)
01800 tabBar->removeTab(tab_idx);
01801 else {
01802 tabBar->insertTab(tab_idx, title);
01803 #ifndef QT_NO_TOOLTIP
01804 tabBar->setTabToolTip(tab_idx, title);
01805 #endif
01806 tabBar->setTabData(tab_idx, id);
01807 }
01808 changed = true;
01809 }
01810
01811 if (title != tabBar->tabText(tab_idx)) {
01812 tabBar->setTabText(tab_idx, title);
01813 #ifndef QT_NO_TOOLTIP
01814 tabBar->setTabToolTip(tab_idx, title);
01815 #endif
01816 changed = true;
01817 }
01818
01819 ++tab_idx;
01820 }
01821
01822 while (tab_idx < tabBar->count()) {
01823 tabBar->removeTab(tab_idx);
01824 changed = true;
01825 }
01826
01827 tabBar->blockSignals(blocked);
01828
01829 that->tabBarVisible = gap || tabBar->count() > 1;
01830
01831 if (changed) {
01832 that->tabBarMin = tabBar->minimumSizeHint();
01833 that->tabBarHint = tabBar->sizeHint();
01834 }
01835 }
01836
01837 QSize QDockAreaLayoutInfo::tabBarMinimumSize() const
01838 {
01839 if (!tabbed)
01840 return QSize(0, 0);
01841
01842 updateTabBar();
01843
01844 return tabBarMin;
01845 }
01846
01847 QSize QDockAreaLayoutInfo::tabBarSizeHint() const
01848 {
01849 if (!tabbed)
01850 return QSize(0, 0);
01851
01852 updateTabBar();
01853
01854 return tabBarHint;
01855 }
01856
01857 QSet<QTabBar*> QDockAreaLayoutInfo::usedTabBars() const
01858 {
01859 QSet<QTabBar*> result;
01860
01861 if (tabbed) {
01862 updateTabBar();
01863 result.insert(tabBar);
01864 }
01865
01866 for (int i = 0; i < item_list.count(); ++i) {
01867 const QDockAreaLayoutItem &item = item_list.at(i);
01868 if (item.skip())
01869 continue;
01870 if (item.subinfo != 0)
01871 result += item.subinfo->usedTabBars();
01872 }
01873
01874 return result;
01875 }
01876
01877 QRect QDockAreaLayoutInfo::tabContentRect() const
01878 {
01879 if (!tabbed)
01880 return QRect();
01881
01882 QRect result = rect;
01883 QSize tbh = tabBarSizeHint();
01884
01885 if (tabBarVisible) {
01886 switch (tabBarShape) {
01887 case QTabBar::RoundedNorth:
01888 result.adjust(0, tbh.height(), 0, 0);
01889 break;
01890 case QTabBar::RoundedSouth:
01891 result.adjust(0, 0, 0, -tbh.height());
01892 break;
01893 case QTabBar::RoundedEast:
01894 result.adjust(0, 0, -tbh.width(), 0);
01895 break;
01896 case QTabBar::RoundedWest:
01897 result.adjust(tbh.width(), 0, 0, 0);
01898 break;
01899 default:
01900 break;
01901 }
01902 }
01903
01904 return result;
01905 }
01906 #endif // QT_NO_TABBAR
01907
01908
01909
01910
01911
01912 QDockWidgetLayout::QDockWidgetLayout(QMainWindow *win)
01913 {
01914 mainWindow = win;
01915 sep = win->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent);
01916 #ifndef QT_NO_TABBAR
01917 const int tabShape = QTabBar::RoundedSouth;
01918 #else
01919 const int tabShape = 0;
01920 #endif
01921 docks[LeftPos] = QDockAreaLayoutInfo(sep, Qt::Vertical, tabShape, win);
01922 docks[RightPos] = QDockAreaLayoutInfo(sep, Qt::Vertical, tabShape, win);
01923 docks[TopPos] = QDockAreaLayoutInfo(sep, Qt::Horizontal, tabShape, win);
01924 docks[BottomPos] = QDockAreaLayoutInfo(sep, Qt::Horizontal, tabShape, win);
01925 centralWidgetItem = 0;
01926 centralWidgetRect = QRect(0, 0, -1, -1);
01927
01928 corners[Qt::TopLeftCorner] = Qt::TopDockWidgetArea;
01929 corners[Qt::TopRightCorner] = Qt::TopDockWidgetArea;
01930 corners[Qt::BottomLeftCorner] = Qt::BottomDockWidgetArea;
01931 corners[Qt::BottomRightCorner] = Qt::BottomDockWidgetArea;
01932 }
01933
01934 bool QDockWidgetLayout::isValid() const
01935 {
01936 return rect.isValid();
01937 }
01938
01939 void QDockWidgetLayout::saveState(QDataStream &stream) const
01940 {
01941 stream << (uchar) DockWidgetStateMarker;
01942 int cnt = 0;
01943 for (int i = 0; i < PosCount; ++i) {
01944 if (!docks[i].item_list.isEmpty())
01945 ++cnt;
01946 }
01947 stream << cnt;
01948 for (int i = 0; i < PosCount; ++i) {
01949 if (docks[i].item_list.isEmpty())
01950 continue;
01951 stream << i << docks[i].rect.size();
01952 docks[i].saveState(stream);
01953 }
01954
01955 stream << centralWidgetRect.size();
01956
01957 for (int i = 0; i < 4; ++i)
01958 stream << static_cast<int>(corners[i]);
01959 }
01960
01961 bool QDockWidgetLayout::restoreState(QDataStream &stream, const QList<QDockWidget*> &dockwidgets)
01962 {
01963 uchar dmarker;
01964 stream >> dmarker;
01965 if (dmarker != DockWidgetStateMarker)
01966 return false;
01967 int cnt;
01968 stream >> cnt;
01969 for (int i = 0; i < cnt; ++i) {
01970 int pos;
01971 stream >> pos;
01972 QSize size;
01973 stream >> size;
01974 docks[pos].rect = QRect(QPoint(0, 0), size);
01975 if (!docks[pos].restoreState(stream, dockwidgets)) {
01976 stream.setStatus(QDataStream::ReadCorruptData);
01977 return false;
01978 }
01979 }
01980
01981 QSize size;
01982 stream >> size;
01983 centralWidgetRect = QRect(QPoint(0, 0), size);
01984
01985 bool ok = stream.status() == QDataStream::Ok;
01986
01987 if (ok) {
01988 int cornerData[4];
01989 for (int i = 0; i < 4; ++i)
01990 stream >> cornerData[i];
01991 if (stream.status() == QDataStream::Ok) {
01992 for (int i = 0; i < 4; ++i)
01993 corners[i] = static_cast<Qt::DockWidgetArea>(cornerData[i]);
01994 }
01995 }
01996
01997 return ok;
01998 }
01999
02000 QList<int> QDockWidgetLayout::indexOf(QDockWidget *dockWidget, IndexOfFlag flag) const
02001 {
02002 for (int i = 0; i < PosCount; ++i) {
02003 QList<int> result = docks[i].indexOf(dockWidget, flag);
02004 if (!result.isEmpty()) {
02005 result.prepend(i);
02006 return result;
02007 }
02008 }
02009 return QList<int>();
02010 }
02011
02012 QList<int> QDockWidgetLayout::gapIndex(const QPoint &pos, bool nestingEnabled) const
02013 {
02014 for (int i = 0; i < PosCount; ++i) {
02015 const QDockAreaLayoutInfo &info = docks[i];
02016
02017 if (!info.isEmpty() && info.rect.contains(pos)) {
02018 QList<int> result = docks[i].gapIndex(pos, nestingEnabled);
02019 if (!result.isEmpty())
02020 result.prepend(i);
02021 return result;
02022 }
02023 }
02024
02025 for (int i = 0; i < PosCount; ++i) {
02026 const QDockAreaLayoutInfo &info = docks[i];
02027
02028 if (info.isEmpty()) {
02029 QRect r;
02030 switch (i) {
02031 case LeftPos:
02032 r = QRect(rect.left(), rect.top(), EmptyDropAreaSize, rect.height());
02033 break;
02034 case RightPos:
02035 r = QRect(rect.right() - EmptyDropAreaSize, rect.top(),
02036 EmptyDropAreaSize, rect.height());
02037 break;
02038 case TopPos:
02039 r = QRect(rect.left(), rect.top(), rect.width(), EmptyDropAreaSize);
02040 break;
02041 case BottomPos:
02042 r = QRect(rect.left(), rect.bottom() - EmptyDropAreaSize,
02043 rect.width(), EmptyDropAreaSize);
02044 break;
02045 }
02046 if (r.contains(pos))
02047 return QList<int>() << i << 0;
02048 }
02049 }
02050
02051 return QList<int>();
02052 }
02053
02054 QList<int> QDockWidgetLayout::findSeparator(const QPoint &pos) const
02055 {
02056 QList<int> result;
02057 for (int i = 0; i < PosCount; ++i) {
02058 const QDockAreaLayoutInfo &info = docks[i];
02059 if (info.isEmpty())
02060 continue;
02061 if (separatorRect(i).contains(pos)) {
02062 result << i;
02063 break;
02064 } else if (info.rect.contains(pos)) {
02065 result = docks[i].findSeparator(pos);
02066 if (!result.isEmpty()) {
02067 result.prepend(i);
02068 break;
02069 }
02070 }
02071 }
02072
02073 return result;
02074 }
02075
02076 QDockAreaLayoutInfo *QDockWidgetLayout::info(QWidget *widget)
02077 {
02078 for (int i = 0; i < PosCount; ++i) {
02079 if (QDockAreaLayoutInfo *result = docks[i].info(widget))
02080 return result;
02081 }
02082
02083 return 0;
02084 }
02085
02086 QDockAreaLayoutInfo *QDockWidgetLayout::info(QList<int> path)
02087 {
02088 Q_ASSERT(!path.isEmpty());
02089 int index = path.takeFirst();
02090 Q_ASSERT(index >= 0 && index < PosCount);
02091
02092 if (path.isEmpty())
02093 return &docks[index];
02094
02095 return docks[index].info(path);
02096 }
02097
02098 QDockAreaLayoutItem &QDockWidgetLayout::item(QList<int> path)
02099 {
02100 Q_ASSERT(!path.isEmpty());
02101 int index = path.takeFirst();
02102 Q_ASSERT(index >= 0 && index < PosCount);
02103 return docks[index].item(path);
02104 }
02105
02106 QRect QDockWidgetLayout::itemRect(QList<int> path) const
02107 {
02108 Q_ASSERT(!path.isEmpty());
02109 int index = path.takeFirst();
02110 Q_ASSERT(index >= 0 && index < PosCount);
02111 return docks[index].itemRect(path);
02112 }
02113
02114 QRect QDockWidgetLayout::separatorRect(int index) const
02115 {
02116 if (docks[index].isEmpty())
02117 return QRect();
02118 QRect r = docks[index].rect;
02119 switch (index) {
02120 case LeftPos:
02121 return QRect(r.right() + 1, r.top(), sep, r.height());
02122 case RightPos:
02123 return QRect(r.left() - sep, r.top(), sep, r.height());
02124 case TopPos:
02125 return QRect(r.left(), r.bottom() + 1, r.width(), sep);
02126 case BottomPos:
02127 return QRect(r.left(), r.top() - sep, r.width(), sep);
02128 default:
02129 break;
02130 }
02131 return QRect();
02132 }
02133
02134 QRect QDockWidgetLayout::separatorRect(QList<int> path) const
02135 {
02136 Q_ASSERT(!path.isEmpty());
02137
02138 int index = path.takeFirst();
02139 Q_ASSERT(index >= 0 && index < PosCount);
02140
02141 if (path.isEmpty())
02142 return separatorRect(index);
02143 else
02144 return docks[index].separatorRect(path);
02145 }
02146
02147 bool QDockWidgetLayout::insertGap(QList<int> path, QWidgetItem *dockWidgetItem)
02148 {
02149 Q_ASSERT(!path.isEmpty());
02150 int index = path.takeFirst();
02151 Q_ASSERT(index >= 0 && index < PosCount);
02152 return docks[index].insertGap(path, dockWidgetItem);
02153 }
02154
02155 QRect QDockWidgetLayout::convertToWidget(QList<int> path, QWidgetItem *dockWidgetItem)
02156 {
02157 Q_ASSERT(!path.isEmpty());
02158 int index = path.takeFirst();
02159 Q_ASSERT(index >= 0 && index < PosCount);
02160 return docks[index].convertToWidget(path, dockWidgetItem);
02161 }
02162
02163 QWidgetItem *QDockWidgetLayout::convertToGap(QList<int> path)
02164 {
02165 Q_ASSERT(!path.isEmpty());
02166 int index = path.takeFirst();
02167 Q_ASSERT(index >= 0 && index < PosCount);
02168 return docks[index].convertToGap(path);
02169 }
02170
02171 void QDockWidgetLayout::remove(QList<int> path)
02172 {
02173 Q_ASSERT(!path.isEmpty());
02174 int index = path.takeFirst();
02175 Q_ASSERT(index >= 0 && index < PosCount);
02176 docks[index].remove(path);
02177 }
02178
02179 static inline int qMin(int i1, int i2, int i3) { return qMin(i1, qMin(i2, i3)); }
02180 static inline int qMax(int i1, int i2, int i3) { return qMax(i1, qMax(i2, i3)); }
02181
02182 void QDockWidgetLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
02183 QVector<QLayoutStruct> *_hor_struct_list)
02184 {
02185 QSize center_hint(0, 0);
02186 QSize center_min(0, 0);
02187 bool have_central = centralWidgetItem != 0 && !centralWidgetItem->isEmpty();
02188 if (have_central) {
02189 center_hint = centralWidgetRect.size();
02190 if (!center_hint.isValid())
02191 center_hint = centralWidgetItem->sizeHint();
02192 center_min = centralWidgetItem->minimumSize();
02193 }
02194
02195 QRect center_rect = rect;
02196 if (!docks[LeftPos].isEmpty())
02197 center_rect.setLeft(rect.left() + docks[LeftPos].rect.width() + sep);
02198 if (!docks[TopPos].isEmpty())
02199 center_rect.setTop(rect.top() + docks[TopPos].rect.height() + sep);
02200 if (!docks[RightPos].isEmpty())
02201 center_rect.setRight(rect.right() - docks[RightPos].rect.width() - sep - 1);
02202 if (!docks[BottomPos].isEmpty())
02203 center_rect.setBottom(rect.bottom() - docks[BottomPos].rect.height() - sep - 1);
02204
02205 QSize left_hint = docks[LeftPos].size();
02206 if (!left_hint.isValid())
02207 left_hint = docks[LeftPos].sizeHint();
02208 QSize left_min = docks[LeftPos].minimumSize();
02209 QSize left_max = docks[LeftPos].maximumSize();
02210 int left_sep = docks[LeftPos].isEmpty() ? 0 : sep;
02211
02212 QSize right_hint = docks[RightPos].size();
02213 if (!right_hint.isValid())
02214 right_hint = docks[RightPos].sizeHint();
02215 QSize right_min = docks[RightPos].minimumSize();
02216 QSize right_max = docks[RightPos].maximumSize();
02217 int right_sep = docks[RightPos].isEmpty() ? 0 : sep;
02218
02219 QSize top_hint = docks[TopPos].size();
02220 if (!top_hint.isValid())
02221 top_hint = docks[TopPos].sizeHint();
02222 QSize top_min = docks[TopPos].minimumSize();
02223 QSize top_max = docks[TopPos].maximumSize();
02224 int top_sep = docks[TopPos].isEmpty() ? 0 : sep;
02225
02226 QSize bottom_hint = docks[BottomPos].size();
02227 if (!bottom_hint.isValid())
02228 bottom_hint = docks[BottomPos].sizeHint();
02229 QSize bottom_min = docks[BottomPos].minimumSize();
02230 QSize bottom_max = docks[BottomPos].maximumSize();
02231 int bottom_sep = docks[BottomPos].isEmpty() ? 0 : sep;
02232
02233 if (_ver_struct_list != 0) {
02234 QVector<QLayoutStruct> &ver_struct_list = *_ver_struct_list;
02235 ver_struct_list.resize(3);
02236
02237
02238
02239 ver_struct_list[0].stretch = 0;
02240 ver_struct_list[0].sizeHint = top_hint.height();
02241 ver_struct_list[0].minimumSize = top_min.height();
02242 ver_struct_list[0].maximumSize = top_max.height();
02243 ver_struct_list[0].expansive = false;
02244 ver_struct_list[0].empty = docks[TopPos].isEmpty();
02245 ver_struct_list[0].pos = docks[TopPos].rect.top();
02246 ver_struct_list[0].size = docks[TopPos].rect.height();
02247
02248
02249
02250 ver_struct_list[1].stretch = center_hint.height();
02251 int left = left_hint.height();
02252 if (corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea)
02253 left -= top_hint.height() + top_sep;
02254 if (corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea)
02255 left -= bottom_hint.height() + bottom_sep;
02256 int right = right_hint.height();
02257 if (corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea)
02258 right -= top_hint.height() + top_sep;
02259 if (corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea)
02260 right -= bottom_hint.height() + bottom_sep;
02261 ver_struct_list[1].sizeHint = qMax(left, center_hint.height(), right);
02262
02263 left = left_min.height();
02264 if (corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea)
02265 left -= top_min.height() + top_sep;
02266 if (corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea)
02267 left -= bottom_min.height() + bottom_sep;
02268 right = right_min.height();
02269 if (corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea)
02270 right -= top_min.height() + top_sep;
02271 if (corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea)
02272 right -= bottom_min.height() + bottom_sep;
02273 ver_struct_list[1].minimumSize = qMax(left, center_min.height(), right);
02274 ver_struct_list[1].maximumSize = have_central ? QWIDGETSIZE_MAX : 0;
02275 ver_struct_list[1].expansive = have_central;
02276 ver_struct_list[1].empty = docks[LeftPos].isEmpty()
02277 && !have_central
02278 && docks[RightPos].isEmpty();
02279 ver_struct_list[1].pos = center_rect.top();
02280 ver_struct_list[1].size = center_rect.height();
02281
02282
02283
02284 ver_struct_list[2].stretch = 0;
02285 ver_struct_list[2].sizeHint = bottom_hint.height();
02286 ver_struct_list[2].minimumSize = bottom_min.height();
02287 ver_struct_list[2].maximumSize = bottom_max.height();
02288 ver_struct_list[2].expansive = false;
02289 ver_struct_list[2].empty = docks[BottomPos].isEmpty();
02290 ver_struct_list[2].pos = docks[BottomPos].rect.top();
02291 ver_struct_list[2].size = docks[BottomPos].rect.height();
02292
02293 for (int i = 0; i < 3; ++i) {
02294 ver_struct_list[i].sizeHint
02295 = qMax(ver_struct_list[i].sizeHint, ver_struct_list[i].minimumSize);
02296 }
02297 }
02298
02299 if (_hor_struct_list != 0) {
02300 QVector<QLayoutStruct> &hor_struct_list = *_hor_struct_list;
02301 hor_struct_list.resize(3);
02302
02303
02304
02305 hor_struct_list[0].stretch = 0;
02306 hor_struct_list[0].sizeHint = left_hint.width();
02307 hor_struct_list[0].minimumSize = left_min.width();
02308 hor_struct_list[0].maximumSize = left_max.width();
02309 hor_struct_list[0].expansive = false;
02310 hor_struct_list[0].empty = docks[LeftPos].isEmpty();
02311 hor_struct_list[0].pos = docks[LeftPos].rect.left();
02312 hor_struct_list[0].size = docks[LeftPos].rect.width();
02313
02314
02315
02316 hor_struct_list[1].stretch = center_hint.width();
02317 int top = top_hint.width();
02318 if (corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea)
02319 top -= left_hint.width() + left_sep;
02320 if (corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea)
02321 top -= right_hint.width() + right_sep;
02322 int bottom = bottom_hint.width();
02323 if (corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea)
02324 bottom -= left_hint.width() + left_sep;
02325 if (corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea)
02326 bottom -= right_hint.width() + right_sep;
02327 hor_struct_list[1].sizeHint = qMax(top, center_hint.width(), bottom);
02328
02329 top = top_min.width();
02330 if (corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea)
02331 top -= left_min.width() + left_sep;
02332 if (corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea)
02333 top -= right_min.width() + right_sep;
02334 bottom = bottom_min.width();
02335 if (corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea)
02336 bottom -= left_min.width() + left_sep;
02337 if (corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea)
02338 bottom -= right_min.width() + right_sep;
02339 hor_struct_list[1].minimumSize = qMax(top, center_min.width(), bottom);
02340 hor_struct_list[1].maximumSize = have_central ? QWIDGETSIZE_MAX : 0;
02341 hor_struct_list[1].expansive = have_central;
02342 hor_struct_list[1].empty = !have_central;
02343 hor_struct_list[1].pos = center_rect.left();
02344 hor_struct_list[1].size = center_rect.width();
02345
02346
02347
02348 hor_struct_list[2].stretch = 0;
02349 hor_struct_list[2].sizeHint = right_hint.width();
02350 hor_struct_list[2].minimumSize = right_min.width();
02351 hor_struct_list[2].maximumSize = right_max.width();
02352 hor_struct_list[2].expansive = false;
02353 hor_struct_list[2].empty = docks[RightPos].isEmpty();
02354 hor_struct_list[2].pos = docks[RightPos].rect.left();
02355 hor_struct_list[2].size = docks[RightPos].rect.width();
02356
02357 for (int i = 0; i < 3; ++i) {
02358 hor_struct_list[i].sizeHint
02359 = qMax(hor_struct_list[i].sizeHint, hor_struct_list[i].minimumSize);
02360 }
02361 }
02362 }
02363
02364 void QDockWidgetLayout::setGrid(QVector<QLayoutStruct> *ver_struct_list,
02365 QVector<QLayoutStruct> *hor_struct_list)
02366 {
02367
02368
02369
02370 QRect r = docks[TopPos].rect;
02371 if (hor_struct_list != 0) {
02372 r.setLeft(corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
02373 || docks[LeftPos].isEmpty()
02374 ? rect.left() : hor_struct_list->at(1).pos);
02375 r.setRight(corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
02376 || docks[RightPos].isEmpty()
02377 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
02378 }
02379 if (ver_struct_list != 0) {
02380 r.setTop(rect.top());
02381 r.setBottom(ver_struct_list->at(1).pos - sep - 1);
02382 }
02383 docks[TopPos].rect = r;
02384 docks[TopPos].fitItems();
02385
02386
02387
02388 r = docks[BottomPos].rect;
02389 if (hor_struct_list != 0) {
02390 r.setLeft(corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
02391 || docks[LeftPos].isEmpty()
02392 ? rect.left() : hor_struct_list->at(1).pos);
02393 r.setRight(corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
02394 || docks[RightPos].isEmpty()
02395 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
02396 }
02397 if (ver_struct_list != 0) {
02398 r.setTop(ver_struct_list->at(2).pos);
02399 r.setBottom(rect.bottom());
02400 }
02401 docks[BottomPos].rect = r;
02402 docks[BottomPos].fitItems();
02403
02404
02405
02406 r = docks[LeftPos].rect;
02407 if (hor_struct_list != 0) {
02408 r.setLeft(rect.left());
02409 r.setRight(hor_struct_list->at(1).pos - sep - 1);
02410 }
02411 if (ver_struct_list != 0) {
02412 r.setTop(corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
02413 || docks[TopPos].isEmpty()
02414 ? rect.top() : ver_struct_list->at(1).pos);
02415 r.setBottom(corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
02416 || docks[BottomPos].isEmpty()
02417 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
02418 }
02419 docks[LeftPos].rect = r;
02420 docks[LeftPos].fitItems();
02421
02422
02423
02424 r = docks[RightPos].rect;
02425 if (hor_struct_list != 0) {
02426 r.setLeft(hor_struct_list->at(2).pos);
02427 r.setRight(rect.right());
02428 }
02429 if (ver_struct_list != 0) {
02430 r.setTop(corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
02431 || docks[TopPos].isEmpty()
02432 ? rect.top() : ver_struct_list->at(1).pos);
02433 r.setBottom(corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
02434 || docks[BottomPos].isEmpty()
02435 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
02436 }
02437 docks[RightPos].rect = r;
02438 docks[RightPos].fitItems();
02439
02440
02441
02442 if (hor_struct_list != 0) {
02443 centralWidgetRect.setLeft(hor_struct_list->at(1).pos);
02444 centralWidgetRect.setWidth(hor_struct_list->at(1).size);
02445 }
02446 if (ver_struct_list != 0) {
02447 centralWidgetRect.setTop(ver_struct_list->at(1).pos);
02448 centralWidgetRect.setHeight(ver_struct_list->at(1).size);
02449 }
02450 }
02451
02452 void QDockWidgetLayout::fitLayout()
02453 {
02454 QVector<QLayoutStruct> ver_struct_list(3);
02455 QVector<QLayoutStruct> hor_struct_list(3);
02456 getGrid(&ver_struct_list, &hor_struct_list);
02457
02458 qGeomCalc(ver_struct_list, 0, 3, rect.top(), rect.height(), sep);
02459 qGeomCalc(hor_struct_list, 0, 3, rect.left(), rect.width(), sep);
02460
02461 setGrid(&ver_struct_list, &hor_struct_list);
02462 }
02463
02464 void QDockWidgetLayout::clear()
02465 {
02466 for (int i = 0; i < PosCount; ++i)
02467 docks[i].clear();
02468
02469 rect = QRect(0, 0, -1, -1);
02470 centralWidgetRect = QRect(0, 0, -1, -1);
02471 }
02472
02473 QSize QDockWidgetLayout::sizeHint() const
02474 {
02475 int left_sep = docks[LeftPos].isEmpty() ? 0 : sep;
02476 int right_sep = docks[RightPos].isEmpty() ? 0 : sep;
02477 int top_sep = docks[TopPos].isEmpty() ? 0 : sep;
02478 int bottom_sep = docks[BottomPos].isEmpty() ? 0 : sep;
02479
02480 QSize left = docks[LeftPos].sizeHint() + QSize(left_sep, 0);
02481 QSize right = docks[RightPos].sizeHint() + QSize(right_sep, 0);
02482 QSize top = docks[TopPos].sizeHint() + QSize(0, top_sep);
02483 QSize bottom = docks[BottomPos].sizeHint() + QSize(0, bottom_sep);
02484 QSize center = centralWidgetItem == 0 ? QSize(0, 0) : centralWidgetItem->sizeHint();
02485
02486 int row1 = top.width();
02487 int row2 = left.width() + center.width() + right.width();
02488 int row3 = bottom.width();
02489 int col1 = left.height();
02490 int col2 = top.height() + center.height() + bottom.height();
02491 int col3 = right.height();
02492
02493 if (corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea)
02494 row1 += left.width();
02495 else
02496 col1 += top.height();
02497
02498 if (corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea)
02499 row1 += right.width();
02500 else
02501 col3 += top.height();
02502
02503 if (corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea)
02504 row3 += left.width();
02505 else
02506 col1 += bottom.height();
02507
02508 if (corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea)
02509 row3 += right.width();
02510 else
02511 col3 += bottom.height();
02512
02513 return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
02514 }
02515
02516 QSize QDockWidgetLayout::minimumSize() const
02517 {
02518 int left_sep = docks[LeftPos].isEmpty() ? 0 : sep;
02519 int right_sep = docks[RightPos].isEmpty() ? 0 : sep;
02520 int top_sep = docks[TopPos].isEmpty() ? 0 : sep;
02521 int bottom_sep = docks[BottomPos].isEmpty() ? 0 : sep;
02522
02523 QSize left = docks[LeftPos].minimumSize() + QSize(left_sep, 0);
02524 QSize right = docks[RightPos].minimumSize() + QSize(right_sep, 0);
02525 QSize top = docks[TopPos].minimumSize() + QSize(0, top_sep);
02526 QSize bottom = docks[BottomPos].minimumSize() + QSize(0, bottom_sep);
02527 QSize center = centralWidgetItem == 0 ? QSize(0, 0) : centralWidgetItem->minimumSize();
02528
02529 int row1 = top.width();
02530 int row2 = left.width() + center.width() + right.width();
02531 int row3 = bottom.width();
02532 int col1 = left.height();
02533 int col2 = top.height() + center.height() + bottom.height();
02534 int col3 = right.height();
02535
02536 if (corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea)
02537 row1 += left.width();
02538 else
02539 col1 += top.height();
02540
02541 if (corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea)
02542 row1 += right.width();
02543 else
02544 col3 += top.height();
02545
02546 if (corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea)
02547 row3 += left.width();
02548 else
02549 col1 += bottom.height();
02550
02551 if (corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea)
02552 row3 += right.width();
02553 else
02554 col3 += bottom.height();
02555
02556 return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
02557 }
02558
02559 void QDockWidgetLayout::addDockWidget(DockPos pos, QDockWidget *dockWidget,
02560 Qt::Orientation orientation)
02561 {
02562 QWidgetItem *dockWidgetItem = new QWidgetItem(dockWidget);
02563 QDockAreaLayoutInfo &info = docks[pos];
02564 if (orientation == info.o || info.isEmpty()) {
02565 QDockAreaLayoutItem new_item(dockWidgetItem);
02566 info.item_list.append(new_item);
02567 #ifndef QT_NO_TABBAR
02568 if (info.tabbed && !new_item.skip()) {
02569 info.updateTabBar();
02570 info.setCurrentTabId(tabId(new_item));
02571 }
02572 #endif
02573 } else {
02574 #ifndef QT_NO_TABBAR
02575 int tbshape = QTabBar::RoundedSouth;
02576 switch (pos) {
02577 case TopPos:
02578 tbshape = QTabBar::RoundedNorth;
02579 break;
02580 case BottomPos:
02581 tbshape = QTabBar::RoundedSouth;
02582 break;
02583 case RightPos:
02584 tbshape = QTabBar::RoundedEast;
02585 break;
02586 case LeftPos:
02587 tbshape = QTabBar::RoundedWest;
02588 break;
02589 default:
02590 break;
02591 }
02592 #else
02593 int tbshape = 0;
02594 #endif
02595 QDockAreaLayoutInfo new_info(sep, orientation, tbshape, mainWindow);
02596 new_info.item_list.append(new QDockAreaLayoutInfo(info));
02597 new_info.item_list.append(dockWidgetItem);
02598 info = new_info;
02599 }
02600 }
02601
02602 void QDockWidgetLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
02603 {
02604 QList<int> path = indexOf(first);
02605 if (path.isEmpty())
02606 return;