~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/qt3support/widgets/q3dockwindow.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

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