src/qt3support/widgets/q3dockwindow.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 "q3dockwindow.h"
       
    43 
       
    44 #ifndef QT_NO_MAINWINDOW
       
    45 #include "qapplication.h"
       
    46 #include "qcursor.h"
       
    47 #include "qdesktopwidget.h"
       
    48 #include "q3dockarea.h"
       
    49 #include "qevent.h"
       
    50 #include "qlayout.h"
       
    51 #include "q3mainwindow.h"
       
    52 #include "qpainter.h"
       
    53 #include "qpointer.h"
       
    54 #include "qstyle.h"
       
    55 #include "qstyleoption.h"
       
    56 #include "qtimer.h"
       
    57 #include "q3toolbar.h"
       
    58 #include "qtoolbutton.h"
       
    59 #include "qtooltip.h"
       
    60 #include <private/q3titlebar_p.h>
       
    61 #include <private/qwidgetresizehandler_p.h>
       
    62 #include <qrubberband.h>
       
    63 #include <qdebug.h>
       
    64 
       
    65 QT_BEGIN_NAMESPACE
       
    66 
       
    67 #ifdef Q_WS_MAC
       
    68 static bool default_opaque = true;
       
    69 #else
       
    70 static bool default_opaque = false;
       
    71 #endif
       
    72 
       
    73 class Q3DockWindowPrivate
       
    74 {
       
    75 };
       
    76 
       
    77 class Q3DockWindowResizeHandle : public QWidget
       
    78 {
       
    79     Q_OBJECT
       
    80 
       
    81 public:
       
    82     Q3DockWindowResizeHandle(Qt::Orientation o, QWidget *parent, Q3DockWindow *w, const char* /*name*/=0);
       
    83     void setOrientation(Qt::Orientation o);
       
    84     Qt::Orientation orientation() const { return orient; }
       
    85 
       
    86     QSize sizeHint() const;
       
    87 
       
    88 protected:
       
    89     void paintEvent(QPaintEvent *);
       
    90     void mouseMoveEvent(QMouseEvent *);
       
    91     void mousePressEvent(QMouseEvent *);
       
    92     void mouseReleaseEvent(QMouseEvent *);
       
    93     bool event(QEvent *event);
       
    94 
       
    95 private:
       
    96     void startLineDraw();
       
    97     void endLineDraw();
       
    98     void drawLine(const QPoint &globalPos);
       
    99 
       
   100 private:
       
   101     Qt::Orientation orient;
       
   102     bool mousePressed;
       
   103     QRubberBand *rubberBand;
       
   104     QPoint lastPos, firstPos;
       
   105     Q3DockWindow *dockWindow;
       
   106     bool mouseOver;
       
   107 };
       
   108 
       
   109 Q3DockWindowResizeHandle::Q3DockWindowResizeHandle(Qt::Orientation o, QWidget *parent,
       
   110                                                   Q3DockWindow *w, const char *)
       
   111     : QWidget(parent, "qt_dockwidget_internal"), mousePressed(false), rubberBand(0), dockWindow(w),
       
   112       mouseOver(false)
       
   113 {
       
   114     setOrientation(o);
       
   115 }
       
   116 
       
   117 QSize Q3DockWindowResizeHandle::sizeHint() const
       
   118 {
       
   119     QStyleOptionQ3DockWindow opt;
       
   120     opt.init(this);
       
   121     if (!dockWindow->area() || dockWindow->area()->orientation() == Qt::Horizontal)
       
   122         opt.state |= QStyle::State_Horizontal;
       
   123 
       
   124     opt.rect = rect();
       
   125     opt.docked = dockWindow->area();
       
   126     opt.closeEnabled = dockWindow->isCloseEnabled();
       
   127     int sw = 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, &opt, this) / 3;
       
   128     return (style()->sizeFromContents(QStyle::CT_Q3DockWindow, &opt, QSize(sw, sw), this).expandedTo(QApplication::globalStrut()));
       
   129 }
       
   130 
       
   131 void Q3DockWindowResizeHandle::setOrientation(Qt::Orientation o)
       
   132 {
       
   133     orient = o;
       
   134     if (o == Qt::Horizontal) {
       
   135 #ifndef QT_NO_CURSOR
       
   136         setCursor(Qt::splitVCursor);
       
   137 #endif
       
   138         setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
       
   139     } else {
       
   140 #ifndef QT_NO_CURSOR
       
   141         setCursor(Qt::splitHCursor);
       
   142 #endif
       
   143         setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding));
       
   144     }
       
   145 }
       
   146 
       
   147 void Q3DockWindowResizeHandle::mousePressEvent(QMouseEvent *e)
       
   148 {
       
   149     e->ignore();
       
   150     if (e->button() != Qt::LeftButton)
       
   151         return;
       
   152     e->accept();
       
   153     mousePressed = true;
       
   154     if (!dockWindow->opaqueMoving())
       
   155         startLineDraw();
       
   156     lastPos = firstPos = e->globalPos();
       
   157     if (!dockWindow->opaqueMoving())
       
   158         drawLine(e->globalPos());
       
   159 }
       
   160 
       
   161 void Q3DockWindowResizeHandle::mouseMoveEvent(QMouseEvent *e)
       
   162 {
       
   163     if (!mousePressed)
       
   164         return;
       
   165     if (!dockWindow->opaqueMoving()) {
       
   166         if (orientation() != dockWindow->area()->orientation()) {
       
   167             if (orientation() == Qt::Horizontal) {
       
   168                 int minpos = dockWindow->area()->mapToGlobal(QPoint(0, 0)).y();
       
   169                 int maxpos = dockWindow->area()->mapToGlobal(QPoint(0, 0)).y() + dockWindow->area()->height();
       
   170                 if (e->globalPos().y() < minpos || e->globalPos().y() > maxpos)
       
   171                     return;
       
   172             } else {
       
   173                 int minpos = dockWindow->area()->mapToGlobal(QPoint(0, 0)).x();
       
   174                 int maxpos = dockWindow->area()->mapToGlobal(QPoint(0, 0)).x() + dockWindow->area()->width();
       
   175                 if (e->globalPos().x() < minpos || e->globalPos().x() > maxpos)
       
   176                     return;
       
   177             }
       
   178         } else {
       
   179             QWidget *w = dockWindow->area()->window();
       
   180             if (w) {
       
   181                 if (orientation() == Qt::Horizontal) {
       
   182                     int minpos = w->mapToGlobal(QPoint(0, 0)).y();
       
   183                     int maxpos = w->mapToGlobal(QPoint(0, 0)).y() + w->height();
       
   184                     if (e->globalPos().y() < minpos || e->globalPos().y() > maxpos)
       
   185                         return;
       
   186                 } else {
       
   187                     int minpos = w->mapToGlobal(QPoint(0, 0)).x();
       
   188                     int maxpos = w->mapToGlobal(QPoint(0, 0)).x() + w->width();
       
   189                     if (e->globalPos().x() < minpos || e->globalPos().x() > maxpos)
       
   190                         return;
       
   191                 }
       
   192             }
       
   193         }
       
   194     }
       
   195 
       
   196     if (!dockWindow->opaqueMoving())
       
   197         drawLine(lastPos);
       
   198     lastPos = e->globalPos();
       
   199     if (dockWindow->opaqueMoving()) {
       
   200         mouseReleaseEvent(e);
       
   201         mousePressed = true;
       
   202         firstPos = e->globalPos();
       
   203     }
       
   204     if (!dockWindow->opaqueMoving())
       
   205         drawLine(e->globalPos());
       
   206 }
       
   207 
       
   208 void Q3DockWindowResizeHandle::mouseReleaseEvent(QMouseEvent *e)
       
   209 {
       
   210     if (mousePressed) {
       
   211         if (!dockWindow->opaqueMoving()) {
       
   212             drawLine(lastPos);
       
   213             endLineDraw();
       
   214         }
       
   215         if (orientation() != dockWindow->area()->orientation())
       
   216             dockWindow->area()->invalidNextOffset(dockWindow);
       
   217         if (orientation() == Qt::Horizontal) {
       
   218             int dy;
       
   219             if (dockWindow->area()->handlePosition() == Q3DockArea::Normal || orientation() != dockWindow->area()->orientation())
       
   220                 dy = e->globalPos().y() - firstPos.y();
       
   221             else
       
   222                 dy =  firstPos.y() - e->globalPos().y();
       
   223             int d = dockWindow->height() + dy;
       
   224             if (orientation() != dockWindow->area()->orientation()) {
       
   225                 dockWindow->setFixedExtentHeight(-1);
       
   226                 d = qMax(d, dockWindow->minimumHeight());
       
   227                 int ms = dockWindow->area()->maxSpace(d, dockWindow);
       
   228                 d = qMin(d, ms);
       
   229                 dockWindow->setFixedExtentHeight(d);
       
   230             } else {
       
   231                 dockWindow->area()->setFixedExtent(d, dockWindow);
       
   232             }
       
   233         } else {
       
   234             int dx;
       
   235             if (dockWindow->area()->handlePosition() == Q3DockArea::Normal || orientation() != dockWindow->area()->orientation())
       
   236                 dx = e->globalPos().x() - firstPos.x();
       
   237             else
       
   238                 dx = firstPos.x() - e->globalPos().x();
       
   239             int d = dockWindow->width() + dx;
       
   240             if (orientation() != dockWindow->area()->orientation()) {
       
   241                 dockWindow->setFixedExtentWidth(-1);
       
   242                 d = qMax(d, dockWindow->minimumWidth());
       
   243                 int ms = dockWindow->area()->maxSpace(d, dockWindow);
       
   244                 d = qMin(d, ms);
       
   245                 dockWindow->setFixedExtentWidth(d);
       
   246             } else {
       
   247                 dockWindow->area()->setFixedExtent(d, dockWindow);
       
   248             }
       
   249         }
       
   250     }
       
   251 
       
   252     QApplication::postEvent(dockWindow->area(), new QEvent(QEvent::LayoutHint));
       
   253     mousePressed = false;
       
   254 }
       
   255 
       
   256 bool Q3DockWindowResizeHandle::event(QEvent *event)
       
   257 {
       
   258     switch (event->type()) {
       
   259     case QEvent::HoverEnter:
       
   260         if (!mouseOver) {
       
   261             mouseOver = true;
       
   262             update();
       
   263         }
       
   264         break;
       
   265     case QEvent::HoverLeave:
       
   266         if (mouseOver) {
       
   267             mouseOver = false;
       
   268             update();
       
   269         }
       
   270         break;
       
   271     default:
       
   272         break;
       
   273     }
       
   274     return QWidget::event(event);
       
   275 }
       
   276 
       
   277 void Q3DockWindowResizeHandle::paintEvent(QPaintEvent *)
       
   278 {
       
   279     QPainter p(this);
       
   280     QStyleOption opt(0);
       
   281     opt.init(this);
       
   282     if (orientation() == Qt::Horizontal)
       
   283         opt.state |= QStyle::State_Horizontal;
       
   284     style()->drawPrimitive(QStyle::PE_IndicatorDockWidgetResizeHandle, &opt, &p, this);
       
   285 }
       
   286 
       
   287 void Q3DockWindowResizeHandle::startLineDraw()
       
   288 {
       
   289     if (rubberBand)
       
   290         endLineDraw();
       
   291     rubberBand = new QRubberBand(QRubberBand::Line);
       
   292     rubberBand->setGeometry(-1, -1, 1, 1);
       
   293     rubberBand->show();
       
   294 }
       
   295 
       
   296 void Q3DockWindowResizeHandle::endLineDraw()
       
   297 {
       
   298     delete rubberBand;
       
   299     rubberBand = 0;
       
   300 }
       
   301 
       
   302 void Q3DockWindowResizeHandle::drawLine(const QPoint &globalPos)
       
   303 {
       
   304     QPoint start = mapToGlobal(QPoint(0, 0));
       
   305     QPoint starta = dockWindow->area()->mapToGlobal(QPoint(0, 0));
       
   306     QPoint end = globalPos;
       
   307     if (orientation() == Qt::Horizontal) {
       
   308         if (orientation() == dockWindow->orientation())
       
   309             rubberBand->setGeometry(starta.x(), end.y(), dockWindow->area()->width(), height());
       
   310         else
       
   311             rubberBand->setGeometry(start.x(), end.y(), width(), height());
       
   312     } else {
       
   313         if (orientation() == dockWindow->orientation())
       
   314             rubberBand->setGeometry(end.x(), starta.y(), width(), dockWindow->area()->height());
       
   315         else
       
   316             rubberBand->setGeometry(end.x(), start.y(), width(), height());
       
   317     }
       
   318 }
       
   319 
       
   320 static QPoint realWidgetPos(Q3DockWindow *w)
       
   321 {
       
   322     if (!w->parentWidget() || w->place() == Q3DockWindow::OutsideDock)
       
   323         return w->pos();
       
   324     return w->parentWidget()->mapToGlobal(w->geometry().topLeft());
       
   325 }
       
   326 
       
   327 class Q3DockWindowHandle : public QWidget
       
   328 {
       
   329     Q_OBJECT
       
   330     Q_PROPERTY(QString windowTitle READ windowTitle)
       
   331     friend class Q3DockWindow;
       
   332     friend class Q3DockWindowTitleBar;
       
   333 
       
   334 public:
       
   335     Q3DockWindowHandle(Q3DockWindow *dw);
       
   336     void updateGui();
       
   337 
       
   338     QSize minimumSizeHint() const;
       
   339     QSize minimumSize() const { return minimumSizeHint(); }
       
   340     QSize sizeHint() const { return minimumSize(); }
       
   341     void setOpaqueMoving(bool b) { opaque = b; }
       
   342 
       
   343     QString windowTitle() const { return dockWindow->windowTitle(); }
       
   344 
       
   345 signals:
       
   346     void doubleClicked();
       
   347 
       
   348 protected:
       
   349     void paintEvent(QPaintEvent *e);
       
   350     void resizeEvent(QResizeEvent *e);
       
   351     void mousePressEvent(QMouseEvent *e);
       
   352     void mouseMoveEvent(QMouseEvent *e);
       
   353     void mouseReleaseEvent(QMouseEvent *e);
       
   354     void mouseDoubleClickEvent(QMouseEvent *e);
       
   355     void keyPressEvent(QKeyEvent *e);
       
   356     void keyReleaseEvent(QKeyEvent *e);
       
   357     void changeEvent(QEvent *);
       
   358 
       
   359 private slots:
       
   360     void minimize();
       
   361 
       
   362 private:
       
   363     Q3DockWindow *dockWindow;
       
   364     QPoint offset;
       
   365     QToolButton *closeButton;
       
   366     QTimer *timer;
       
   367     uint opaque                : 1;
       
   368     uint mousePressed        : 1;
       
   369     uint hadDblClick        : 1;
       
   370     uint ctrlDown : 1;
       
   371     QPointer<QWidget> oldFocus;
       
   372 };
       
   373 
       
   374 class Q3DockWindowTitleBar : public Q3TitleBar
       
   375 {
       
   376     Q_OBJECT
       
   377     friend class Q3DockWindow;
       
   378     friend class Q3DockWindowHandle;
       
   379 
       
   380 public:
       
   381     Q3DockWindowTitleBar(Q3DockWindow *dw);
       
   382     void updateGui();
       
   383     void setOpaqueMoving(bool b) { opaque = b; }
       
   384 
       
   385 protected:
       
   386     void resizeEvent(QResizeEvent *e);
       
   387     void mousePressEvent(QMouseEvent *e);
       
   388     void mouseMoveEvent(QMouseEvent *e);
       
   389     void mouseReleaseEvent(QMouseEvent *e);
       
   390     void mouseDoubleClickEvent(QMouseEvent *e);
       
   391     void keyPressEvent(QKeyEvent *e);
       
   392     void keyReleaseEvent(QKeyEvent *e);
       
   393 
       
   394 private:
       
   395     Q3DockWindow *dockWindow;
       
   396     QPoint offset;
       
   397     uint mousePressed : 1;
       
   398     uint hadDblClick : 1;
       
   399     uint opaque : 1;
       
   400     uint ctrlDown : 1;
       
   401     QPointer<QWidget> oldFocus;
       
   402 
       
   403 };
       
   404 
       
   405 Q3DockWindowHandle::Q3DockWindowHandle(Q3DockWindow *dw)
       
   406     : QWidget(dw, "qt_dockwidget_internal"), dockWindow(dw),
       
   407       closeButton(0), opaque(default_opaque), mousePressed(false)
       
   408 {
       
   409     ctrlDown = false;
       
   410     timer = new QTimer(this);
       
   411     connect(timer, SIGNAL(timeout()), this, SLOT(minimize()));
       
   412 #ifdef Q_WS_WIN
       
   413     setCursor(Qt::SizeAllCursor);
       
   414 #endif
       
   415 }
       
   416 
       
   417 void Q3DockWindowHandle::paintEvent(QPaintEvent *e)
       
   418 {
       
   419     if (!dockWindow->dockArea && !opaque)
       
   420         return;
       
   421     QPainter p(this);
       
   422     QStyleOptionQ3DockWindow opt;
       
   423     opt.init(this);
       
   424     if (!dockWindow->area() || dockWindow->area()->orientation() == Qt::Horizontal)
       
   425         opt.state |= QStyle::State_Horizontal;
       
   426 
       
   427     opt.rect = rect();
       
   428     opt.docked = dockWindow->area();
       
   429     opt.closeEnabled = dockWindow->isCloseEnabled();
       
   430     opt.rect = QStyle::visualRect(opt.direction, opt.rect,
       
   431                                   style()->subElementRect(QStyle::SE_Q3DockWindowHandleRect, &opt, this));
       
   432     style()->drawPrimitive(QStyle::PE_IndicatorToolBarHandle, &opt, &p, this);
       
   433     QWidget::paintEvent(e);
       
   434 }
       
   435 
       
   436 void Q3DockWindowHandle::keyPressEvent(QKeyEvent *e)
       
   437 {
       
   438     if (!mousePressed)
       
   439         return;
       
   440     if (e->key() == Qt::Key_Control) {
       
   441         ctrlDown = true;
       
   442         dockWindow->handleMove(mapFromGlobal(QCursor::pos()) - offset, QCursor::pos(), !opaque);
       
   443     }
       
   444 }
       
   445 
       
   446 void Q3DockWindowHandle::keyReleaseEvent(QKeyEvent *e)
       
   447 {
       
   448     if (!mousePressed)
       
   449         return;
       
   450     if (e->key() == Qt::Key_Control) {
       
   451         ctrlDown = false;
       
   452         dockWindow->handleMove(mapFromGlobal(QCursor::pos()) - offset, QCursor::pos(), !opaque);
       
   453     }
       
   454 }
       
   455 
       
   456 void Q3DockWindowHandle::mousePressEvent(QMouseEvent *e)
       
   457 {
       
   458     if (!dockWindow->dockArea)
       
   459         return;
       
   460     ctrlDown = (e->state() & Qt::ControlButton) == Qt::ControlButton;
       
   461     oldFocus = qApp->focusWidget();
       
   462     setFocus();
       
   463     e->ignore();
       
   464     if (e->button() != Qt::LeftButton)
       
   465         return;
       
   466     e->accept();
       
   467     hadDblClick = false;
       
   468     mousePressed = true;
       
   469     offset = e->pos();
       
   470     dockWindow->startRectDraw(mapToGlobal(e->pos()), !opaque);
       
   471     if (!opaque)
       
   472         qApp->installEventFilter(dockWindow);
       
   473 }
       
   474 
       
   475 void Q3DockWindowHandle::mouseMoveEvent(QMouseEvent *e)
       
   476 {
       
   477     if (!mousePressed || e->pos() == offset)
       
   478         return;
       
   479     ctrlDown = (e->state() & Qt::ControlButton) == Qt::ControlButton;
       
   480     dockWindow->handleMove(e->pos() - offset, e->globalPos(), !opaque);
       
   481     if (opaque)
       
   482         dockWindow->updatePosition(e->globalPos());
       
   483 }
       
   484 
       
   485 void Q3DockWindowHandle::mouseReleaseEvent(QMouseEvent *e)
       
   486 {
       
   487     ctrlDown = false;
       
   488     qApp->removeEventFilter(dockWindow);
       
   489     if (oldFocus)
       
   490         oldFocus->setFocus();
       
   491     if (!mousePressed)
       
   492         return;
       
   493     dockWindow->endRectDraw(!opaque);
       
   494     mousePressed = false;
       
   495 #ifdef Q_WS_MAC
       
   496     releaseMouse();
       
   497 #endif
       
   498     if (!hadDblClick && offset == e->pos()) {
       
   499         timer->start(QApplication::doubleClickInterval(), true);
       
   500     } else if (!hadDblClick) {
       
   501         dockWindow->updatePosition(e->globalPos());
       
   502     }
       
   503     if (opaque)
       
   504         dockWindow->titleBar->mousePressed = false;
       
   505     if (dockWindow->parentWidget())
       
   506         QApplication::postEvent(dockWindow->parentWidget(), new QEvent(QEvent::LayoutHint));
       
   507 }
       
   508 
       
   509 void Q3DockWindowHandle::minimize()
       
   510 {
       
   511     if (!dockWindow->area())
       
   512         return;
       
   513 
       
   514     Q3MainWindow *mw = qobject_cast<Q3MainWindow*>(dockWindow->area()->parentWidget());
       
   515     if (mw && mw->isDockEnabled(dockWindow, Qt::DockMinimized))
       
   516         mw->moveDockWindow(dockWindow, Qt::DockMinimized);
       
   517 }
       
   518 
       
   519 void Q3DockWindowHandle::resizeEvent(QResizeEvent *)
       
   520 {
       
   521     updateGui();
       
   522 }
       
   523 
       
   524 void Q3DockWindowHandle::updateGui()
       
   525 {
       
   526     updateGeometry();
       
   527 
       
   528     if (!closeButton) {
       
   529         closeButton = new QToolButton(this, "qt_close_button1");
       
   530 #ifndef QT_NO_CURSOR
       
   531         closeButton->setCursor(Qt::ArrowCursor);
       
   532 #endif
       
   533         QStyleOption opt(0);
       
   534         opt.init(closeButton);
       
   535         closeButton->setIcon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton, &opt,
       
   536                                                     closeButton));
       
   537         closeButton->setFixedSize(12, 12);
       
   538         connect(closeButton, SIGNAL(clicked()),
       
   539                  dockWindow, SLOT(hide()));
       
   540     }
       
   541 
       
   542     if (dockWindow->isCloseEnabled() && dockWindow->area())
       
   543         closeButton->show();
       
   544     else
       
   545         closeButton->hide();
       
   546 
       
   547     if (!dockWindow->area())
       
   548         return;
       
   549 
       
   550     if (dockWindow->area()->orientation() == Qt::Horizontal) {
       
   551         int off = (width() - closeButton->width() - 1) / 2;
       
   552         closeButton->move(off, 2);
       
   553     } else {
       
   554         int off = (height() - closeButton->height() - 1) / 2;
       
   555         int x = QApplication::reverseLayout() ? 2 : width() - closeButton->width() - 2;
       
   556         closeButton->move(x, off);
       
   557     }
       
   558 }
       
   559 
       
   560 void Q3DockWindowHandle::changeEvent(QEvent *ev)
       
   561 {
       
   562     if(ev->type() == QEvent::StyleChange) {
       
   563         if (closeButton) {
       
   564             QStyleOption opt(0);
       
   565             opt.init(closeButton);
       
   566             closeButton->setIcon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton,
       
   567                                                         &opt, closeButton));
       
   568         }
       
   569     }
       
   570     QWidget::changeEvent(ev);
       
   571 }
       
   572 
       
   573 QSize Q3DockWindowHandle::minimumSizeHint() const
       
   574 {
       
   575     if (!dockWindow->dockArea)
       
   576         return QSize(0, 0);
       
   577     int wh = dockWindow->isCloseEnabled() ? 17 : style()->pixelMetric(QStyle::PM_ToolBarHandleExtent, 0, this);
       
   578     if (dockWindow->orientation() == Qt::Horizontal)
       
   579         return QSize(wh, 0);
       
   580     return QSize(0, wh);
       
   581 }
       
   582 
       
   583 void Q3DockWindowHandle::mouseDoubleClickEvent(QMouseEvent *e)
       
   584 {
       
   585     e->ignore();
       
   586     if (e->button() != Qt::LeftButton)
       
   587         return;
       
   588     e->accept();
       
   589     timer->stop();
       
   590     emit doubleClicked();
       
   591     hadDblClick = true;
       
   592     if (dockWindow->parentWidget())
       
   593         QApplication::postEvent(dockWindow->parentWidget(), new QEvent(QEvent::LayoutHint));
       
   594 }
       
   595 
       
   596 Q3DockWindowTitleBar::Q3DockWindowTitleBar(Q3DockWindow *dw)
       
   597     : Q3TitleBar(0, dw), dockWindow(dw),
       
   598       mousePressed(false), hadDblClick(false), opaque(default_opaque)
       
   599 {
       
   600     setObjectName(QLatin1String("qt_dockwidget_internal"));
       
   601     ctrlDown = false;
       
   602     setMouseTracking(true);
       
   603     QStyleOptionTitleBar opt = getStyleOption();
       
   604     setFixedHeight(style()->pixelMetric(QStyle::PM_TitleBarHeight, &opt, this));
       
   605     connect(this, SIGNAL(doClose()), dockWindow, SLOT(hide()));
       
   606 }
       
   607 
       
   608 void Q3DockWindowTitleBar::keyPressEvent(QKeyEvent *e)
       
   609 {
       
   610     if (!mousePressed)
       
   611         return;
       
   612     if (e->key() == Qt::Key_Control) {
       
   613         ctrlDown = true;
       
   614         dockWindow->handleMove(mapFromGlobal(QCursor::pos()) - offset, QCursor::pos(), !opaque);
       
   615     }
       
   616 }
       
   617 
       
   618 void Q3DockWindowTitleBar::keyReleaseEvent(QKeyEvent *e)
       
   619 {
       
   620     if (!mousePressed)
       
   621         return;
       
   622     if (e->key() == Qt::Key_Control) {
       
   623         ctrlDown = false;
       
   624         dockWindow->handleMove(mapFromGlobal(QCursor::pos()) - offset, QCursor::pos(), !opaque);
       
   625     }
       
   626 }
       
   627 
       
   628 void Q3DockWindowTitleBar::mousePressEvent(QMouseEvent *e)
       
   629 {
       
   630     QStyleOptionTitleBar opt;
       
   631     opt.init(this);
       
   632     opt.subControls = QStyle::SC_All;
       
   633     opt.activeSubControls = QStyle::SC_None;
       
   634     opt.text = windowTitle();
       
   635     //################
       
   636     QIcon icon = windowIcon();
       
   637     QSize s = icon.actualSize(QSize(64, 64));
       
   638     opt.icon = icon.pixmap(s);
       
   639     opt.titleBarState = window() ? window()->windowState() : static_cast<Qt::WindowStates>(Qt::WindowNoState);
       
   640     opt.titleBarFlags = fakeWindowFlags();
       
   641     QStyle::SubControl tbctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt,
       
   642                                                                e->pos(), this);
       
   643 
       
   644     if (tbctrl < QStyle::SC_TitleBarLabel && tbctrl != QStyle::SC_None) {
       
   645         Q3TitleBar::mousePressEvent(e);
       
   646         return;
       
   647     }
       
   648 
       
   649     ctrlDown = (e->state() & Qt::ControlButton) == Qt::ControlButton;
       
   650     oldFocus = qApp->focusWidget();
       
   651 // setFocus activates the window, which deactivates the main window
       
   652 // not what we want, and not required anyway on Windows
       
   653 #ifndef Q_WS_WIN
       
   654     setFocus();
       
   655 #endif
       
   656 
       
   657     e->ignore();
       
   658     if (e->button() != Qt::LeftButton)
       
   659         return;
       
   660     if (e->y() < 3 && dockWindow->isResizeEnabled())
       
   661         return;
       
   662 
       
   663     e->accept();
       
   664     bool oldPressed = mousePressed;
       
   665     mousePressed = true;
       
   666     hadDblClick = false;
       
   667     offset = e->pos();
       
   668     dockWindow->startRectDraw(mapToGlobal(e->pos()), !opaque);
       
   669 // grabMouse resets the Windows mouse press count, so we never receive a double click on Windows
       
   670 // not required on Windows, and did work on X11, too, but no problem there in the first place
       
   671 #ifndef Q_WS_WIN
       
   672     if(!oldPressed && dockWindow->opaqueMoving())
       
   673         grabMouse();
       
   674 #else
       
   675     Q_UNUSED(oldPressed);
       
   676 #endif
       
   677 }
       
   678 
       
   679 void Q3DockWindowTitleBar::mouseMoveEvent(QMouseEvent *e)
       
   680 {
       
   681     if (!mousePressed) {
       
   682         Q3TitleBar::mouseMoveEvent(e);
       
   683         return;
       
   684     }
       
   685 
       
   686     ctrlDown = (e->state() & Qt::ControlButton) == Qt::ControlButton;
       
   687     e->accept();
       
   688     dockWindow->handleMove(e->pos() - offset, e->globalPos(), !opaque);
       
   689 }
       
   690 
       
   691 void Q3DockWindowTitleBar::mouseReleaseEvent(QMouseEvent *e)
       
   692 {
       
   693     if (!mousePressed) {
       
   694         Q3TitleBar::mouseReleaseEvent(e);
       
   695         return;
       
   696     }
       
   697 
       
   698     ctrlDown = false;
       
   699     qApp->removeEventFilter(dockWindow);
       
   700     if (oldFocus)
       
   701         oldFocus->setFocus();
       
   702 
       
   703     if (dockWindow->place() == Q3DockWindow::OutsideDock)
       
   704         dockWindow->raise();
       
   705 
       
   706     if(dockWindow->opaqueMoving())
       
   707         releaseMouse();
       
   708     if (!mousePressed)
       
   709         return;
       
   710     dockWindow->endRectDraw(!opaque);
       
   711     mousePressed = false;
       
   712     if (!hadDblClick)
       
   713         dockWindow->updatePosition(e->globalPos());
       
   714     if (opaque) {
       
   715         dockWindow->horHandle->mousePressed = false;
       
   716         dockWindow->verHandle->mousePressed = false;
       
   717     }
       
   718     if (dockWindow->parentWidget())
       
   719         QApplication::postEvent(dockWindow->parentWidget(), new QEvent(QEvent::LayoutHint));
       
   720 }
       
   721 
       
   722 void Q3DockWindowTitleBar::resizeEvent(QResizeEvent *e)
       
   723 {
       
   724     updateGui();
       
   725     Q3TitleBar::resizeEvent(e);
       
   726 }
       
   727 
       
   728 void Q3DockWindowTitleBar::updateGui()
       
   729 {
       
   730     if (dockWindow->isCloseEnabled()) {
       
   731         setFakeWindowFlags(fakeWindowFlags() | Qt::WStyle_SysMenu);
       
   732     } else {
       
   733         setFakeWindowFlags(fakeWindowFlags() & ~Qt::WStyle_SysMenu);
       
   734     }
       
   735 }
       
   736 
       
   737 void Q3DockWindowTitleBar::mouseDoubleClickEvent(QMouseEvent *)
       
   738 {
       
   739     emit doubleClicked();
       
   740     hadDblClick = true;
       
   741     if (dockWindow->parentWidget())
       
   742         QApplication::postEvent(dockWindow->parentWidget(), new QEvent(QEvent::LayoutHint));
       
   743 }
       
   744 
       
   745 /*!
       
   746     \class Q3DockWindow
       
   747     \brief The Q3DockWindow class provides a widget which can be docked
       
   748     inside a Q3DockArea or floated as a top level window on the
       
   749     desktop.
       
   750 
       
   751     \compat
       
   752 
       
   753     This class handles moving, resizing, docking and undocking dock
       
   754     windows. Q3ToolBar is a subclass of Q3DockWindow so the
       
   755     functionality provided for dock windows is available with the same
       
   756     API for toolbars.
       
   757 
       
   758     \img qmainwindow-qdockareas.png Q3DockWindows in a Q3DockArea
       
   759     \caption Two Q3DockWindows (\l{Q3ToolBar}s) in a \l Q3DockArea
       
   760 
       
   761     \img qdockwindow.png A Q3DockWindow
       
   762     \caption A Floating Q3DockWindow
       
   763 
       
   764     If the user drags the dock window into the dock area the dock
       
   765     window will be docked. If the user drags the dock area outside any
       
   766     dock areas the dock window will be undocked (floated) and will
       
   767     become a top level window. Double clicking a floating dock
       
   768     window's title bar will dock the dock window to the last dock area
       
   769     it was docked in. Double clicking a docked dock window's handle
       
   770     will undock (float) the dock window.
       
   771     \omit
       
   772     Single clicking a docked dock window's handle will minimize the
       
   773     dock window (only its handle will appear, below the menu bar).
       
   774     Single clicking the minimized handle will restore the dock window
       
   775     to the last dock area that it was docked in.
       
   776     \endomit
       
   777     If the user clicks the close button (which appears on floating
       
   778     dock windows by default) the dock window will disappear. You can
       
   779     control whether or not a dock window has a close button with
       
   780     setCloseMode().
       
   781 
       
   782     Q3MainWindow provides four dock areas (top, left, right and bottom)
       
   783     which can be used by dock windows. For many applications using the
       
   784     dock areas provided by Q3MainWindow is sufficient. (See the \l
       
   785     Q3DockArea documentation if you want to create your own dock
       
   786     areas.) In Q3MainWindow a right-click popup menu (the dock window
       
   787     menu) is available which lists dock windows and can be used to
       
   788     show or hide them. (The popup menu only lists dock windows that
       
   789     have a \link QWidget::setWindowTitle() caption\endlink.)
       
   790 
       
   791     When you construct a dock window you \e must pass it a Q3DockArea
       
   792     or a Q3MainWindow as its parent if you want it docked. Pass 0 for
       
   793     the parent if you want it floated.
       
   794 
       
   795     \snippet doc/src/snippets/code/src_qt3support_widgets_q3dockwindow.cpp 0
       
   796 
       
   797     In the example above we create a new Q3ToolBar in the constructor
       
   798     of a Q3MainWindow subclass (so that the \e this pointer points to
       
   799     the Q3MainWindow). By default the toolbar will be added to the \c
       
   800     Top dock area, but we've moved it to the \c Left dock area.
       
   801 
       
   802     A dock window is often used to contain a single widget. In these
       
   803     cases the widget can be set by calling setWidget(). If you're
       
   804     constructing a dock window that contains multiple widgets, e.g. a
       
   805     toolbar, arrange the widgets within a box layout inside the dock
       
   806     window. To do this use the boxLayout() function to get a pointer
       
   807     to the dock window's box layout, then add widgets to the layout
       
   808     using the box layout's QBoxLayout::addWidget() function. The dock
       
   809     window will dynamically set the orientation of the layout to be
       
   810     vertical or horizontal as necessary, although you can control this
       
   811     yourself with setOrientation().
       
   812 
       
   813     Although a common use of dock windows is for toolbars, they can be
       
   814     used with any widgets. When using larger
       
   815     widgets it may make sense for the dock window to be resizable by
       
   816     calling setResizeEnabled(). Resizable dock windows are given
       
   817     splitter-like handles to allow the user to resize them within
       
   818     their dock area. When resizable dock windows are undocked they
       
   819     become top level windows and can be resized like any other top
       
   820     level windows, e.g. by dragging a corner or edge.
       
   821 
       
   822     Qt::Dock windows can be docked and undocked using dock() and undock().
       
   823     A dock window's orientation can be set with setOrientation(). You
       
   824     can also use Q3DockArea::moveDockWindow(). If you're using a
       
   825     Q3MainWindow, Q3MainWindow::moveDockWindow() and
       
   826     Q3MainWindow::removeDockWindow() are available.
       
   827 
       
   828     A dock window can have some preferred settings, for example, you
       
   829     can set a preferred offset from the left edge (or top edge for
       
   830     vertical dock areas) of the dock area using setOffset(). If you'd
       
   831     prefer a dock window to start on a new line when it is docked use
       
   832     setNewLine(). The setFixedExtentWidth() and setFixedExtentHeight()
       
   833     functions can be used to define the dock window's preferred size,
       
   834     and the setHorizontallyStretchable() and setVerticallyStretchable()
       
   835     functions set whether the dock window can be stretched or not.
       
   836     Dock windows can be moved by default, but this can be changed with
       
   837     setMovingEnabled(). When a dock window is moved it is shown as a
       
   838     rectangular outline, but it can be shown normally using
       
   839     setOpaqueMoving().
       
   840 
       
   841     When a dock window's visibility changes, i.e. it is shown or
       
   842     hidden, the visibilityChanged() signal is emitted. When a dock
       
   843     window is docked, undocked or moved inside the dock area the
       
   844     placeChanged() signal is emitted.
       
   845 */
       
   846 
       
   847 /*!
       
   848     \enum Q3DockWindow::Place
       
   849 
       
   850     This enum specifies the possible locations for a Q3DockWindow:
       
   851 
       
   852     \value InDock  Inside a Q3DockArea.
       
   853     \value OutsideDock  Floating as a top level window on the desktop.
       
   854 */
       
   855 
       
   856 /*!
       
   857     \enum Q3DockWindow::CloseMode
       
   858 
       
   859     This enum type specifies when (if ever) a dock window has a close
       
   860     button.
       
   861 
       
   862     \value Never  The dock window never has a close button and cannot
       
   863     be closed by the user.
       
   864     \value Docked  The dock window has a close button only when
       
   865     docked.
       
   866     \value Undocked  The dock window has a close button only when
       
   867     floating.
       
   868     \value Always The dock window always has a close button.
       
   869     \omit
       
   870     Note that dock windows can always be minimized if the user clicks
       
   871     their dock window handle when they are docked.
       
   872     \endomit
       
   873 */
       
   874 
       
   875 /*!
       
   876     \fn void Q3DockWindow::setHorizontalStretchable(bool b)
       
   877 
       
   878     If \a b is true the dock window is set to be horizontally
       
   879     stretchable.
       
   880 */
       
   881 /*!
       
   882     \fn void Q3DockWindow::setVerticalStretchable(bool b)
       
   883 
       
   884     If \a b is true the dock window is set to be vertically
       
   885     stretchable.
       
   886 */
       
   887 /*!
       
   888     \fn bool Q3DockWindow::isHorizontalStretchable() const
       
   889 
       
   890     Returns true if the dock window can be stretched horizontally;
       
   891     otherwise returns false.
       
   892 */
       
   893 /*!
       
   894     \fn bool Q3DockWindow::isVerticalStretchable() const
       
   895 
       
   896     Returns true if the dock window can be stretched vertically;
       
   897     otherwise returns false.
       
   898 */
       
   899 /*!
       
   900     \fn void Q3DockWindow::orientationChanged(Qt::Orientation o)
       
   901 
       
   902     This signal is emitted when the orientation of the dock window is
       
   903     changed. The new orientation is \a o.
       
   904 */
       
   905 
       
   906 /*!
       
   907     \fn void Q3DockWindow::placeChanged(Q3DockWindow::Place p)
       
   908 
       
   909     This signal is emitted when the dock window is docked (\a p is \c
       
   910     InDock), undocked (\a p is \c OutsideDock) or moved inside the
       
   911     the dock area.
       
   912 
       
   913     \sa Q3DockArea::moveDockWindow(), Q3DockArea::removeDockWindow(),
       
   914     Q3MainWindow::moveDockWindow(), Q3MainWindow::removeDockWindow()
       
   915 */
       
   916 
       
   917 /*!
       
   918     \fn void Q3DockWindow::visibilityChanged(bool visible)
       
   919 
       
   920     This signal is emitted when the visibility of the dock window
       
   921     relatively to its dock area is changed. If \a visible is true, the
       
   922     Q3DockWindow is now visible to the dock area, otherwise it has been
       
   923     hidden.
       
   924 
       
   925     A dock window can be hidden if it has a close button which the
       
   926     user has clicked. In the case of a Q3MainWindow a dock window can
       
   927     have its visibility changed (hidden or shown) by clicking its name
       
   928     in the dock window menu that lists the Q3MainWindow's dock windows.
       
   929 */
       
   930 
       
   931 /*!
       
   932     \fn Q3DockArea *Q3DockWindow::area() const
       
   933 
       
   934     Returns the dock area in which this dock window is docked, or 0 if
       
   935     the dock window is floating.
       
   936 */
       
   937 
       
   938 /*!
       
   939     \property Q3DockWindow::place
       
   940     \brief the location where the dock window is placed
       
   941 
       
   942     This is either \c InDock or \c OutsideDock.
       
   943 
       
   944     \sa Q3DockArea::moveDockWindow(), Q3DockArea::removeDockWindow(),
       
   945         Q3MainWindow::moveDockWindow(), Q3MainWindow::removeDockWindow()
       
   946 */
       
   947 
       
   948 /*!
       
   949     Constructs a Q3DockWindow with parent \a parent, called \a name and
       
   950     with widget flags \a f.
       
   951 */
       
   952 
       
   953 Q3DockWindow::Q3DockWindow(QWidget* parent, const char* name, Qt::WindowFlags f)
       
   954     : Q3Frame(parent, name, f | Qt::WType_Dialog | Qt::WStyle_Customize | Qt::WStyle_NoBorder)
       
   955 {
       
   956     curPlace = InDock;
       
   957     isToolbar = false;
       
   958     init();
       
   959 }
       
   960 
       
   961 /*!
       
   962     Constructs a Q3DockWindow with parent \a parent, called \a name and
       
   963     with widget flags \a f.
       
   964 
       
   965     If \a p is \c InDock, the dock window is docked into a dock area
       
   966     and \a parent \e must be a Q3DockArea or a Q3MainWindow. If the \a
       
   967     parent is a Q3MainWindow the dock window will be docked in the main
       
   968     window's \c Top dock area.
       
   969 
       
   970     If \a p is \c OutsideDock, the dock window is created as a floating
       
   971     window.
       
   972 
       
   973     We recommend creating the dock area \c InDock with a Q3MainWindow
       
   974     as parent then calling Q3MainWindow::moveDockWindow() to move the
       
   975     dock window where you want it.
       
   976 */
       
   977 
       
   978 Q3DockWindow::Q3DockWindow(Place p, QWidget *parent, const char *name, Qt::WindowFlags f)
       
   979     : Q3Frame(parent, name, f | Qt::WType_Dialog | Qt::WStyle_Customize | Qt::WStyle_NoBorder)
       
   980 {
       
   981     curPlace = p;
       
   982     isToolbar = false;
       
   983     init();
       
   984 }
       
   985 
       
   986 /*! \internal
       
   987 */
       
   988 
       
   989 Q3DockWindow::Q3DockWindow(Place p, QWidget *parent, const char *name, Qt::WindowFlags f, bool toolbar)
       
   990     : Q3Frame(parent, name, f | Qt::WType_Dialog | Qt::WStyle_Customize | Qt::WStyle_NoBorder)
       
   991 {
       
   992     curPlace = p;
       
   993     isToolbar = toolbar;
       
   994     init();
       
   995 }
       
   996 
       
   997 class Q3DockWindowGridLayout : public QGridLayout
       
   998 {
       
   999 public:
       
  1000     Q3DockWindowGridLayout(QWidget *parent, int nRows, int nCols)
       
  1001         : QGridLayout(parent, nRows, nCols) {};
       
  1002 
       
  1003     Qt::Orientations expandingDirections() const
       
  1004     {
       
  1005         return 0;
       
  1006     }
       
  1007 };
       
  1008 
       
  1009 void Q3DockWindow::init()
       
  1010 {
       
  1011     wid = 0;
       
  1012     rubberBand = 0;
       
  1013     dockArea = 0;
       
  1014     tmpDockArea = 0;
       
  1015     resizeEnabled = false;
       
  1016     moveEnabled = true;
       
  1017     nl = false;
       
  1018     opaque = default_opaque;
       
  1019     cMode = Never;
       
  1020     offs = 0;
       
  1021     fExtent = QSize(-1, -1);
       
  1022     dockWindowData = 0;
       
  1023     lastPos = QPoint(-1, -1);
       
  1024     lastSize = QSize(-1, -1);
       
  1025     stretchable[Qt::Horizontal] = false;
       
  1026     stretchable[Qt::Vertical] = false;
       
  1027 
       
  1028     widgetResizeHandler = new QWidgetResizeHandler(this);
       
  1029     widgetResizeHandler->setMovingEnabled(false);
       
  1030 
       
  1031     titleBar      = new Q3DockWindowTitleBar(this);
       
  1032     verHandle     = new Q3DockWindowHandle(this);
       
  1033     verHandle->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred));
       
  1034     horHandle     = new Q3DockWindowHandle(this);
       
  1035     horHandle->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
       
  1036 
       
  1037     vHandleLeft   = new Q3DockWindowResizeHandle(Qt::Vertical, this, this, "vert. handle");
       
  1038     vHandleRight  = new Q3DockWindowResizeHandle(Qt::Vertical, this, this, "vert. handle");
       
  1039     hHandleTop    = new Q3DockWindowResizeHandle(Qt::Horizontal, this, this, "horz. handle");
       
  1040     hHandleBottom = new Q3DockWindowResizeHandle(Qt::Horizontal, this, this, "horz. handle");
       
  1041 
       
  1042     // Creating inner layout
       
  1043     hbox          = new QVBoxLayout();
       
  1044     vbox          = new QHBoxLayout();
       
  1045     childBox          = new QBoxLayout(QBoxLayout::LeftToRight);
       
  1046     vbox->addSpacing(2);
       
  1047     vbox->addWidget(verHandle);
       
  1048     vbox->addStretch(0);
       
  1049     vbox->addLayout(childBox, 1);
       
  1050     vbox->addStretch(0);
       
  1051 
       
  1052     hbox->setResizeMode(QLayout::FreeResize);
       
  1053     hbox->setMargin(isResizeEnabled() || curPlace == OutsideDock ? 2 : 0);
       
  1054     hbox->setSpacing(1);
       
  1055     hbox->addWidget(titleBar);
       
  1056     hbox->addWidget(horHandle);
       
  1057     hbox->addLayout(vbox);
       
  1058 
       
  1059     // Set up the initial handle layout for Qt::Vertical
       
  1060     // Handle layout will change on calls to setOrienation()
       
  1061     QGridLayout *glayout = new Q3DockWindowGridLayout(this, 3, 3);
       
  1062     glayout->setResizeMode(QLayout::Minimum);
       
  1063     glayout->addMultiCellWidget(hHandleTop,    0, 0, 1, 1);
       
  1064     glayout->addMultiCellWidget(hHandleBottom, 2, 2, 1, 1);
       
  1065     glayout->addMultiCellWidget(vHandleLeft,   0, 2, 0, 0);
       
  1066     glayout->addMultiCellWidget(vHandleRight,  0, 2, 2, 2);
       
  1067     glayout->addLayout(hbox, 1, 1);
       
  1068     glayout->setRowStretch(1, 1);
       
  1069     glayout->setColStretch(1, 1);
       
  1070 
       
  1071     hHandleBottom->hide();
       
  1072     vHandleRight->hide();
       
  1073     hHandleTop->hide();
       
  1074     vHandleLeft->hide();
       
  1075     setFrameStyle(Q3Frame::StyledPanel | Q3Frame::Raised);
       
  1076     setLineWidth(2);
       
  1077 
       
  1078     if (parentWidget())
       
  1079         parentWidget()->installEventFilter(this);
       
  1080     QWidget *mw = parentWidget();
       
  1081     Q3DockArea *da = qobject_cast<Q3DockArea*>(parentWidget());
       
  1082     if (da) {
       
  1083         if (curPlace == InDock)
       
  1084             da->moveDockWindow(this);
       
  1085         mw = da->parentWidget();
       
  1086     }
       
  1087     if (qobject_cast<Q3MainWindow*>(mw)) {
       
  1088         if (place() == InDock) {
       
  1089             Qt::Dock myDock = Qt::DockTop;
       
  1090             // make sure we put the window in the correct dock.
       
  1091             if (dockArea) {
       
  1092                 Q3MainWindow *mainw = (Q3MainWindow*)mw;
       
  1093                 // I'm not checking if it matches the top because I've
       
  1094                 // done the assignment to it above.
       
  1095                 if (dockArea == mainw->leftDock())
       
  1096                     myDock = Qt::DockLeft;
       
  1097                 else if (dockArea == mainw->rightDock())
       
  1098                     myDock = Qt::DockRight;
       
  1099                 else if (dockArea == mainw->bottomDock())
       
  1100                     myDock = Qt::DockBottom;
       
  1101             }
       
  1102             ((Q3MainWindow*)mw)->addDockWindow(this, myDock);
       
  1103         }
       
  1104         moveEnabled = ((Q3MainWindow*)mw)->dockWindowsMovable();
       
  1105         opaque = ((Q3MainWindow*)mw)->opaqueMoving();
       
  1106     }
       
  1107 
       
  1108     updateGui();
       
  1109 
       
  1110     connect(titleBar, SIGNAL(doubleClicked()), this, SLOT(dock()));
       
  1111     connect(verHandle, SIGNAL(doubleClicked()), this, SLOT(undock()));
       
  1112     connect(horHandle, SIGNAL(doubleClicked()), this, SLOT(undock()));
       
  1113     connect(this, SIGNAL(orientationChanged(Qt::Orientation)),
       
  1114              this, SLOT(setOrientation(Qt::Orientation)));
       
  1115 }
       
  1116 
       
  1117 /*!
       
  1118     Sets the orientation of the dock window to \a o. The orientation
       
  1119     is propagated to the layout boxLayout().
       
  1120 
       
  1121     \warning All undocked Q3ToolBars will always have a horizontal orientation.
       
  1122 */
       
  1123 
       
  1124 void Q3DockWindow::setOrientation(Qt::Orientation o)
       
  1125 {
       
  1126     QGridLayout *glayout = (QGridLayout*)layout();
       
  1127     glayout->removeWidget(hHandleTop);
       
  1128     glayout->removeWidget(hHandleBottom);
       
  1129     glayout->removeWidget(vHandleLeft);
       
  1130     glayout->removeWidget(vHandleRight);
       
  1131 
       
  1132     if (o == Qt::Horizontal) {
       
  1133         // Set up the new layout as
       
  1134         //   3 3 3      1 = vHandleLeft   4 = hHandleBottom
       
  1135         //   1 X 2      2 = vHandleRight  X = Inner Layout
       
  1136         //   4 4 4      3 = hHandleTop
       
  1137         glayout->addMultiCellWidget(hHandleTop,    0, 0, 0, 2);
       
  1138         glayout->addMultiCellWidget(hHandleBottom, 2, 2, 0, 2);
       
  1139         glayout->addMultiCellWidget(vHandleLeft,   1, 1, 0, 0);
       
  1140         glayout->addMultiCellWidget(vHandleRight,  1, 1, 2, 2);
       
  1141     } else {
       
  1142         // Set up the new layout as
       
  1143         //   1 3 2      1 = vHandleLeft   4 = hHandleBottom
       
  1144         //   1 X 2      2 = vHandleRight  X = Inner Layout
       
  1145         //   1 4 2      3 = hHandleTop
       
  1146         glayout->addMultiCellWidget(hHandleTop,    0, 0, 1, 1);
       
  1147         glayout->addMultiCellWidget(hHandleBottom, 2, 2, 1, 1);
       
  1148         glayout->addMultiCellWidget(vHandleLeft,   0, 2, 0, 0);
       
  1149         glayout->addMultiCellWidget(vHandleRight,  0, 2, 2, 2);
       
  1150     }
       
  1151     boxLayout()->setDirection(o == Qt::Horizontal ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom);
       
  1152     QApplication::sendPostedEvents(this, QEvent::LayoutHint);
       
  1153     QEvent *e = new QEvent(QEvent::LayoutHint);
       
  1154     QApplication::postEvent(this, e);
       
  1155 }
       
  1156 
       
  1157 /*!
       
  1158     Destroys the dock window and its child widgets.
       
  1159 */
       
  1160 
       
  1161 Q3DockWindow::~Q3DockWindow()
       
  1162 {
       
  1163     qApp->removeEventFilter(this);
       
  1164     if (area())
       
  1165         area()->removeDockWindow(this, false, false);
       
  1166     Q3DockArea *a = area();
       
  1167     if (!a && dockWindowData)
       
  1168         a = ((Q3DockArea::DockWindowData*)dockWindowData)->area;
       
  1169     Q3MainWindow *mw = a ? qobject_cast<Q3MainWindow*>(a->parentWidget()) : 0;
       
  1170     if (mw)
       
  1171         mw->removeDockWindow(this);
       
  1172 
       
  1173     delete (Q3DockArea::DockWindowData*)dockWindowData;
       
  1174 }
       
  1175 
       
  1176 /*!  \reimp
       
  1177 */
       
  1178 
       
  1179 void Q3DockWindow::resizeEvent(QResizeEvent *e)
       
  1180 {
       
  1181     Q3Frame::resizeEvent(e);
       
  1182     updateGui();
       
  1183 }
       
  1184 
       
  1185 
       
  1186 void Q3DockWindow::swapRect(QRect &r, Qt::Orientation o, const QPoint &offset, Q3DockArea *)
       
  1187 {
       
  1188     r.setSize(QSize(r.height(), r.width()));
       
  1189     bool reverse = QApplication::reverseLayout();
       
  1190     if (o == Qt::Horizontal)
       
  1191         r.moveBy(-r.width()/2, 0);
       
  1192     else
       
  1193         r.moveBy(reverse ? - r.width() : 0, -r.height() / 2 );
       
  1194     r.moveBy(offset.x(), offset.y());
       
  1195 }
       
  1196 
       
  1197 QWidget *Q3DockWindow::areaAt(const QPoint &gp)
       
  1198 {
       
  1199     QWidget *w = qApp->widgetAt(gp);
       
  1200 
       
  1201     if (w && (w == this || w == titleBar) && parentWidget())
       
  1202         w = parentWidget()->childAt(parentWidget()->mapFromGlobal(gp));
       
  1203 
       
  1204     while (w) {
       
  1205         if (qobject_cast<Q3DockArea*>(w)) {
       
  1206             Q3DockArea *a = (Q3DockArea*)w;
       
  1207             if (a->isDockWindowAccepted(this))
       
  1208                 return w;
       
  1209         }
       
  1210         if (qobject_cast<Q3MainWindow*>(w)) {
       
  1211             Q3MainWindow *mw = (Q3MainWindow*)w;
       
  1212             Q3DockArea *a = mw->dockingArea(mw->mapFromGlobal(gp));
       
  1213             if (a && a->isDockWindowAccepted(this))
       
  1214                 return a;
       
  1215         }
       
  1216         w = w->isWindow() ? 0 : (QWidget *)w->parent();
       
  1217     }
       
  1218     return 0;
       
  1219 }
       
  1220 
       
  1221 void Q3DockWindow::handleMove(const QPoint &pos, const QPoint &gp, bool drawRect)
       
  1222 {
       
  1223     if (!rubberBand)
       
  1224         return;
       
  1225 
       
  1226     currRect = QRect(realWidgetPos(this), size());
       
  1227     QWidget *w = areaAt(gp);
       
  1228     if (titleBar->ctrlDown || horHandle->ctrlDown || verHandle->ctrlDown)
       
  1229         w = 0;
       
  1230     currRect.moveBy(pos.x(), pos.y());
       
  1231     if (!qobject_cast<Q3DockArea*>(w)) {
       
  1232         if (startOrientation != Qt::Horizontal && qobject_cast<Q3ToolBar*>(this))
       
  1233             swapRect(currRect, Qt::Horizontal, startOffset, (Q3DockArea*)w);
       
  1234         if (drawRect) {
       
  1235             rubberBand->setGeometry(currRect);
       
  1236         } else {
       
  1237             QPoint mp(mapToGlobal(pos));
       
  1238             if(place() == InDock) {
       
  1239                 undock();
       
  1240                 if(titleBar) {
       
  1241                     mp = QPoint(titleBar->width() / 2, titleBar->height() / 2);
       
  1242                     QMouseEvent me(QEvent::MouseButtonPress, mp, Qt::LeftButton, 0);
       
  1243                     QApplication::sendEvent(titleBar, &me);
       
  1244                     mp = titleBar->mapToGlobal(mp);
       
  1245                 }
       
  1246             }
       
  1247             move(mp);
       
  1248         }
       
  1249         state = OutsideDock;
       
  1250         return;
       
  1251     }
       
  1252 
       
  1253     Q3DockArea *area = (Q3DockArea*)w;
       
  1254     if(area->isVisible()) {
       
  1255         state = InDock;
       
  1256         Qt::Orientation o = (area ? area->orientation() :
       
  1257                           (boxLayout()->direction() == QBoxLayout::LeftToRight ||
       
  1258                             boxLayout()->direction() == QBoxLayout::RightToLeft ?
       
  1259                             Qt::Horizontal : Qt::Vertical));
       
  1260         if (startOrientation != o)
       
  1261             swapRect(currRect, o, startOffset, area);
       
  1262         if (drawRect) {
       
  1263             rubberBand->setGeometry(currRect);
       
  1264         }
       
  1265         tmpDockArea = area;
       
  1266     }
       
  1267 }
       
  1268 
       
  1269 void Q3DockWindow::updateGui()
       
  1270 {
       
  1271     if (curPlace == OutsideDock) {
       
  1272         hbox->setMargin(2);
       
  1273         horHandle->hide();
       
  1274         verHandle->hide();
       
  1275         if (moveEnabled)
       
  1276             titleBar->show();
       
  1277         else
       
  1278             titleBar->hide();
       
  1279         titleBar->updateGui();
       
  1280         hHandleTop->hide();
       
  1281         vHandleLeft->hide();
       
  1282         hHandleBottom->hide();
       
  1283         vHandleRight->hide();
       
  1284         setLineWidth(2);
       
  1285         widgetResizeHandler->setActive(isResizeEnabled());
       
  1286     } else {
       
  1287         hbox->setMargin(0);
       
  1288         titleBar->hide();
       
  1289         if (orientation() == Qt::Horizontal) {
       
  1290             horHandle->hide();
       
  1291             if (moveEnabled)
       
  1292                 verHandle->show();
       
  1293             else
       
  1294                 verHandle->hide();
       
  1295 #ifdef Q_WS_MAC
       
  1296             if(horHandle->mousePressed) {
       
  1297                 horHandle->mousePressed = false;
       
  1298                 verHandle->mousePressed = true;
       
  1299                 verHandle->grabMouse();
       
  1300             }
       
  1301 #endif
       
  1302             verHandle->updateGui();
       
  1303         } else {
       
  1304             if (moveEnabled)
       
  1305                 horHandle->show();
       
  1306             else
       
  1307                 horHandle->hide();
       
  1308             horHandle->updateGui();
       
  1309 #ifdef Q_WS_MAC
       
  1310             if(verHandle->mousePressed) {
       
  1311                 verHandle->mousePressed = false;
       
  1312                 horHandle->mousePressed = true;
       
  1313                 horHandle->grabMouse();
       
  1314             }
       
  1315 #endif
       
  1316             verHandle->hide();
       
  1317         }
       
  1318         if (isResizeEnabled()) {
       
  1319             if (orientation() == Qt::Horizontal) {
       
  1320                 hHandleBottom->raise();
       
  1321                 hHandleTop->raise();
       
  1322             } else {
       
  1323                 vHandleRight->raise();
       
  1324                 vHandleLeft->raise();
       
  1325             }
       
  1326 
       
  1327             if (area()) {
       
  1328                 if (orientation() == Qt::Horizontal) {
       
  1329                     if (area()->handlePosition() == Q3DockArea::Normal) {
       
  1330                         hHandleBottom->show();
       
  1331                         hHandleTop->hide();
       
  1332                     } else {
       
  1333                         hHandleTop->show();
       
  1334                         hHandleBottom->hide();
       
  1335                     }
       
  1336                     if (!area()->isLastDockWindow(this))
       
  1337                         vHandleRight->show();
       
  1338                     else
       
  1339                         vHandleRight->hide();
       
  1340                     vHandleLeft->hide();
       
  1341                 } else {
       
  1342                     if ((area()->handlePosition() == Q3DockArea::Normal) != QApplication::reverseLayout()) {
       
  1343                         vHandleRight->show();
       
  1344                         vHandleLeft->hide();
       
  1345                     } else {
       
  1346                         vHandleLeft->show();
       
  1347                         vHandleRight->hide();
       
  1348                     }
       
  1349                     if (!area()->isLastDockWindow(this))
       
  1350                         hHandleBottom->show();
       
  1351                     else
       
  1352                         hHandleBottom->hide();
       
  1353                     hHandleTop->hide();
       
  1354                 }
       
  1355             }
       
  1356         }
       
  1357 #ifndef Q_OS_WINCE
       
  1358         if (moveEnabled)
       
  1359             setLineWidth(1);
       
  1360         else
       
  1361             setLineWidth(0);
       
  1362 #endif
       
  1363         widgetResizeHandler->setActive(false);
       
  1364     }
       
  1365 }
       
  1366 
       
  1367 void Q3DockWindow::updatePosition(const QPoint &globalPos)
       
  1368 {
       
  1369     if (curPlace == OutsideDock && state == InDock)
       
  1370         lastSize = size();
       
  1371 
       
  1372     bool doAdjustSize = curPlace != state && state == OutsideDock;
       
  1373     bool doUpdate = true;
       
  1374     bool doOrientationChange = true;
       
  1375     if (state != curPlace && state == InDock) {
       
  1376         doUpdate = false;
       
  1377         curPlace = state;
       
  1378         updateGui();
       
  1379         QApplication::sendPostedEvents();
       
  1380     }
       
  1381     Qt::Orientation oo = orientation();
       
  1382 
       
  1383     if (state == InDock) {
       
  1384         if (tmpDockArea) {
       
  1385             bool differentDocks = false;
       
  1386             if (dockArea && dockArea != tmpDockArea) {
       
  1387                 differentDocks = true;
       
  1388                 delete (Q3DockArea::DockWindowData*)dockWindowData;
       
  1389                 dockWindowData = dockArea->dockWindowData(this);
       
  1390                 dockArea->removeDockWindow(this, false, false);
       
  1391             }
       
  1392             dockArea = tmpDockArea;
       
  1393             if (differentDocks) {
       
  1394                 if (doUpdate) {
       
  1395                     doUpdate = false;
       
  1396                     curPlace = state;
       
  1397                     updateGui();
       
  1398                 }
       
  1399                 emit orientationChanged(tmpDockArea->orientation());
       
  1400                 doOrientationChange = false;
       
  1401             } else {
       
  1402                 updateGui();
       
  1403             }
       
  1404             dockArea->moveDockWindow(this, globalPos, currRect, startOrientation != oo);
       
  1405         }
       
  1406     } else {
       
  1407         if (dockArea) {
       
  1408             Q3MainWindow *mw = (Q3MainWindow*)dockArea->parentWidget();
       
  1409             if (qobject_cast<Q3MainWindow*>(mw) &&
       
  1410                  (!mw->isDockEnabled(Qt::DockTornOff) ||
       
  1411                    !mw->isDockEnabled(this, Qt::DockTornOff)))
       
  1412                 return;
       
  1413             delete (Q3DockArea::DockWindowData*)dockWindowData;
       
  1414             dockWindowData = dockArea->dockWindowData(this);
       
  1415             dockArea->removeDockWindow(this, true,
       
  1416                 startOrientation != Qt::Horizontal && qobject_cast<Q3ToolBar*>(this));
       
  1417         }
       
  1418         dockArea = 0;
       
  1419         QPoint topLeft = currRect.topLeft();
       
  1420         QRect screen = qApp->desktop()->availableGeometry(topLeft);
       
  1421         if (!screen.contains(topLeft)) {
       
  1422             topLeft.setY(qMax(topLeft.y(), screen.top()));
       
  1423             topLeft.setY(qMin(topLeft.y(), screen.bottom()-height()));
       
  1424             topLeft.setX(qMax(topLeft.x(), screen.left()));
       
  1425             topLeft.setX(qMin(topLeft.x(), screen.right()-width()));
       
  1426         }
       
  1427         move(topLeft);
       
  1428     }
       
  1429 
       
  1430     if (curPlace == InDock && state == OutsideDock && !qobject_cast<Q3ToolBar*>(this)) {
       
  1431         if (lastSize != QSize(-1, -1))
       
  1432             resize(lastSize);
       
  1433     }
       
  1434 
       
  1435     if (doUpdate) {
       
  1436         curPlace = state;
       
  1437         updateGui();
       
  1438     }
       
  1439     if (doOrientationChange)
       
  1440         emit orientationChanged(orientation());
       
  1441     tmpDockArea = 0;
       
  1442     if (doAdjustSize) {
       
  1443         QApplication::sendPostedEvents(this, QEvent::LayoutHint);
       
  1444         if (qobject_cast<Q3ToolBar*>(this))
       
  1445             adjustSize();
       
  1446         if (lastSize == QSize(-1, -1))
       
  1447             setAttribute(Qt::WA_Resized, false); // Ensures size is recalculated (non-opaque).
       
  1448         show();
       
  1449         if (parentWidget() && isWindow())
       
  1450             parentWidget()->setActiveWindow();
       
  1451 
       
  1452     }
       
  1453 
       
  1454     emit placeChanged(curPlace);
       
  1455 }
       
  1456 
       
  1457 /*!
       
  1458     Sets the dock window's main widget to \a w.
       
  1459 
       
  1460     \sa boxLayout()
       
  1461 */
       
  1462 
       
  1463 void Q3DockWindow::setWidget(QWidget *w)
       
  1464 {
       
  1465     wid = w;
       
  1466     boxLayout()->addWidget(w);
       
  1467     updateGui();
       
  1468 }
       
  1469 
       
  1470 /*!
       
  1471     Returns the dock window's main widget.
       
  1472 
       
  1473     \sa setWidget()
       
  1474 */
       
  1475 
       
  1476 QWidget *Q3DockWindow::widget() const
       
  1477 {
       
  1478     return wid;
       
  1479 }
       
  1480 
       
  1481 void Q3DockWindow::startRectDraw(const QPoint &so, bool drawRect)
       
  1482 {
       
  1483     state = place();
       
  1484     if (rubberBand)
       
  1485         endRectDraw(!opaque);
       
  1486     rubberBand = new QRubberBand(QRubberBand::Rectangle);
       
  1487     currRect = QRect(realWidgetPos(this), size());
       
  1488     if (drawRect) {
       
  1489         rubberBand->setGeometry(currRect);
       
  1490     }
       
  1491     startOrientation = orientation();
       
  1492     startOffset = mapFromGlobal(so);
       
  1493     rubberBand->show();
       
  1494 }
       
  1495 
       
  1496 void Q3DockWindow::endRectDraw(bool)
       
  1497 {
       
  1498     delete rubberBand;
       
  1499     rubberBand = 0;
       
  1500 }
       
  1501 
       
  1502 /*!
       
  1503   \reimp
       
  1504 */
       
  1505 void Q3DockWindow::drawFrame(QPainter *p)
       
  1506 {
       
  1507     if (place() == InDock) {
       
  1508         Q3Frame::drawFrame(p);
       
  1509         return;
       
  1510     }
       
  1511 
       
  1512     QStyleOptionFrame opt;
       
  1513     opt.rect = rect();
       
  1514     opt.palette = palette();
       
  1515     opt.state = QStyle::State_None;
       
  1516     if (titleBar->isActive())
       
  1517         opt.state |= QStyle::State_Active;
       
  1518     opt.lineWidth = lineWidth();
       
  1519     opt.midLineWidth = midLineWidth();
       
  1520 
       
  1521     style()->drawPrimitive(QStyle::PE_FrameWindow, &opt, p, this);
       
  1522 }
       
  1523 
       
  1524 /*!
       
  1525   \reimp
       
  1526 */
       
  1527 void Q3DockWindow::drawContents(QPainter *p)
       
  1528 {
       
  1529     // This is only used by the PocketPC style. We probably need to revist later.
       
  1530     QStyleOption opt(0, QStyleOption::SO_Default);
       
  1531     opt.init(this);
       
  1532     if (titleBar->isActive())
       
  1533         opt.state |= QStyle::State_Active;
       
  1534     style()->drawControl(QStyle::CE_Q3DockWindowEmptyArea, &opt, p, this);
       
  1535 }
       
  1536 
       
  1537 /*!
       
  1538     \property Q3DockWindow::resizeEnabled
       
  1539     \brief whether the dock window is resizeable
       
  1540 
       
  1541     A resizeable dock window can be resized using splitter-like
       
  1542     handles inside a dock area and like every other top level window
       
  1543     when floating.
       
  1544 
       
  1545     A dock window is both horizontally and vertically stretchable if
       
  1546     you call setResizeEnabled(true).
       
  1547 
       
  1548     This property is false by default.
       
  1549 
       
  1550     \sa setVerticallyStretchable() setHorizontallyStretchable()
       
  1551 */
       
  1552 
       
  1553 void Q3DockWindow::setResizeEnabled(bool b)
       
  1554 {
       
  1555     resizeEnabled = b;
       
  1556     updateGui();
       
  1557 }
       
  1558 
       
  1559 /*!
       
  1560     \property Q3DockWindow::movingEnabled
       
  1561     \brief whether the user can move the dock window within the dock
       
  1562     area, move the dock window to another dock area, or float the dock
       
  1563     window.
       
  1564 
       
  1565     This property is true by default.
       
  1566 */
       
  1567 
       
  1568 void Q3DockWindow::setMovingEnabled(bool b)
       
  1569 {
       
  1570     moveEnabled = b;
       
  1571     updateGui();
       
  1572 }
       
  1573 
       
  1574 bool Q3DockWindow::isResizeEnabled() const
       
  1575 {
       
  1576     return resizeEnabled;
       
  1577 }
       
  1578 
       
  1579 bool Q3DockWindow::isMovingEnabled() const
       
  1580 {
       
  1581     return moveEnabled;
       
  1582 }
       
  1583 
       
  1584 /*!
       
  1585     \property Q3DockWindow::closeMode
       
  1586     \brief the close mode of a dock window
       
  1587 
       
  1588     Defines when (if ever) the dock window has a close button. The
       
  1589     choices are \c Never, \c Docked (i.e. only when docked), \c
       
  1590     Undocked (only when undocked, i.e. floated) or \c Always.
       
  1591 
       
  1592     The default is \c Never.
       
  1593 */
       
  1594 
       
  1595 void Q3DockWindow::setCloseMode(int m)
       
  1596 {
       
  1597     cMode = m;
       
  1598     if (place() == InDock) {
       
  1599         horHandle->updateGui();
       
  1600         verHandle->updateGui();
       
  1601     } else {
       
  1602         titleBar->updateGui();
       
  1603     }
       
  1604 }
       
  1605 
       
  1606 /*!
       
  1607     Returns true if the dock window has a close button; otherwise
       
  1608     returns false. The result depends on the dock window's \l Place
       
  1609     and its \l CloseMode.
       
  1610 
       
  1611     \sa setCloseMode()
       
  1612 */
       
  1613 
       
  1614 bool Q3DockWindow::isCloseEnabled() const
       
  1615 {
       
  1616     return  (((cMode & Docked) == Docked && place() == InDock) ||
       
  1617               ((cMode & Undocked) == Undocked && place() == OutsideDock));
       
  1618 }
       
  1619 
       
  1620 int Q3DockWindow::closeMode() const
       
  1621 {
       
  1622     return cMode;
       
  1623 }
       
  1624 
       
  1625 /*!
       
  1626     \property Q3DockWindow::horizontallyStretchable
       
  1627     \brief whether the dock window is horizontally stretchable.
       
  1628 
       
  1629     A dock window is horizontally stretchable if you call
       
  1630     setHorizontallyStretchable(true) or setResizeEnabled(true).
       
  1631 
       
  1632     \warning Stretchability is broken. You must call
       
  1633     setResizeEnabled(true) to get proper behavior and even then
       
  1634     Q3DockWindow does not limit stretchablilty.
       
  1635 
       
  1636     \sa setResizeEnabled()
       
  1637 */
       
  1638 
       
  1639 void Q3DockWindow::setHorizontallyStretchable(bool b)
       
  1640 {
       
  1641     stretchable[Qt::Horizontal] = b;
       
  1642 }
       
  1643 
       
  1644 /*!
       
  1645     \property Q3DockWindow::verticallyStretchable
       
  1646     \brief whether the dock window is vertically stretchable.
       
  1647 
       
  1648     A dock window is vertically stretchable if you call
       
  1649     setVerticallyStretchable(true) or setResizeEnabled(true).
       
  1650 
       
  1651     \sa setResizeEnabled()
       
  1652 
       
  1653     \warning Stretchability is broken. You must call
       
  1654     setResizeEnabled(true) to get proper behavior and even then
       
  1655     Q3DockWindow does not limit stretchablilty.
       
  1656 */
       
  1657 
       
  1658 void Q3DockWindow::setVerticallyStretchable(bool b)
       
  1659 {
       
  1660     stretchable[Qt::Vertical] = b;
       
  1661 }
       
  1662 
       
  1663 bool Q3DockWindow::isHorizontallyStretchable() const
       
  1664 {
       
  1665     return isResizeEnabled() || stretchable[Qt::Horizontal];
       
  1666 }
       
  1667 
       
  1668 bool Q3DockWindow::isVerticallyStretchable() const
       
  1669 {
       
  1670     return isResizeEnabled() || stretchable[Qt::Vertical];
       
  1671 }
       
  1672 
       
  1673 /*!
       
  1674     \property Q3DockWindow::stretchable
       
  1675     \brief whether the dock window is stretchable in the current
       
  1676     orientation()
       
  1677 
       
  1678     This property can be set using setHorizontallyStretchable() and
       
  1679     setVerticallyStretchable(), or with setResizeEnabled().
       
  1680 
       
  1681     \warning Stretchability is broken. You must call
       
  1682     setResizeEnabled(true) to get proper behavior and even then
       
  1683     Q3DockWindow does not limit stretchablilty.
       
  1684 
       
  1685     \sa setResizeEnabled()
       
  1686 */
       
  1687 
       
  1688 bool Q3DockWindow::isStretchable() const
       
  1689 {
       
  1690     if (orientation() == Qt::Horizontal)
       
  1691         return isHorizontallyStretchable();
       
  1692     return isVerticallyStretchable();
       
  1693 }
       
  1694 
       
  1695 /*!
       
  1696     Returns the orientation of the dock window.
       
  1697 
       
  1698     \sa orientationChanged()
       
  1699 */
       
  1700 
       
  1701 Qt::Orientation Q3DockWindow::orientation() const
       
  1702 {
       
  1703     if (dockArea)
       
  1704         return dockArea->orientation();
       
  1705     if (qobject_cast<const Q3ToolBar*>(this))
       
  1706         return Qt::Horizontal;
       
  1707     return (((Q3DockWindow*)this)->boxLayout()->direction() == QBoxLayout::LeftToRight ||
       
  1708              ((Q3DockWindow*)this)->boxLayout()->direction() == QBoxLayout::RightToLeft ?
       
  1709              Qt::Horizontal : Qt::Vertical);
       
  1710 }
       
  1711 
       
  1712 int Q3DockWindow::offset() const
       
  1713 {
       
  1714     return offs;
       
  1715 }
       
  1716 
       
  1717 /*!
       
  1718     \property Q3DockWindow::offset
       
  1719     \brief the dock window's preferred offset from the dock area's
       
  1720     left edge (top edge for vertical dock areas)
       
  1721 
       
  1722     The default is 0.
       
  1723 */
       
  1724 
       
  1725 void Q3DockWindow::setOffset(int o)
       
  1726 {
       
  1727     offs = o;
       
  1728 }
       
  1729 
       
  1730 /*!
       
  1731     Returns the dock window's preferred size (fixed extent).
       
  1732 
       
  1733     \sa setFixedExtentWidth() setFixedExtentHeight()
       
  1734 */
       
  1735 
       
  1736 QSize Q3DockWindow::fixedExtent() const
       
  1737 {
       
  1738     return fExtent;
       
  1739 }
       
  1740 
       
  1741 /*!
       
  1742     Sets the dock window's preferred width for its fixed extent (size)
       
  1743     to \a w.
       
  1744 
       
  1745     \sa setFixedExtentHeight()
       
  1746 */
       
  1747 
       
  1748 void Q3DockWindow::setFixedExtentWidth(int w)
       
  1749 {
       
  1750     fExtent.setWidth(w);
       
  1751 }
       
  1752 
       
  1753 /*!
       
  1754     Sets the dock window's preferred height for its fixed extent
       
  1755     (size) to \a h.
       
  1756 
       
  1757     \sa setFixedExtentWidth()
       
  1758 */
       
  1759 
       
  1760 void Q3DockWindow::setFixedExtentHeight(int h)
       
  1761 {
       
  1762     fExtent.setHeight(h);
       
  1763 }
       
  1764 
       
  1765 /*!
       
  1766     \property Q3DockWindow::newLine
       
  1767     \brief whether the dock window prefers to start a new line in the
       
  1768     dock area.
       
  1769 
       
  1770     The default is false, i.e. the dock window doesn't require a new
       
  1771     line in the dock area.
       
  1772 */
       
  1773 
       
  1774 void Q3DockWindow::setNewLine(bool b)
       
  1775 {
       
  1776     nl = b;
       
  1777 }
       
  1778 
       
  1779 bool Q3DockWindow::newLine() const
       
  1780 {
       
  1781     return nl;
       
  1782 }
       
  1783 
       
  1784 /*!
       
  1785     Returns the layout which is used for adding widgets to the dock
       
  1786     window. The layout's orientation is set automatically to match the
       
  1787     orientation of the dock window. You can add widgets to the layout
       
  1788     using the box layout's QBoxLayout::addWidget() function.
       
  1789 
       
  1790     If the dock window only needs to contain a single widget use
       
  1791     setWidget() instead.
       
  1792 
       
  1793     \sa setWidget() setOrientation()
       
  1794 */
       
  1795 
       
  1796 QBoxLayout *Q3DockWindow::boxLayout()
       
  1797 {
       
  1798     return childBox;
       
  1799 }
       
  1800 
       
  1801 /*! \reimp
       
  1802  */
       
  1803 
       
  1804 QSize Q3DockWindow::sizeHint() const
       
  1805 {
       
  1806     QSize sh(Q3Frame::sizeHint());
       
  1807     if (place() == InDock)
       
  1808         sh = sh.expandedTo(fixedExtent());
       
  1809     sh = sh.expandedTo(QSize(16, 16));
       
  1810     if (area()) {
       
  1811         if (area()->orientation() == Qt::Horizontal && !vHandleRight->isVisible())
       
  1812             sh.setWidth(sh.width() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3);
       
  1813         else if (area()->orientation() == Qt::Vertical && !hHandleBottom->isVisible())
       
  1814             sh.setHeight(sh.height() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3);
       
  1815     }
       
  1816     return sh;
       
  1817 }
       
  1818 
       
  1819 /*! \internal
       
  1820  */
       
  1821 
       
  1822 QSize Q3DockWindow::minimumSize() const
       
  1823 {
       
  1824     QSize ms(Q3Frame::minimumSize());
       
  1825     if (place() == InDock)
       
  1826         ms = ms.expandedTo(fixedExtent());
       
  1827     ms = ms.expandedTo(QSize(16, 16));
       
  1828     if (area()) {
       
  1829         if (area()->orientation() == Qt::Horizontal && !vHandleRight->isVisible())
       
  1830             ms.setWidth(ms.width() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3);
       
  1831         else if (area()->orientation() == Qt::Vertical && !hHandleBottom->isVisible())
       
  1832             ms.setHeight(ms.height() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3);
       
  1833     }
       
  1834     return ms;
       
  1835 }
       
  1836 
       
  1837 /*! \reimp
       
  1838  */
       
  1839 
       
  1840 QSize Q3DockWindow::minimumSizeHint() const
       
  1841 {
       
  1842     QSize msh(Q3Frame::minimumSize());
       
  1843     if (place() == InDock)
       
  1844         msh = msh.expandedTo(fixedExtent());
       
  1845     msh = msh.expandedTo(QSize(16, 16));
       
  1846     if (area()) {
       
  1847         if (area()->orientation() == Qt::Horizontal && !vHandleRight->isVisible())
       
  1848             msh.setWidth(msh.width() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3);
       
  1849         else if (area()->orientation() == Qt::Vertical && !hHandleBottom->isVisible())
       
  1850             msh.setHeight(msh.height() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3);
       
  1851     }
       
  1852     return msh;
       
  1853 }
       
  1854 
       
  1855 /*!
       
  1856     \fn void Q3DockWindow::undock()
       
  1857 
       
  1858     Undocks the Q3DockWindow from its current dock area if it is
       
  1859     docked; otherwise does nothing.
       
  1860 
       
  1861     \sa dock() Q3DockArea::moveDockWindow(),
       
  1862     Q3DockArea::removeDockWindow(), Q3MainWindow::moveDockWindow(),
       
  1863     Q3MainWindow::removeDockWindow()
       
  1864 */
       
  1865 
       
  1866 /*!
       
  1867     \fn void Q3DockWindow::undock(QWidget *widget)
       
  1868 
       
  1869     Undocks the specified \a widget from its current dock area if it is
       
  1870     docked; otherwise does nothing.
       
  1871 
       
  1872     \sa dock() Q3DockArea::moveDockWindow(),
       
  1873     Q3DockArea::removeDockWindow(), Q3MainWindow::moveDockWindow(),
       
  1874     Q3MainWindow::removeDockWindow()
       
  1875 */
       
  1876 void Q3DockWindow::undock(QWidget *w)
       
  1877 {
       
  1878     Q3MainWindow *mw = 0;
       
  1879     if (area())
       
  1880         mw = qobject_cast<Q3MainWindow*>(area()->parentWidget());
       
  1881     if (mw && !mw->isDockEnabled(this, Qt::DockTornOff))
       
  1882         return;
       
  1883     if ((place() == OutsideDock && !w))
       
  1884         return;
       
  1885 
       
  1886     QPoint p(50, 50);
       
  1887     if (window())
       
  1888         p = window()->pos() + QPoint(20, 20);
       
  1889     if (dockArea) {
       
  1890         delete (Q3DockArea::DockWindowData*)dockWindowData;
       
  1891         dockWindowData = dockArea->dockWindowData(this);
       
  1892         dockArea->removeDockWindow(this, true, orientation() != Qt::Horizontal && qobject_cast<Q3ToolBar*>(this));
       
  1893     }
       
  1894     dockArea = 0;
       
  1895     if (lastPos != QPoint(-1, -1) && lastPos.x() > 0 && lastPos.y() > 0)
       
  1896         move(lastPos);
       
  1897     else
       
  1898         move(p);
       
  1899     if (lastSize != QSize(-1, -1))
       
  1900         resize(lastSize);
       
  1901     curPlace = OutsideDock;
       
  1902     updateGui();
       
  1903     emit orientationChanged(orientation());
       
  1904     QApplication::sendPostedEvents(this, QEvent::LayoutHint);
       
  1905     if (qobject_cast<Q3ToolBar*>(this))
       
  1906         adjustSize();
       
  1907     if (!w) {
       
  1908         if (!parentWidget() || parentWidget()->isVisible()) {
       
  1909             if (lastSize == QSize(-1, -1))
       
  1910                 setAttribute(Qt::WA_Resized, false);// Ensures size is recalculated (opaque).
       
  1911             show();
       
  1912         }
       
  1913     } else {
       
  1914         setParent(w, 0);
       
  1915         move(-width() - 5, -height() - 5);
       
  1916         resize(1, 1);
       
  1917         show();
       
  1918     }
       
  1919     if (parentWidget() && isWindow())
       
  1920         parentWidget()->setActiveWindow();
       
  1921     emit placeChanged(place());
       
  1922 }
       
  1923 
       
  1924 void Q3DockWindow::removeFromDock(bool fixNewLines)
       
  1925 {
       
  1926     if (dockArea)
       
  1927         dockArea->removeDockWindow(this, false, false, fixNewLines);
       
  1928 }
       
  1929 
       
  1930 /*!
       
  1931     Docks the dock window into the last dock area in which it was
       
  1932     docked.
       
  1933 
       
  1934     If the dock window has no last dock area (e.g. it was created as a
       
  1935     floating window and has never been docked), or if the last dock
       
  1936     area it was docked in does not exist (e.g. the dock area has been
       
  1937     deleted), nothing happens.
       
  1938 
       
  1939     The dock window will dock with the dock area regardless of the return value
       
  1940     of Q3DockArea::isDockWindowAccepted().
       
  1941 
       
  1942     \sa undock() Q3DockArea::moveDockWindow(),
       
  1943     Q3DockArea::removeDockWindow(), Q3MainWindow::moveDockWindow(),
       
  1944     Q3MainWindow::removeDockWindow(), Q3DockArea::isDockWindowAccepted()
       
  1945 
       
  1946 */
       
  1947 
       
  1948 void Q3DockWindow::dock()
       
  1949 {
       
  1950     if (!(Q3DockArea::DockWindowData*)dockWindowData ||
       
  1951          !((Q3DockArea::DockWindowData*)dockWindowData)->area)
       
  1952         return;
       
  1953     curPlace = InDock;
       
  1954     lastPos = pos();
       
  1955     lastSize = size();
       
  1956     ((Q3DockArea::DockWindowData*)dockWindowData)->
       
  1957         area->dockWindow(this, (Q3DockArea::DockWindowData*)dockWindowData);
       
  1958     emit orientationChanged(orientation());
       
  1959     emit placeChanged(place());
       
  1960 }
       
  1961 
       
  1962 /*! \reimp
       
  1963  */
       
  1964 
       
  1965 void Q3DockWindow::hideEvent(QHideEvent *e)
       
  1966 {
       
  1967     Q3Frame::hideEvent(e);
       
  1968 }
       
  1969 
       
  1970 /*! \reimp
       
  1971  */
       
  1972 
       
  1973 void Q3DockWindow::showEvent(QShowEvent *e)
       
  1974 {
       
  1975     if (curPlace == OutsideDock && (parent() && parent()->objectName() == QLatin1String("qt_hide_dock"))) {
       
  1976         QRect sr = qApp->desktop()->availableGeometry(this);
       
  1977         if (!sr.contains(pos())) {
       
  1978             int nx = qMin(qMax(x(), sr.x()), sr.right()-width());
       
  1979             int ny = qMin(qMax(y(), sr.y()), sr.bottom()-height());
       
  1980             move(nx, ny);
       
  1981         }
       
  1982     }
       
  1983 
       
  1984     Q3Frame::showEvent(e);
       
  1985 }
       
  1986 
       
  1987 /*!
       
  1988     \property Q3DockWindow::opaqueMoving
       
  1989     \brief whether the dock window will be shown normally whilst it is
       
  1990     being moved.
       
  1991 
       
  1992     If this property is false, (the default), the dock window will be
       
  1993     represented by an outline rectangle whilst it is being moved.
       
  1994 
       
  1995     \warning Currently opaque moving has some problems and we do not
       
  1996     recommend using it at this time. We expect to fix these problems
       
  1997     in a future release.
       
  1998 */
       
  1999 
       
  2000 void Q3DockWindow::setOpaqueMoving(bool b)
       
  2001 {
       
  2002     opaque = b;
       
  2003     horHandle->setOpaqueMoving(b);
       
  2004     verHandle->setOpaqueMoving(b);
       
  2005     titleBar->setOpaqueMoving(b);
       
  2006 }
       
  2007 
       
  2008 bool Q3DockWindow::opaqueMoving() const
       
  2009 {
       
  2010     return opaque;
       
  2011 }
       
  2012 
       
  2013 void Q3DockWindow::updateSplitterVisibility(bool visible)
       
  2014 {
       
  2015     if (area() && isResizeEnabled()) {
       
  2016         if (orientation() == Qt::Horizontal) {
       
  2017             if (visible)
       
  2018                 vHandleRight->show();
       
  2019             else
       
  2020                 vHandleRight->hide();
       
  2021             vHandleLeft->hide();
       
  2022         } else {
       
  2023             if (visible)
       
  2024                 hHandleBottom->show();
       
  2025             else
       
  2026                 hHandleBottom->hide();
       
  2027             hHandleTop->hide();
       
  2028         }
       
  2029     }
       
  2030 }
       
  2031 
       
  2032 /*! \reimp */
       
  2033 bool Q3DockWindow::eventFilter(QObject * o, QEvent *e)
       
  2034 {
       
  2035     if (!o->isWidgetType())
       
  2036         return false;
       
  2037 
       
  2038     if (e->type() == QEvent::KeyPress &&
       
  2039         (horHandle->mousePressed ||
       
  2040           verHandle->mousePressed ||
       
  2041           titleBar->mousePressed)) {
       
  2042         QKeyEvent *ke = (QKeyEvent*)e;
       
  2043         if (ke->key() == Qt::Key_Escape) {
       
  2044             horHandle->mousePressed =
       
  2045                 verHandle->mousePressed =
       
  2046                     titleBar->mousePressed = false;
       
  2047             endRectDraw(!opaque);
       
  2048             qApp->removeEventFilter(this);
       
  2049             return true;
       
  2050         }
       
  2051     } else if (((QWidget*)o)->window() != this && place() == OutsideDock && isWindow()) {
       
  2052         if ((e->type() == QEvent::WindowDeactivate ||
       
  2053             e->type() == QEvent::WindowActivate))
       
  2054             event(e);
       
  2055     }
       
  2056     return false;
       
  2057 }
       
  2058 
       
  2059 /*! \reimp */
       
  2060 bool Q3DockWindow::event(QEvent *e)
       
  2061 {
       
  2062     switch (e->type()) {
       
  2063     case QEvent::WindowDeactivate:
       
  2064         if (place() == OutsideDock && isWindow() && parentWidget()
       
  2065              && parentWidget()->isActiveWindow())
       
  2066             return true;
       
  2067         break;
       
  2068     case QEvent::HideToParent:
       
  2069         emit visibilityChanged(false);
       
  2070         break;
       
  2071     case QEvent::ShowToParent:
       
  2072         emit visibilityChanged(true);
       
  2073         break;
       
  2074     case QEvent::WindowTitleChange:
       
  2075     {
       
  2076         QString s = Q3Frame::windowTitle();
       
  2077         titleBar->setWindowTitle(s);
       
  2078 #ifndef QT_NO_TOOLTIP
       
  2079         horHandle->setToolTip(s);
       
  2080         verHandle->setToolTip(s);
       
  2081 #endif
       
  2082         break;
       
  2083     }
       
  2084     default:
       
  2085         break;
       
  2086     }
       
  2087     return Q3Frame::event(e);
       
  2088 }
       
  2089 
       
  2090 /*!
       
  2091     Returns the dock window's title.
       
  2092 */
       
  2093 QString Q3DockWindow::windowTitle() const
       
  2094 {
       
  2095     return titleBar->windowTitle();
       
  2096 }
       
  2097 
       
  2098 /*! \reimp */
       
  2099 void Q3DockWindow::contextMenuEvent(QContextMenuEvent *e)
       
  2100 {
       
  2101     QObject *o = this;
       
  2102     while (o) {
       
  2103         if (qobject_cast<Q3MainWindow*>(o))
       
  2104             break;
       
  2105         o = o->parent();
       
  2106     }
       
  2107     if (!o || ! ((Q3MainWindow*)o)->showDockMenu(e->globalPos()))
       
  2108         e->ignore();
       
  2109 }
       
  2110 
       
  2111 QT_END_NAMESPACE
       
  2112 
       
  2113 #include "q3dockwindow.moc"
       
  2114 
       
  2115 #endif //QT_NO_MAINWINDOW