src/qt3support/widgets/q3dockarea.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt3Support module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "q3dockarea.h"
       
    43 
       
    44 #ifndef QT_NO_MAINWINDOW
       
    45 #include "qsplitter.h"
       
    46 #include "qevent.h"
       
    47 #include "qlayout.h"
       
    48 #include "qapplication.h"
       
    49 #include "qpainter.h"
       
    50 #include "qmap.h"
       
    51 #include "q3mainwindow.h"
       
    52 #include "q3toolbar.h"
       
    53 
       
    54 QT_BEGIN_NAMESPACE
       
    55 
       
    56 //#define QDOCKAREA_DEBUG
       
    57 
       
    58 struct Q3DockData
       
    59 {
       
    60     Q3DockData() : w(0), rect() {}
       
    61     Q3DockData(Q3DockWindow *dw, const QRect &r) : w(dw), rect(r) {}
       
    62     Q3DockWindow *w;
       
    63     QRect rect;
       
    64 
       
    65     Q_DUMMY_COMPARISON_OPERATOR(Q3DockData)
       
    66 };
       
    67 
       
    68 static int fix_x(Q3DockWindow* w, int width = -1) {
       
    69     if (QApplication::reverseLayout()) {
       
    70         if (width < 0)
       
    71             width = w->width();
       
    72         return w->parentWidget()->width() - w->x() - width;
       
    73     }
       
    74     return w->x();
       
    75 }
       
    76 static int fix_x(Q3DockWindow* w, int x, int width = -1) {
       
    77     if (QApplication::reverseLayout()) {
       
    78         if (width < 0)
       
    79             width = w->width();
       
    80         return w->parentWidget()->width() - x - width;
       
    81     }
       
    82     return x;
       
    83 }
       
    84 
       
    85 static QPoint fix_pos(Q3DockWindow* w) {
       
    86     if (QApplication::reverseLayout()) {
       
    87         QPoint p = w->pos();
       
    88         p.rx() = w->parentWidget()->width() - p.x() - w->width();
       
    89         return p;
       
    90     }
       
    91     return w->pos();
       
    92 }
       
    93 
       
    94 
       
    95 void Q3DockAreaLayout::setGeometry(const QRect &r)
       
    96 {
       
    97     QLayout::setGeometry(r);
       
    98     layoutItems(r);
       
    99 }
       
   100 
       
   101 QLayoutItem *Q3DockAreaLayout::itemAt(int) const
       
   102 {
       
   103     return 0; //###
       
   104 }
       
   105 
       
   106 QLayoutItem *Q3DockAreaLayout::takeAt(int)
       
   107 {
       
   108     return 0; //###
       
   109 }
       
   110 
       
   111 int Q3DockAreaLayout::count() const
       
   112 {
       
   113     return 0; //###
       
   114 }
       
   115 
       
   116 
       
   117 QSize Q3DockAreaLayout::sizeHint() const
       
   118 {
       
   119     if (dockWindows->isEmpty())
       
   120         return QSize(0, 0);
       
   121 
       
   122     if (dirty) {
       
   123         Q3DockAreaLayout *that = (Q3DockAreaLayout *) this;
       
   124         that->layoutItems(geometry());
       
   125     }
       
   126 
       
   127     int w = 0;
       
   128     int h = 0;
       
   129     int y = -1;
       
   130     int x = -1;
       
   131     int ph = 0;
       
   132     int pw = 0;
       
   133     for (int i = 0; i < dockWindows->size(); ++i) {
       
   134         Q3DockWindow *dw = dockWindows->at(i);
       
   135         int plush = 0, plusw = 0;
       
   136         if (dw->isHidden())
       
   137             continue;
       
   138         if (hasHeightForWidth()) {
       
   139             if (y != dw->y())
       
   140                 plush = ph;
       
   141             y = dw->y();
       
   142             ph = dw->height();
       
   143         } else {
       
   144             if (x != dw->x())
       
   145                 plusw = pw;
       
   146             x = dw->x();
       
   147             pw = dw->width();
       
   148         }
       
   149         h = qMax(h, dw->height() + plush);
       
   150         w = qMax(w, dw->width() + plusw);
       
   151     }
       
   152 
       
   153     if (hasHeightForWidth())
       
   154         return QSize(0, h);
       
   155     return QSize(w, 0);
       
   156 }
       
   157 
       
   158 bool Q3DockAreaLayout::hasHeightForWidth() const
       
   159 {
       
   160     return orient == Qt::Horizontal;
       
   161 }
       
   162 
       
   163 void Q3DockAreaLayout::init()
       
   164 {
       
   165     dirty = true;
       
   166     cached_width = 0;
       
   167     cached_height = 0;
       
   168     cached_hfw = -1;
       
   169     cached_wfh = -1;
       
   170 }
       
   171 
       
   172 void Q3DockAreaLayout::invalidate()
       
   173 {
       
   174     dirty = true;
       
   175     cached_width = 0;
       
   176     cached_height = 0;
       
   177     QLayout::invalidate();
       
   178 }
       
   179 
       
   180 static int start_pos(const QRect &r, Qt::Orientation o)
       
   181 {
       
   182     if (o == Qt::Horizontal) {
       
   183         return qMax(0, r.x());
       
   184     } else {
       
   185         return qMax(0, r.y());
       
   186     }
       
   187 }
       
   188 
       
   189 static void add_size(int s, int &pos, Qt::Orientation o)
       
   190 {
       
   191     if (o == Qt::Horizontal) {
       
   192         pos += s;
       
   193     } else {
       
   194         pos += s;
       
   195     }
       
   196 }
       
   197 
       
   198 static int space_left(const QRect &r, int pos, Qt::Orientation o)
       
   199 {
       
   200     if (o == Qt::Horizontal) {
       
   201         return (r.x() + r.width()) - pos;
       
   202     } else {
       
   203         return (r.y() + r.height()) - pos;
       
   204     }
       
   205 }
       
   206 
       
   207 static int dock_extent(Q3DockWindow *w, Qt::Orientation o, int maxsize)
       
   208 {
       
   209     if (o == Qt::Horizontal)
       
   210         return qMin(maxsize, qMax(w->sizeHint().width(), w->fixedExtent().width()));
       
   211     else
       
   212         return qMin(maxsize, qMax(w->sizeHint().height(), w->fixedExtent().height()));
       
   213 }
       
   214 
       
   215 static int dock_strut(Q3DockWindow *w, Qt::Orientation o)
       
   216 {
       
   217     if (o != Qt::Horizontal) {
       
   218         int wid;
       
   219         if ((wid = w->fixedExtent().width()) != -1)
       
   220             return qMax(wid, qMax(w->minimumSize().width(), w->minimumSizeHint().width()));
       
   221         return qMax(w->sizeHint().width(), qMax(w->minimumSize().width(), w->minimumSizeHint().width()));
       
   222     } else {
       
   223         int hei;
       
   224         if ((hei = w->fixedExtent().height()) != -1)
       
   225             return qMax(hei, qMax(w->minimumSizeHint().height(), w->minimumSize().height()));
       
   226         return qMax(w->sizeHint().height(), qMax(w->minimumSizeHint().height(), w->minimumSize().height()));
       
   227     }
       
   228 }
       
   229 
       
   230 static void set_geometry(Q3DockWindow *w, int pos, int sectionpos, int extent, int strut, Qt::Orientation o)
       
   231 {
       
   232     if (o == Qt::Horizontal)
       
   233         w->setGeometry(fix_x(w, pos, extent), sectionpos, extent, strut);
       
   234     else
       
   235         w->setGeometry(sectionpos, pos, strut, extent);
       
   236 }
       
   237 
       
   238 static int size_extent(const QSize &s, Qt::Orientation o, bool swap = false)
       
   239 {
       
   240     return o == Qt::Horizontal ? (swap ? s.height() : s.width()) : (swap ? s.width() :  s.height());
       
   241 }
       
   242 
       
   243 static int point_pos(const QPoint &p, Qt::Orientation o, bool swap = false)
       
   244 {
       
   245     return o == Qt::Horizontal ? (swap ? p.y() : p.x()) : (swap ? p.x() : p.y());
       
   246 }
       
   247 
       
   248 static void shrink_extend(Q3DockWindow *dw, int &dockExtend, int /*spaceLeft*/, Qt::Orientation o)
       
   249 {
       
   250     Q3ToolBar *tb = qobject_cast<Q3ToolBar*>(dw);
       
   251     if (o == Qt::Horizontal) {
       
   252         int mw = 0;
       
   253         if (!tb)
       
   254             mw = dw->minimumWidth();
       
   255         else
       
   256             mw = dw->sizeHint().width();
       
   257         dockExtend = mw;
       
   258     } else {
       
   259         int mh = 0;
       
   260         if (!tb)
       
   261             mh = dw->minimumHeight();
       
   262         else
       
   263             mh = dw->sizeHint().height();
       
   264         dockExtend = mh;
       
   265     }
       
   266 }
       
   267 
       
   268 static void place_line(QList<Q3DockData> &lastLine, Qt::Orientation o, int linestrut, int fullextent, int tbstrut, int maxsize, Q3DockAreaLayout *)
       
   269 {
       
   270     Q3DockWindow *last = 0;
       
   271     QRect lastRect;
       
   272     for (QList<Q3DockData>::Iterator it = lastLine.begin(); it != lastLine.end(); ++it) {
       
   273         if (tbstrut != -1 && qobject_cast<Q3ToolBar*>((*it).w))
       
   274             (*it).rect.setHeight(tbstrut);
       
   275         if (!last) {
       
   276             last = (*it).w;
       
   277             lastRect = (*it).rect;
       
   278             continue;
       
   279         }
       
   280         if (!last->isStretchable()) {
       
   281             int w = qMin(lastRect.width(), maxsize);
       
   282             set_geometry(last, lastRect.x(), lastRect.y(), w, lastRect.height(), o);
       
   283         } else {
       
   284             int w = qMin((*it).rect.x() - lastRect.x(), maxsize);
       
   285             set_geometry(last, lastRect.x(), lastRect.y(), w,
       
   286                           last->isResizeEnabled() ? linestrut : lastRect.height(), o);
       
   287         }
       
   288         last = (*it).w;
       
   289         lastRect = (*it).rect;
       
   290     }
       
   291     if (!last)
       
   292         return;
       
   293     if (!last->isStretchable()) {
       
   294         int w = qMin(lastRect.width(), maxsize);
       
   295         set_geometry(last, lastRect.x(), lastRect.y(), w, lastRect.height(), o);
       
   296     } else {
       
   297         int w = qMin(fullextent - lastRect.x() - (o == Qt::Vertical ? 1 : 0), maxsize);
       
   298         set_geometry(last, lastRect.x(), lastRect.y(), w,
       
   299                       last->isResizeEnabled() ? linestrut : lastRect.height(), o);
       
   300     }
       
   301 }
       
   302 
       
   303 QSize Q3DockAreaLayout::minimumSize() const
       
   304 {
       
   305     if (dockWindows->isEmpty())
       
   306         return QSize(0, 0);
       
   307 
       
   308     if (dirty) {
       
   309         Q3DockAreaLayout *that = (Q3DockAreaLayout *) this;
       
   310         that->layoutItems(geometry());
       
   311     }
       
   312 
       
   313     int s = 0;
       
   314 
       
   315     for (int i = 0; i < dockWindows->size(); ++i) {
       
   316         Q3DockWindow *dw = dockWindows->at(i);
       
   317         if (dw->isHidden())
       
   318             continue;
       
   319         s = qMax(s, dock_strut(dw, orientation()));
       
   320     }
       
   321 
       
   322     return orientation() == Qt::Horizontal ? QSize(0, s ? s+2 : 0) :  QSize(s, 0);
       
   323 }
       
   324 
       
   325 
       
   326 
       
   327 int Q3DockAreaLayout::layoutItems(const QRect &rect, bool testonly)
       
   328 {
       
   329     if (dockWindows->isEmpty())
       
   330         return 0;
       
   331 
       
   332     dirty = false;
       
   333 
       
   334     // some corrections
       
   335     QRect r = rect;
       
   336     if (orientation() == Qt::Vertical)
       
   337         r.setHeight(r.height() - 3);
       
   338 
       
   339     // init
       
   340     lines.clear();
       
   341     ls.clear();
       
   342     int start = start_pos(r, orientation());
       
   343     int pos = start;
       
   344     int sectionpos = 0;
       
   345     int linestrut = 0;
       
   346     QList<Q3DockData> lastLine;
       
   347     int tbstrut = -1;
       
   348     int maxsize = size_extent(rect.size(), orientation());
       
   349     int visibleWindows = 0;
       
   350 
       
   351     // go through all widgets in the dock
       
   352     for (int i = 0; i < dockWindows->size(); ++i) {
       
   353         Q3DockWindow *dw = dockWindows->at(i);
       
   354         if (dw->isHidden())
       
   355             continue;
       
   356         ++visibleWindows;
       
   357         // find position for the widget: This is the maximum of the
       
   358         // end of the previous widget and the offset of the widget. If
       
   359         // the position + the width of the widget dosn't fit into the
       
   360         // dock, try moving it a bit back, if possible.
       
   361         int op = pos;
       
   362         int dockExtend = dock_extent(dw, orientation(), maxsize);
       
   363         if (!dw->isStretchable()) {
       
   364             pos = qMax(pos, dw->offset());
       
   365             if (pos + dockExtend > size_extent(r.size(), orientation()) - 1)
       
   366                 pos = qMax(op, size_extent(r.size(), orientation()) - 1 - dockExtend);
       
   367         }
       
   368         if (!lastLine.isEmpty() && !dw->newLine() && space_left(rect, pos, orientation()) < dockExtend)
       
   369             shrink_extend(dw, dockExtend, space_left(rect, pos, orientation()), orientation());
       
   370         // if the current widget doesn't fit into the line anymore and it is not the first widget of the line
       
   371         if (!lastLine.isEmpty() &&
       
   372              (space_left(rect, pos, orientation()) < dockExtend || dw->newLine())) {
       
   373             if (!testonly) // place the last line, if not in test mode
       
   374                 place_line(lastLine, orientation(), linestrut, size_extent(r.size(), orientation()), tbstrut, maxsize, this);
       
   375             // remember the line coordinats of the last line
       
   376             if (orientation() == Qt::Horizontal)
       
   377                 lines.append(QRect(0, sectionpos, r.width(), linestrut));
       
   378             else
       
   379                 lines.append(QRect(sectionpos, 0, linestrut, r.height()));
       
   380             // do some clearing for the next line
       
   381             lastLine.clear();
       
   382             sectionpos += linestrut;
       
   383             linestrut = 0;
       
   384             pos = start;
       
   385             tbstrut = -1;
       
   386         }
       
   387 
       
   388         // remember first widget of a line
       
   389         if (lastLine.isEmpty()) {
       
   390             ls.append(dw);
       
   391             // try to make the best position
       
   392             int op = pos;
       
   393             if (!dw->isStretchable())
       
   394                 pos = qMax(pos, dw->offset());
       
   395             if (pos + dockExtend > size_extent(r.size(), orientation()) - 1)
       
   396                 pos = qMax(op, size_extent(r.size(), orientation()) - 1 - dockExtend);
       
   397         }
       
   398         // do some calculations and add the remember the rect which the docking widget requires for the placing
       
   399         QRect dwRect(pos, sectionpos, dockExtend, dock_strut(dw, orientation() ));
       
   400         lastLine.append(Q3DockData(dw, dwRect));
       
   401         if (qobject_cast<Q3ToolBar*>(dw))
       
   402             tbstrut = qMax(tbstrut, dock_strut(dw, orientation()));
       
   403         linestrut = qMax(dock_strut(dw, orientation()), linestrut);
       
   404         add_size(dockExtend, pos, orientation());
       
   405     }
       
   406 
       
   407     // if some stuff was not placed/stored yet, do it now
       
   408     if (!testonly)
       
   409         place_line(lastLine, orientation(), linestrut, size_extent(r.size(), orientation()), tbstrut, maxsize, this);
       
   410     if (orientation() == Qt::Horizontal)
       
   411         lines.append(QRect(0, sectionpos, r.width(), linestrut));
       
   412     else
       
   413         lines.append(QRect(sectionpos, 0, linestrut, r.height()));
       
   414     if (lines.size() >= 2 && *(--lines.end()) == *(--(--lines.end())))
       
   415         lines.removeLast();
       
   416 
       
   417     bool hadResizable = false;
       
   418     for (int i = 0; i < dockWindows->size(); ++i) {
       
   419         Q3DockWindow *dw = dockWindows->at(i);
       
   420         if (!dw->isVisibleTo(parentWidget))
       
   421             continue;
       
   422         hadResizable = hadResizable || dw->isResizeEnabled();
       
   423         dw->updateSplitterVisibility(visibleWindows > 1); //!dw->area()->isLastDockWindow(dw));
       
   424         if (Q3ToolBar *tb = qobject_cast<Q3ToolBar *>(dw))
       
   425             tb->checkForExtension(dw->size());
       
   426     }
       
   427     return sectionpos + linestrut;
       
   428 }
       
   429 
       
   430 int Q3DockAreaLayout::heightForWidth(int w) const
       
   431 {
       
   432     if (dockWindows->isEmpty() && parentWidget)
       
   433         return parentWidget->minimumHeight();
       
   434 
       
   435     if (cached_width != w) {
       
   436         Q3DockAreaLayout * mthis = (Q3DockAreaLayout*)this;
       
   437         mthis->cached_width = w;
       
   438         int h = mthis->layoutItems(QRect(0, 0, w, 0), true);
       
   439         mthis->cached_hfw = h;
       
   440         return h;
       
   441     }
       
   442 
       
   443     return cached_hfw;
       
   444 }
       
   445 
       
   446 int Q3DockAreaLayout::widthForHeight(int h) const
       
   447 {
       
   448     if (cached_height != h) {
       
   449         Q3DockAreaLayout * mthis = (Q3DockAreaLayout*)this;
       
   450         mthis->cached_height = h;
       
   451         int w = mthis->layoutItems(QRect(0, 0, 0, h), true);
       
   452         mthis->cached_wfh = w;
       
   453         return w;
       
   454     }
       
   455     return cached_wfh;
       
   456 }
       
   457 
       
   458 
       
   459 
       
   460 
       
   461 /*!
       
   462     \class Q3DockArea
       
   463     \brief The Q3DockArea class manages and lays out Q3DockWindows.
       
   464 
       
   465     \compat
       
   466 
       
   467     A Q3DockArea is a container which manages a list of
       
   468     \l{Q3DockWindow}s which it lays out within its area. In cooperation
       
   469     with the \l{Q3DockWindow}s it is responsible for the docking and
       
   470     undocking of \l{Q3DockWindow}s and moving them inside the dock
       
   471     area. Q3DockAreas also handle the wrapping of \l{Q3DockWindow}s to
       
   472     fill the available space as compactly as possible. Q3DockAreas can
       
   473     contain Q3ToolBars since Q3ToolBar is a Q3DockWindow subclass.
       
   474 
       
   475     QMainWindow contains four Q3DockAreas which you can use for your
       
   476     Q3ToolBars and Q3DockWindows, so in most situations you do not
       
   477     need to use the Q3DockArea class directly. Although QMainWindow
       
   478     contains support for its own dock areas, you can't add new ones.
       
   479     You also can't add a Q3DockArea to your own subclass of QWidget.
       
   480     It won't be shown.
       
   481 
       
   482     \img qmainwindow-qdockareas.png QMainWindow's Q3DockAreas
       
   483 
       
   484     \target lines
       
   485     \section1 Lines.
       
   486 
       
   487     Q3DockArea uses the concept of lines. A line is a horizontal
       
   488     region which may contain dock windows side-by-side. A dock area
       
   489     may have room for more than one line. When dock windows are docked
       
   490     into a dock area they are usually added at the right hand side of
       
   491     the top-most line that has room (unless manually placed by the
       
   492     user). When users move dock windows they may leave empty lines or
       
   493     gaps in non-empty lines. Qt::Dock windows can be lined up to
       
   494     minimize wasted space using the lineUp() function.
       
   495 
       
   496     The Q3DockArea class maintains a position list of all its child
       
   497     dock windows. Qt::Dock windows are added to a dock area from position
       
   498     0 onwards. Qt::Dock windows are laid out sequentially in position
       
   499     order from left to right, and in the case of multiple lines of
       
   500     dock windows, from top to bottom. If a dock window is floated it
       
   501     still retains its position since this is where the window will
       
   502     return if the user double clicks its caption. A dock window's
       
   503     position can be determined with hasDockWindow(). The position can
       
   504     be changed with moveDockWindow().
       
   505 
       
   506     To dock or undock a dock window use Q3DockWindow::dock() and
       
   507     Q3DockWindow::undock() respectively. If you want to control which
       
   508     dock windows can dock in a dock area use setAcceptDockWindow(). To
       
   509     see if a dock area contains a particular dock window use
       
   510     \l{hasDockWindow()}; to see how many dock windows a dock area
       
   511     contains use count().
       
   512 
       
   513     The streaming operators can write the positions of the dock
       
   514     windows in the dock area to a QTextStream. The positions can be
       
   515     read back later to restore the saved positions.
       
   516 
       
   517     Save the positions to a QTextStream:
       
   518     \snippet doc/src/snippets/code/src_qt3support_widgets_q3dockarea.cpp 0
       
   519 
       
   520     Restore the positions from a QTextStream:
       
   521     \snippet doc/src/snippets/code/src_qt3support_widgets_q3dockarea.cpp 1
       
   522 */
       
   523 
       
   524 /*!
       
   525     \property Q3DockArea::handlePosition
       
   526     \brief where the dock window splitter handle is placed in the dock
       
   527     area
       
   528 
       
   529     The default position is \c Normal.
       
   530 */
       
   531 
       
   532 /*!
       
   533     \property Q3DockArea::orientation
       
   534     \brief the dock area's orientation
       
   535 
       
   536     There is no default value; the orientation is specified in the
       
   537     constructor.
       
   538 */
       
   539 
       
   540 /*!
       
   541     \enum Q3DockArea::HandlePosition
       
   542 
       
   543     A dock window has two kinds of handles, the dock window handle
       
   544     used for dragging the dock window, and the splitter handle used to
       
   545     resize the dock window in relation to other dock windows using a
       
   546     splitter. (The splitter handle is only visible for docked
       
   547     windows.)
       
   548 
       
   549     This enum specifies where the dock window splitter handle is
       
   550     placed in the dock area.
       
   551 
       
   552     \value Normal The splitter handles of dock windows are placed at
       
   553     the right or bottom.
       
   554 
       
   555     \value Reverse The splitter handles of dock windows are placed at
       
   556     the left or top.
       
   557 */
       
   558 
       
   559 /*!
       
   560     Constructs a Q3DockArea with orientation \a o, HandlePosition \a h,
       
   561     parent \a parent and called \a name.
       
   562 */
       
   563 
       
   564 Q3DockArea::Q3DockArea(Qt::Orientation o, HandlePosition h, QWidget *parent, const char *name)
       
   565     : QWidget(parent, name), orient(o), layout(0), hPos(h)
       
   566 {
       
   567     layout = new Q3DockAreaLayout(this, o, &dockWindows, 0, 0, "toollayout");
       
   568     installEventFilter(this);
       
   569 }
       
   570 
       
   571 /*!
       
   572     Destroys the dock area and all the dock windows docked in the dock
       
   573     area.
       
   574 
       
   575     Does not affect any floating dock windows or dock windows in other
       
   576     dock areas, even if they first appeared in this dock area.
       
   577     Floating dock windows are effectively top level windows and are
       
   578     not child windows of the dock area. When a floating dock window is
       
   579     docked (dragged into a dock area) its parent becomes the dock
       
   580     area.
       
   581 */
       
   582 
       
   583 Q3DockArea::~Q3DockArea()
       
   584 {
       
   585     while (!dockWindows.isEmpty())
       
   586         delete dockWindows.takeFirst();
       
   587 }
       
   588 
       
   589 /*!
       
   590     Moves the Q3DockWindow \a w within the dock area. If \a w is not
       
   591     already docked in this area, \a w is docked first. If \a index is
       
   592     -1 or larger than the number of docked widgets, \a w is appended
       
   593     at the end, otherwise it is inserted at the position \a index.
       
   594 */
       
   595 
       
   596 void Q3DockArea::moveDockWindow(Q3DockWindow *w, int index)
       
   597 {
       
   598     invalidateFixedSizes();
       
   599     Q3DockWindow *dockWindow = 0;
       
   600     int dockWindowIndex = findDockWindow(w);
       
   601     if (dockWindowIndex == -1) {
       
   602         dockWindow = w;
       
   603         bool vis = dockWindow->isVisible();
       
   604         dockWindow->setParent(this);
       
   605         dockWindow->move(0, 0);
       
   606         if(vis)
       
   607             dockWindow->show();
       
   608         w->installEventFilter(this);
       
   609         updateLayout();
       
   610         setSizePolicy(QSizePolicy(orientation() == Qt::Horizontal ? QSizePolicy::Expanding : QSizePolicy::Minimum,
       
   611                                     orientation() == Qt::Vertical ? QSizePolicy::Expanding : QSizePolicy::Minimum));
       
   612         dockWindows.append(w);
       
   613     } else {
       
   614         if (w->parent() != this) {
       
   615             bool vis = w->isVisible();
       
   616             w->setParent(this);
       
   617             w->move(0, 0);
       
   618             if(vis)
       
   619                 w->show();
       
   620         }
       
   621         if (index == -1) {
       
   622             dockWindows.removeAll(w);
       
   623             dockWindows.append(w);
       
   624         }
       
   625     }
       
   626 
       
   627     w->dockArea = this;
       
   628     w->curPlace = Q3DockWindow::InDock;
       
   629     w->updateGui();
       
   630 
       
   631     if (index != -1 && index < (int)dockWindows.count()) {
       
   632         dockWindows.removeAll(w);
       
   633         dockWindows.insert(index, w);
       
   634     }
       
   635 }
       
   636 
       
   637 /*!
       
   638     Returns true if the dock area contains the dock window \a w;
       
   639     otherwise returns false. If \a index is not 0 it will be set as
       
   640     follows: if the dock area contains the dock window *\a{index} is
       
   641     set to \a w's index position; otherwise *\a{index} is set to -1.
       
   642 */
       
   643 
       
   644 bool Q3DockArea::hasDockWindow(Q3DockWindow *w, int *index)
       
   645 {
       
   646     int i = dockWindows.indexOf(w);
       
   647     if (index)
       
   648         *index = i;
       
   649     return i != -1;
       
   650 }
       
   651 
       
   652 int Q3DockArea::lineOf(int index)
       
   653 {
       
   654     QList<Q3DockWindow *> lineStarts = layout->lineStarts();
       
   655     int i = 0;
       
   656     for (; i < lineStarts.size(); ++i) {
       
   657         Q3DockWindow *w = lineStarts.at(i);
       
   658         if (dockWindows.indexOf(w) >= index)
       
   659             return i;
       
   660     }
       
   661     return i;
       
   662 }
       
   663 
       
   664 /*!
       
   665     \overload
       
   666 
       
   667     Moves the dock window \a w inside the dock area where \a p is the
       
   668     new position (in global screen coordinates), \a r is the suggested
       
   669     rectangle of the dock window and \a swap specifies whether or not
       
   670     the orientation of the docked widget needs to be changed.
       
   671 
       
   672     This function is used internally by Q3DockWindow. You shouldn't
       
   673     need to call it yourself.
       
   674 */
       
   675 
       
   676 void Q3DockArea::moveDockWindow(Q3DockWindow *w, const QPoint &p, const QRect &r, bool swap)
       
   677 {
       
   678     invalidateFixedSizes();
       
   679     int mse = -10;
       
   680     bool hasResizable = false;
       
   681     for (int i = 0; i < dockWindows.size(); ++i) {
       
   682         Q3DockWindow *dw = dockWindows.at(i);
       
   683         if (dw->isHidden())
       
   684             continue;
       
   685         if (dw->isResizeEnabled())
       
   686             hasResizable = true;
       
   687         if (orientation() != Qt::Horizontal)
       
   688             mse = qMax(qMax(dw->fixedExtent().width(), dw->width()), mse);
       
   689         else
       
   690             mse = qMax(qMax(dw->fixedExtent().height(), dw->height()), mse);
       
   691     }
       
   692     if (!hasResizable && w->isResizeEnabled()) {
       
   693         if (orientation() != Qt::Horizontal)
       
   694             mse = qMax(w->fixedExtent().width(), mse);
       
   695         else
       
   696             mse = qMax(w->fixedExtent().height(), mse);
       
   697     }
       
   698 
       
   699     Q3DockWindow *dockWindow = 0;
       
   700     int dockWindowIndex = findDockWindow(w);
       
   701     QList<Q3DockWindow *> lineStarts = layout->lineStarts();
       
   702     QList<QRect> lines = layout->lineList();
       
   703     bool wasAloneInLine = false;
       
   704     QPoint pos = mapFromGlobal(p);
       
   705     int line = lineOf(dockWindowIndex);
       
   706     QRect lr;
       
   707     if (line < lines.size())
       
   708         lr = lines.at(line);
       
   709     if (dockWindowIndex != -1) {
       
   710         if (lineStarts.contains(w)
       
   711             && ((dockWindowIndex < dockWindows.count() - 1
       
   712                  && lineStarts.contains(dockWindows.at(dockWindowIndex + 1)))
       
   713                 || dockWindowIndex == dockWindows.count() - 1))
       
   714             wasAloneInLine = true;
       
   715         dockWindow = dockWindows.takeAt(dockWindowIndex);
       
   716         if (!wasAloneInLine) { // only do the pre-layout if the widget isn't the only one in its line
       
   717             if (lineStarts.contains(dockWindow) && dockWindowIndex < dockWindows.count())
       
   718                 dockWindows.at(dockWindowIndex)->setNewLine(true);
       
   719             layout->layoutItems(QRect(0, 0, width(), height()), true);
       
   720         }
       
   721     } else {
       
   722         dockWindow = w;
       
   723         bool vis = dockWindow->isVisible();
       
   724         dockWindow->setParent(this);
       
   725         dockWindow->move(0, 0);
       
   726         if(vis)
       
   727             dockWindow->show();
       
   728         if (swap)
       
   729             dockWindow->resize(dockWindow->height(), dockWindow->width());
       
   730         w->installEventFilter(this);
       
   731     }
       
   732 
       
   733     lineStarts = layout->lineStarts();
       
   734     lines = layout->lineList();
       
   735 
       
   736     QRect rect = QRect(mapFromGlobal(r.topLeft()), r.size());
       
   737     if (orientation() == Qt::Horizontal && QApplication::reverseLayout()) {
       
   738         rect = QRect(width() - rect.x() - rect.width(), rect.y(), rect.width(), rect.height());
       
   739         pos.rx() = width() - pos.x();
       
   740     }
       
   741     dockWindow->setOffset(point_pos(rect.topLeft(), orientation()));
       
   742     if (orientation() == Qt::Horizontal) {
       
   743         int offs = dockWindow->offset();
       
   744         if (width() - offs < dockWindow->minimumWidth())
       
   745             dockWindow->setOffset(width() - dockWindow->minimumWidth());
       
   746     } else {
       
   747         int offs = dockWindow->offset();
       
   748         if (height() - offs < dockWindow->minimumHeight())
       
   749             dockWindow->setOffset(height() - dockWindow->minimumHeight());
       
   750     }
       
   751 
       
   752     if (dockWindows.isEmpty()) {
       
   753         dockWindows.append(dockWindow);
       
   754     } else {
       
   755         int dockLine = -1;
       
   756         bool insertLine = false;
       
   757         int i = 0;
       
   758         QRect lineRect;
       
   759         // find the line which we touched with the mouse
       
   760         for (QList<QRect>::Iterator it = lines.begin(); it != lines.end(); ++it, ++i) {
       
   761             if (point_pos(pos, orientation(), true) >= point_pos((*it).topLeft(), orientation(), true) &&
       
   762                  point_pos(pos, orientation(), true) <= point_pos((*it).topLeft(), orientation(), true) +
       
   763                  size_extent((*it).size(), orientation(), true)) {
       
   764                 dockLine = i;
       
   765                 lineRect = *it;
       
   766                 break;
       
   767             }
       
   768         }
       
   769         if (dockLine == -1) { // outside the dock...
       
   770             insertLine = true;
       
   771             if (point_pos(pos, orientation(), true) < 0) // insert as first line
       
   772                 dockLine = 0;
       
   773             else
       
   774                 dockLine = (int)lines.count(); // insert after the last line ### size_t/int cast
       
   775         } else { // inside the dock (we have found a dockLine)
       
   776             if (point_pos(pos, orientation(), true) <
       
   777                  point_pos(lineRect.topLeft(), orientation(), true) + 4) {        // mouse was at the very beginning of the line
       
   778                 insertLine = true;                                        // insert a new line before that with the docking widget
       
   779             } else if (point_pos(pos, orientation(), true) >
       
   780                         point_pos(lineRect.topLeft(), orientation(), true) +
       
   781                         size_extent(lineRect.size(), orientation(), true) - 4) {        // mouse was at the very and of the line
       
   782                 insertLine = true;                                                // insert a line after that with the docking widget
       
   783                 dockLine++;
       
   784             }
       
   785         }
       
   786 
       
   787         if (!insertLine && wasAloneInLine && lr.contains(pos)) // if we are alone in a line and just moved in there, re-insert it
       
   788             insertLine = true;
       
   789 
       
   790 #if defined(QDOCKAREA_DEBUG)
       
   791         qDebug("insert in line %d, and insert that line: %d", dockLine, insertLine);
       
   792         qDebug("     (btw, we have %d lines)", lines.count());
       
   793 #endif
       
   794         Q3DockWindow *dw = 0;
       
   795         if (dockLine >= (int)lines.count()) { // insert after last line
       
   796             dockWindows.append(dockWindow);
       
   797             dockWindow->setNewLine(true);
       
   798 #if defined(QDOCKAREA_DEBUG)
       
   799             qDebug("insert at the end");
       
   800 #endif
       
   801         } else if (dockLine == 0 && insertLine) { // insert before first line
       
   802             dockWindows.insert(0, dockWindow);
       
   803             dockWindows.at(1)->setNewLine(true);
       
   804 #if defined(QDOCKAREA_DEBUG)
       
   805             qDebug("insert at the begin");
       
   806 #endif
       
   807         } else { // insert somewhere in between
       
   808             // make sure each line start has a new line
       
   809             for (int i = 0; i < lineStarts.size(); ++i) {
       
   810                 dw = lineStarts.at(i);
       
   811                 dw->setNewLine(true);
       
   812             }
       
   813 
       
   814             // find the index of the first widget in the search line
       
   815             int searchLine = dockLine;
       
   816 #if defined(QDOCKAREA_DEBUG)
       
   817             qDebug("search line start of %d", searchLine);
       
   818 #endif
       
   819             Q3DockWindow *lsw = lineStarts.at(searchLine);
       
   820             int index = dockWindows.indexOf(lsw);
       
   821             if (index == -1) { // the linestart widget hasn't been found, try to find it harder
       
   822                 if (lsw == w && dockWindowIndex <= dockWindows.count())
       
   823                     index = dockWindowIndex;
       
   824                 else
       
   825                     index = 0;
       
   826             }
       
   827 #if defined(QDOCKAREA_DEBUG)
       
   828             qDebug("     which starts at %d", index);
       
   829 #endif
       
   830             if (!insertLine) { // if we insert the docking widget in the existing line
       
   831                 // find the index for the widget
       
   832                 bool inc = true;
       
   833                 bool firstTime = true;
       
   834                 for (int i = index; i < dockWindows.size(); ++i) {
       
   835                     dw = dockWindows.at(i);
       
   836                     if (orientation() == Qt::Horizontal)
       
   837                         dw->setFixedExtentWidth(-1);
       
   838                     else
       
   839                         dw->setFixedExtentHeight(-1);
       
   840                     if (!firstTime && lineStarts.contains(dw)) // we are in the next line, so break
       
   841                         break;
       
   842                     if (point_pos(pos, orientation()) <
       
   843                          point_pos(fix_pos(dw), orientation()) + size_extent(dw->size(), orientation()) / 2) {
       
   844                         inc = false;
       
   845                     }
       
   846                     if (inc)
       
   847                         index++;
       
   848                     firstTime = false;
       
   849                 }
       
   850 #if defined(QDOCKAREA_DEBUG)
       
   851                 qDebug("insert at index: %d", index);
       
   852 #endif
       
   853                 // if we insert it just before a widget which has a new line, transfer the newline to the docking widget
       
   854                 // but not if we didn't only mave a widget in its line which was alone in the line before
       
   855                 if (!(wasAloneInLine && lr.contains(pos))
       
   856                      && index >= 0 && index < dockWindows.count() &&
       
   857                      dockWindows.at(index)->newLine() && lineOf(index) == dockLine) {
       
   858 #if defined(QDOCKAREA_DEBUG)
       
   859                     qDebug("get rid of the old newline and get me one");
       
   860 #endif
       
   861                     dockWindows.at(index)->setNewLine(false);
       
   862                     dockWindow->setNewLine(true);
       
   863                 } else if (wasAloneInLine && lr.contains(pos)) {
       
   864                     dockWindow->setNewLine(true);
       
   865                 } else { // if we are somewhere in a line, get rid of the newline
       
   866                     dockWindow->setNewLine(false);
       
   867                 }
       
   868             } else { // insert in a new line, so make sure the dock widget and the widget which will be after it have a newline
       
   869 #if defined(QDOCKAREA_DEBUG)
       
   870                 qDebug("insert a new line");
       
   871 #endif
       
   872                 if (index < dockWindows.count()) {
       
   873 #if defined(QDOCKAREA_DEBUG)
       
   874                     qDebug("give the widget at %d a newline", index);
       
   875 #endif
       
   876                     Q3DockWindow* nldw = dockWindows.at(index);
       
   877                     if (nldw)
       
   878                         nldw->setNewLine(true);
       
   879                 }
       
   880 #if defined(QDOCKAREA_DEBUG)
       
   881                 qDebug("give me a newline");
       
   882 #endif
       
   883                 dockWindow->setNewLine(true);
       
   884             }
       
   885             // finally insert the widget
       
   886             dockWindows.insert(index, dockWindow);
       
   887         }
       
   888     }
       
   889 
       
   890     if (mse != -10 && w->isResizeEnabled()) {
       
   891         if (orientation() != Qt::Horizontal)
       
   892             w->setFixedExtentWidth(qMin(qMax(w->minimumWidth(), mse), w->sizeHint().width()));
       
   893         else
       
   894             w->setFixedExtentHeight(qMin(qMax(w->minimumHeight(), mse), w->sizeHint().height()));
       
   895     }
       
   896 
       
   897     updateLayout();
       
   898     setSizePolicy(QSizePolicy(orientation() == Qt::Horizontal ? QSizePolicy::Expanding : QSizePolicy::Minimum,
       
   899                                 orientation() == Qt::Vertical ? QSizePolicy::Expanding : QSizePolicy::Minimum));
       
   900 }
       
   901 
       
   902 /*!
       
   903     Removes the dock window \a w from the dock area. If \a
       
   904     makeFloating is true, \a w gets floated, and if \a swap is true,
       
   905     the orientation of \a w gets swapped. If \a fixNewLines is true
       
   906     (the default) newlines in the area will be fixed.
       
   907 
       
   908     You should never need to call this function yourself. Use
       
   909     Q3DockWindow::dock() and Q3DockWindow::undock() instead.
       
   910 */
       
   911 
       
   912 void Q3DockArea::removeDockWindow(Q3DockWindow *w, bool makeFloating, bool swap, bool fixNewLines)
       
   913 {
       
   914     w->removeEventFilter(this);
       
   915     Q3DockWindow *dockWindow = 0;
       
   916     int i = findDockWindow(w);
       
   917     if (i == -1)
       
   918         return;
       
   919     dockWindow = dockWindows.at(i);
       
   920     dockWindows.removeAt(i);
       
   921     QList<Q3DockWindow *> lineStarts = layout->lineStarts();
       
   922     if (fixNewLines && lineStarts.contains(dockWindow) && i < dockWindows.count())
       
   923         dockWindows.at(i)->setNewLine(true);
       
   924     if (makeFloating) {
       
   925         QWidget *p = parentWidget() ? parentWidget() : window();
       
   926         dockWindow->setParent(p, Qt::WType_Dialog | Qt::WStyle_Customize | Qt::WStyle_NoBorder | Qt::WStyle_Tool);
       
   927         dockWindow->move(0, 0);
       
   928     }
       
   929     if (swap)
       
   930         dockWindow->resize(dockWindow->height(), dockWindow->width());
       
   931     updateLayout();
       
   932     if (dockWindows.isEmpty())
       
   933         setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
       
   934 }
       
   935 
       
   936 int Q3DockArea::findDockWindow(Q3DockWindow *w)
       
   937 {
       
   938     return dockWindows.indexOf(w);
       
   939 }
       
   940 
       
   941 void Q3DockArea::updateLayout()
       
   942 {
       
   943     layout->invalidate();
       
   944     layout->activate();
       
   945 }
       
   946 
       
   947 /*! \reimp
       
   948  */
       
   949 
       
   950 bool Q3DockArea::eventFilter(QObject *o, QEvent *e)
       
   951 {
       
   952     if (e->type() == QEvent::Close) {
       
   953         if (qobject_cast<Q3DockWindow*>(o)) {
       
   954             o->removeEventFilter(this);
       
   955             QApplication::sendEvent(o, e);
       
   956             if (((QCloseEvent*)e)->isAccepted())
       
   957                 removeDockWindow((Q3DockWindow*)o, false, false);
       
   958             return true;
       
   959         }
       
   960     }
       
   961     return false;
       
   962 }
       
   963 
       
   964 /*! \internal
       
   965 
       
   966     Invalidates the offset of the next dock window in the dock area.
       
   967  */
       
   968 
       
   969 void Q3DockArea::invalidNextOffset(Q3DockWindow *dw)
       
   970 {
       
   971     int i = dockWindows.indexOf(dw);
       
   972     if (i == -1 || i >= (int)dockWindows.count() - 1)
       
   973         return;
       
   974     if ((dw = dockWindows.at(++i)))
       
   975         dw->setOffset(0);
       
   976 }
       
   977 
       
   978 /*!
       
   979     \property Q3DockArea::count
       
   980     \brief the number of dock windows in the dock area
       
   981 */
       
   982 int Q3DockArea::count() const
       
   983 {
       
   984     return dockWindows.count();
       
   985 }
       
   986 
       
   987 /*!
       
   988     \property Q3DockArea::empty
       
   989     \brief whether the dock area is empty
       
   990 */
       
   991 
       
   992 bool Q3DockArea::isEmpty() const
       
   993 {
       
   994     return dockWindows.isEmpty();
       
   995 }
       
   996 
       
   997 
       
   998 /*!
       
   999     Returns a list of the dock windows in the dock area.
       
  1000 */
       
  1001 
       
  1002 QList<Q3DockWindow *> Q3DockArea::dockWindowList() const
       
  1003 {
       
  1004     return dockWindows;
       
  1005 }
       
  1006 
       
  1007 /*!
       
  1008     Lines up the dock windows in this dock area to minimize wasted
       
  1009     space. If \a keepNewLines is true, only space within lines is
       
  1010     cleaned up. If \a keepNewLines is false the number of lines might
       
  1011     be changed.
       
  1012 */
       
  1013 
       
  1014 void Q3DockArea::lineUp(bool keepNewLines)
       
  1015 {
       
  1016     for (int i = 0; i < dockWindows.size(); ++i) {
       
  1017         Q3DockWindow *dw = dockWindows.at(i);
       
  1018         dw->setOffset(0);
       
  1019         if (!keepNewLines)
       
  1020             dw->setNewLine(false);
       
  1021     }
       
  1022     layout->activate();
       
  1023 }
       
  1024 
       
  1025 Q3DockArea::DockWindowData *Q3DockArea::dockWindowData(Q3DockWindow *w)
       
  1026 {
       
  1027     DockWindowData *data = new DockWindowData;
       
  1028     data->index = findDockWindow(w);
       
  1029     if (data->index == -1) {
       
  1030         delete data;
       
  1031         return 0;
       
  1032     }
       
  1033     QList<Q3DockWindow *> lineStarts = layout->lineStarts();
       
  1034     int i = -1;
       
  1035     for (int j = 0; j < dockWindows.size(); ++j) {
       
  1036         Q3DockWindow *dw = dockWindows.at(j);
       
  1037         if (lineStarts.contains(dw))
       
  1038             ++i;
       
  1039         if (dw == w)
       
  1040             break;
       
  1041     }
       
  1042     data->line = i;
       
  1043     data->offset = point_pos(QPoint(fix_x(w), w->y()), orientation());
       
  1044     data->area = this;
       
  1045     data->fixedExtent = w->fixedExtent();
       
  1046     return data;
       
  1047 }
       
  1048 
       
  1049 void Q3DockArea::dockWindow(Q3DockWindow *dockWindow, DockWindowData *data)
       
  1050 {
       
  1051     if (!data)
       
  1052         return;
       
  1053 
       
  1054     dockWindow->setParent(this);
       
  1055     dockWindow->move(0, 0);
       
  1056 
       
  1057     dockWindow->installEventFilter(this);
       
  1058     dockWindow->dockArea = this;
       
  1059     dockWindow->updateGui();
       
  1060 
       
  1061     if (dockWindows.isEmpty()) {
       
  1062         dockWindows.append(dockWindow);
       
  1063     } else {
       
  1064         QList<Q3DockWindow *> lineStarts = layout->lineStarts();
       
  1065         int index = 0;
       
  1066         if (lineStarts.count() > data->line)
       
  1067             index = dockWindows.indexOf(lineStarts.at(data->line));
       
  1068         if (index == -1)
       
  1069             index = 0;
       
  1070         bool firstTime = true;
       
  1071         int offset = data->offset;
       
  1072         for (int i = index; i < dockWindows.size(); ++i) {
       
  1073             Q3DockWindow *dw = dockWindows.at(i);
       
  1074             if (!firstTime && lineStarts.contains(dw))
       
  1075                 break;
       
  1076             if (offset <
       
  1077                  point_pos(fix_pos(dw), orientation()) + size_extent(dw->size(), orientation()) / 2)
       
  1078                 break;
       
  1079             index++;
       
  1080             firstTime = false;
       
  1081         }
       
  1082         if (index >= 0 && index < dockWindows.count() &&
       
  1083              dockWindows.at(index)->newLine() && lineOf(index) == data->line) {
       
  1084             dockWindows.at(index)->setNewLine(false);
       
  1085             dockWindow->setNewLine(true);
       
  1086         } else {
       
  1087             dockWindow->setNewLine(false);
       
  1088         }
       
  1089 
       
  1090         dockWindows.insert(index, dockWindow);
       
  1091     }
       
  1092     dockWindow->show();
       
  1093 
       
  1094     dockWindow->setFixedExtentWidth(data->fixedExtent.width());
       
  1095     dockWindow->setFixedExtentHeight(data->fixedExtent.height());
       
  1096 
       
  1097     updateLayout();
       
  1098     setSizePolicy(QSizePolicy(orientation() == Qt::Horizontal ? QSizePolicy::Expanding : QSizePolicy::Minimum,
       
  1099                                 orientation() == Qt::Vertical ? QSizePolicy::Expanding : QSizePolicy::Minimum));
       
  1100 
       
  1101 }
       
  1102 
       
  1103 /*!
       
  1104     Returns true if dock window \a dw could be docked into the dock
       
  1105     area; otherwise returns false.
       
  1106 
       
  1107     \sa setAcceptDockWindow()
       
  1108 */
       
  1109 
       
  1110 bool Q3DockArea::isDockWindowAccepted(Q3DockWindow *dw)
       
  1111 {
       
  1112     if (!dw)
       
  1113         return false;
       
  1114     if (forbiddenWidgets.contains(dw))
       
  1115         return false;
       
  1116 
       
  1117     Q3MainWindow *mw = qobject_cast<Q3MainWindow*>(parentWidget());
       
  1118     if (!mw)
       
  1119         return true;
       
  1120     if (!mw->hasDockWindow(dw))
       
  1121         return false;
       
  1122     if (!mw->isDockEnabled(this))
       
  1123         return false;
       
  1124     if (!mw->isDockEnabled(dw, this))
       
  1125         return false;
       
  1126     return true;
       
  1127 }
       
  1128 
       
  1129 /*!
       
  1130     If \a accept is true, dock window \a dw can be docked in the dock
       
  1131     area. If \a accept is false, dock window \a dw cannot be docked in
       
  1132     the dock area.
       
  1133 
       
  1134     \sa isDockWindowAccepted()
       
  1135 */
       
  1136 
       
  1137 void Q3DockArea::setAcceptDockWindow(Q3DockWindow *dw, bool accept)
       
  1138 {
       
  1139     if (accept)
       
  1140         forbiddenWidgets.removeAll(dw);
       
  1141     else if (forbiddenWidgets.contains(dw))
       
  1142         forbiddenWidgets.append(dw);
       
  1143 }
       
  1144 
       
  1145 void Q3DockArea::invalidateFixedSizes()
       
  1146 {
       
  1147     for (int i = 0; i < dockWindows.size(); ++i) {
       
  1148         Q3DockWindow *dw = dockWindows.at(i);
       
  1149         if (orientation() == Qt::Horizontal)
       
  1150             dw->setFixedExtentWidth(-1);
       
  1151         else
       
  1152             dw->setFixedExtentHeight(-1);
       
  1153     }
       
  1154 }
       
  1155 
       
  1156 int Q3DockArea::maxSpace(int hint, Q3DockWindow *dw)
       
  1157 {
       
  1158     int index = findDockWindow(dw);
       
  1159     if (index == -1 || index + 1 >= (int)dockWindows.count()) {
       
  1160         if (orientation() == Qt::Horizontal)
       
  1161             return dw->width();
       
  1162         return dw->height();
       
  1163     }
       
  1164 
       
  1165     Q3DockWindow *w = 0;
       
  1166     int i = 0;
       
  1167     do {
       
  1168         w = dockWindows.at(index + (++i));
       
  1169     } while (i + 1 < (int)dockWindows.count() && (!w || w->isHidden()));
       
  1170     if (!w || !w->isResizeEnabled() || i >= (int)dockWindows.count()) {
       
  1171         if (orientation() == Qt::Horizontal)
       
  1172             return dw->width();
       
  1173         return dw->height();
       
  1174     }
       
  1175     int min = 0;
       
  1176     Q3ToolBar *tb = qobject_cast<Q3ToolBar*>(w);
       
  1177     if (orientation() == Qt::Horizontal) {
       
  1178         w->setFixedExtentWidth(-1);
       
  1179         if (!tb)
       
  1180             min = qMax(w->minimumSize().width(), w->minimumSizeHint().width());
       
  1181         else
       
  1182             min = w->sizeHint().width();
       
  1183     } else {
       
  1184         w->setFixedExtentHeight(-1);
       
  1185         if (!tb)
       
  1186             min = qMax(w->minimumSize().height(), w->minimumSizeHint().height());
       
  1187         else
       
  1188             min = w->sizeHint().height();
       
  1189     }
       
  1190 
       
  1191     int diff = hint - (orientation() == Qt::Horizontal ? dw->width() : dw->height());
       
  1192 
       
  1193     if ((orientation() == Qt::Horizontal ? w->width() : w->height()) - diff < min)
       
  1194         hint = (orientation() == Qt::Horizontal ? dw->width() : dw->height()) + (orientation() == Qt::Horizontal ? w->width() : w->height()) - min;
       
  1195 
       
  1196     diff = hint - (orientation() == Qt::Horizontal ? dw->width() : dw->height());
       
  1197     if (orientation() == Qt::Horizontal)
       
  1198         w->setFixedExtentWidth(w->width() - diff);
       
  1199     else
       
  1200         w->setFixedExtentHeight(w->height() - diff);
       
  1201     return hint;
       
  1202 }
       
  1203 
       
  1204 void Q3DockArea::setFixedExtent(int d, Q3DockWindow *dw)
       
  1205 {
       
  1206     QList<Q3DockWindow *> lst;
       
  1207     for (int i = 0; i < dockWindows.size(); ++i) {
       
  1208         Q3DockWindow *w = dockWindows.at(i);
       
  1209         if (w->isHidden())
       
  1210             continue;
       
  1211         if (orientation() == Qt::Horizontal) {
       
  1212             if (dw->y() != w->y())
       
  1213                 continue;
       
  1214         } else {
       
  1215             if (dw->x() != w->x())
       
  1216                 continue;
       
  1217         }
       
  1218         if (orientation() == Qt::Horizontal)
       
  1219             d = qMax(d, w->minimumHeight());
       
  1220         else
       
  1221             d = qMax(d, w->minimumWidth());
       
  1222         if (w->isResizeEnabled())
       
  1223             lst.append(w);
       
  1224     }
       
  1225     for (int i = 0; i < lst.size(); ++i) {
       
  1226         Q3DockWindow *w = lst.at(i);
       
  1227         if (orientation() == Qt::Horizontal)
       
  1228             w->setFixedExtentHeight(d);
       
  1229         else
       
  1230             w->setFixedExtentWidth(d);
       
  1231     }
       
  1232 }
       
  1233 
       
  1234 bool Q3DockArea::isLastDockWindow(Q3DockWindow *dw)
       
  1235 {
       
  1236     int i = dockWindows.indexOf(dw);
       
  1237     if (i == -1 || i >= (int)dockWindows.count() - 1)
       
  1238         return true;
       
  1239     Q3DockWindow *w = 0;
       
  1240     if ((w = dockWindows.at(++i))) {
       
  1241         if (orientation() == Qt::Horizontal && dw->y() < w->y())
       
  1242             return true;
       
  1243         if (orientation() == Qt::Vertical && dw->x() < w->x())
       
  1244             return true;
       
  1245     } else {
       
  1246         return true;
       
  1247     }
       
  1248     return false;
       
  1249 }
       
  1250 
       
  1251 #ifndef QT_NO_TEXTSTREAM
       
  1252 
       
  1253 /*!
       
  1254     \relates Q3DockArea
       
  1255 
       
  1256     Writes the layout of the dock windows in dock area \a dockArea to
       
  1257     the text stream \a ts.
       
  1258 */
       
  1259 
       
  1260 QTextStream &operator<<(QTextStream &ts, const Q3DockArea &dockArea)
       
  1261 {
       
  1262     QString str;
       
  1263     QList<Q3DockWindow *> l = dockArea.dockWindowList();
       
  1264 
       
  1265     for (int i = 0; i < l.size(); ++i) {
       
  1266         Q3DockWindow *dw = l.at(i);
       
  1267         str += QLatin1Char('[') + QString(dw->windowTitle()) + QLatin1Char(',') + QString::number((int)dw->offset()) +
       
  1268                QLatin1Char(',') + QString::number((int)dw->newLine()) + QLatin1Char(',') + QString::number(dw->fixedExtent().width()) +
       
  1269                QLatin1Char(',') + QString::number(dw->fixedExtent().height()) + QLatin1Char(',') + QString::number((int)!dw->isHidden()) + QLatin1Char(']');
       
  1270     }
       
  1271     ts << str << endl;
       
  1272 
       
  1273     return ts;
       
  1274 }
       
  1275 
       
  1276 /*!
       
  1277     \relates Q3DockArea
       
  1278 
       
  1279     Reads the layout description of the dock windows in dock area \a
       
  1280     dockArea from the text stream \a ts and restores it. The layout
       
  1281     description must have been previously written by the operator<<()
       
  1282     function.
       
  1283 */
       
  1284 
       
  1285 QTextStream &operator>>(QTextStream &ts, Q3DockArea &dockArea)
       
  1286 {
       
  1287     QString s = ts.readLine();
       
  1288 
       
  1289     QString name, offset, newLine, width, height, visible;
       
  1290 
       
  1291     enum State { Pre, Name, Offset, NewLine, Width, Height, Visible, Post };
       
  1292     int state = Pre;
       
  1293     QChar c;
       
  1294     QList<Q3DockWindow *> l = dockArea.dockWindowList();
       
  1295 
       
  1296     for (int i = 0; i < s.length(); ++i) {
       
  1297         c = s[i];
       
  1298         if (state == Pre && c == QLatin1Char('[')) {
       
  1299             state++;
       
  1300             continue;
       
  1301         }
       
  1302         if (c == QLatin1Char(',') &&
       
  1303              (state == Name || state == Offset || state == NewLine || state == Width || state == Height)) {
       
  1304             state++;
       
  1305             continue;
       
  1306         }
       
  1307         if (state == Visible && c == QLatin1Char(']')) {
       
  1308             for (int j = 0; j < l.size(); ++j) {
       
  1309                 Q3DockWindow *dw = l.at(j);
       
  1310                 if (QString(dw->windowTitle()) == name) {
       
  1311                     dw->setNewLine((bool)newLine.toInt());
       
  1312                     dw->setOffset(offset.toInt());
       
  1313                     dw->setFixedExtentWidth(width.toInt());
       
  1314                     dw->setFixedExtentHeight(height.toInt());
       
  1315                     if (!(bool)visible.toInt())
       
  1316                         dw->hide();
       
  1317                     else
       
  1318                         dw->show();
       
  1319                     break;
       
  1320                 }
       
  1321             }
       
  1322 
       
  1323             name = offset = newLine = width = height = visible = QLatin1String("");
       
  1324 
       
  1325             state = Pre;
       
  1326             continue;
       
  1327         }
       
  1328         if (state == Name)
       
  1329             name += c;
       
  1330         else if (state == Offset)
       
  1331             offset += c;
       
  1332         else if (state == NewLine)
       
  1333             newLine += c;
       
  1334         else if (state == Width)
       
  1335             width += c;
       
  1336         else if (state == Height)
       
  1337             height += c;
       
  1338         else if (state == Visible)
       
  1339             visible += c;
       
  1340     }
       
  1341 
       
  1342     dockArea.QWidget::layout()->invalidate();
       
  1343     dockArea.QWidget::layout()->activate();
       
  1344     return ts;
       
  1345 }
       
  1346 #endif
       
  1347 
       
  1348 QT_END_NAMESPACE
       
  1349 
       
  1350 #endif //QT_NO_MAINWINDOW