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

« back to all changes in this revision

Viewing changes to src/gui/widgets/qdockwidget.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 widgets module 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 "qdockwidget.h"
 
30
 
 
31
#include <qaction.h>
 
32
#include <qapplication.h>
 
33
#include <qdesktopwidget.h>
 
34
#include <qdrawutil.h>
 
35
#include <qevent.h>
 
36
#include <qfontmetrics.h>
 
37
#include <qmainwindow.h>
 
38
#include <qpainter.h>
 
39
#include <qrubberband.h>
 
40
#include <qstyle.h>
 
41
#include <qstyleoption.h>
 
42
#include <qtoolbutton.h>
 
43
 
 
44
#include <private/qwidgetresizehandler_p.h>
 
45
 
 
46
#include "qdockwidget_p.h"
 
47
#include "qdockwidgetlayout_p.h"
 
48
#include "qmainwindowlayout_p.h"
 
49
 
 
50
 
 
51
inline bool hasFeature(QDockWidget *dockwidget, QDockWidget::DockWidgetFeature feature)
 
52
{ return (dockwidget->features() & feature) == feature; }
 
53
 
 
54
 
 
55
/*
 
56
    A Dock Window:
 
57
 
 
58
    [+] is the float button
 
59
    [X] is the close button
 
60
 
 
61
    +-------------------------------+
 
62
    | Dock Window Title       [+][X]|
 
63
    +-------------------------------+
 
64
    |                               |
 
65
    | place to put the single       |
 
66
    | QDockWidget child (this space |
 
67
    | does not yet have a name)     |
 
68
    |                               |
 
69
    |                               |
 
70
    |                               |
 
71
    |                               |
 
72
    |                               |
 
73
    |                               |
 
74
    |                               |
 
75
    |                               |
 
76
    |                               |
 
77
    +-------------------------------+
 
78
 
 
79
*/
 
80
 
 
81
 
 
82
 
 
83
 
 
84
/*
 
85
  Tool window title
 
86
*/
 
87
 
 
88
class QDockWidgetTitle;
 
89
 
 
90
class QDockWidgetTitleButton : public QAbstractButton
 
91
{
 
92
    Q_OBJECT
 
93
 
 
94
public:
 
95
    QDockWidgetTitleButton(QDockWidgetTitle *title);
 
96
 
 
97
    QSize sizeHint() const;
 
98
    inline QSize minimumSizeHint() const
 
99
    { return sizeHint(); }
 
100
 
 
101
    void enterEvent(QEvent *event);
 
102
    void leaveEvent(QEvent *event);
 
103
    void paintEvent(QPaintEvent *event);
 
104
};
 
105
 
 
106
class QDockWidgetTitle : public QWidget
 
107
{
 
108
    Q_OBJECT
 
109
 
 
110
public:
 
111
    QDockWidgetTitle(QDockWidget *tw);
 
112
 
 
113
    void styleChange(QStyle &);
 
114
 
 
115
    void mousePressEvent(QMouseEvent *event);
 
116
    void mouseMoveEvent(QMouseEvent *event);
 
117
    void mouseReleaseEvent(QMouseEvent *event);
 
118
    void contextMenuEvent(QContextMenuEvent *event);
 
119
    void paintEvent(QPaintEvent *event);
 
120
 
 
121
    void updateButtons();
 
122
    void updateWindowTitle();
 
123
 
 
124
    QDockWidget *dockwidget;
 
125
 
 
126
    QSpacerItem *spacer;
 
127
    QDockWidgetTitleButton *floatButton;
 
128
    QDockWidgetTitleButton *closeButton;
 
129
 
 
130
    QBoxLayout *box;
 
131
 
 
132
    struct DragState {
 
133
        QRubberBand *rubberband;
 
134
        QRect origin;   // starting position
 
135
        QRect current;  // current size of the dockwidget (can be either placed or floating)
 
136
        QRect floating; // size of the floating dockwidget
 
137
        QPoint offset;
 
138
        bool canDrop;
 
139
    };
 
140
    DragState *state;
 
141
 
 
142
public slots:
 
143
    void toggleTopLevel();
 
144
};
 
145
 
 
146
QDockWidgetTitleButton::QDockWidgetTitleButton(QDockWidgetTitle *title)
 
147
    : QAbstractButton(title)
 
148
{ setFocusPolicy(Qt::NoFocus); }
 
149
 
 
150
QSize QDockWidgetTitleButton::sizeHint() const
 
151
{
 
152
    ensurePolished();
 
153
 
 
154
    int dim = 0;
 
155
    if (!icon().isNull()) {
 
156
        const QPixmap pm = icon().pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize), QIcon::Normal);
 
157
        dim = qMax(pm.width(), pm.height());
 
158
    }
 
159
 
 
160
    return QSize(dim + 4, dim + 4);
 
161
}
 
162
 
 
163
void QDockWidgetTitleButton::enterEvent(QEvent *event)
 
164
{
 
165
    if (isEnabled()) update();
 
166
    QAbstractButton::enterEvent(event);
 
167
}
 
168
 
 
169
void QDockWidgetTitleButton::leaveEvent(QEvent *event)
 
170
{
 
171
    if (isEnabled()) update();
 
172
    QAbstractButton::leaveEvent(event);
 
173
}
 
174
 
 
175
void QDockWidgetTitleButton::paintEvent(QPaintEvent *)
 
176
{
 
177
    QPainter p(this);
 
178
 
 
179
    QRect r = rect();
 
180
    QStyleOption opt;
 
181
    opt.init(this);
 
182
    opt.state |= QStyle::State_AutoRaise;
 
183
    if (isEnabled() && underMouse() && !isChecked() && !isDown())
 
184
        opt.state |= QStyle::State_Raised;
 
185
    if (isChecked())
 
186
        opt.state |= QStyle::State_On;
 
187
    if (isDown())
 
188
        opt.state |= QStyle::State_Sunken;
 
189
    style()->drawPrimitive(QStyle::PE_PanelButtonTool, &opt, &p, this);
 
190
 
 
191
    r.adjust(2, 2, -2, -2);
 
192
    QPixmap pm = icon().pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize), isEnabled() ? QIcon::Normal : QIcon::Disabled);
 
193
    style()->drawItemPixmap(&p, r, Qt::AlignCenter, pm);
 
194
}
 
195
 
 
196
QDockWidgetTitle::QDockWidgetTitle(QDockWidget *tw)
 
197
    : QWidget(tw), dockwidget(tw), floatButton(0), closeButton(0), state(0)
 
198
{
 
199
    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
 
200
 
 
201
    spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed);
 
202
 
 
203
    box = new QBoxLayout(QBoxLayout::LeftToRight, this);
 
204
    box->setMargin(style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth));
 
205
    box->setSpacing(0);
 
206
    box->addItem(spacer);
 
207
 
 
208
    updateButtons();
 
209
    updateWindowTitle();
 
210
}
 
211
 
 
212
void QDockWidgetTitle::styleChange(QStyle &)
 
213
{
 
214
    box->setMargin(style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth));
 
215
 
 
216
    updateWindowTitle();
 
217
 
 
218
    if (floatButton)
 
219
        floatButton->setIcon(style()->standardPixmap(QStyle::SP_TitleBarMaxButton));
 
220
 
 
221
    if (closeButton)
 
222
        closeButton->setIcon(style()->standardPixmap(QStyle::SP_TitleBarCloseButton));
 
223
}
 
224
 
 
225
void QDockWidgetTitle::mousePressEvent(QMouseEvent *event)
 
226
{
 
227
    if (event->button() != Qt::LeftButton) return;
 
228
 
 
229
    // check if the tool window is movable... do nothing if it is not
 
230
    if (!::hasFeature(dockwidget, QDockWidget::DockWidgetMovable))
 
231
        return;
 
232
 
 
233
    QMainWindowLayout *layout =
 
234
        qobject_cast<QMainWindowLayout *>(dockwidget->parentWidget()->layout());
 
235
    if (!layout)
 
236
        return;
 
237
    layout->saveLayoutInfo();
 
238
 
 
239
    Q_ASSERT(!state);
 
240
    state = new DragState;
 
241
 
 
242
    const int screen_number = QApplication::desktop()->screenNumber(window());
 
243
    state->rubberband = new QRubberBand(QRubberBand::Rectangle,
 
244
                                        QApplication::desktop()->screen(screen_number));
 
245
 
 
246
    // the current location of the tool window in global coordinates
 
247
    state->origin = QRect(dockwidget->mapToGlobal(QPoint(0, 0)), dockwidget->size());
 
248
    state->current = state->origin;
 
249
 
 
250
    // like the above, except using the tool window's size hint
 
251
    state->floating = dockwidget->isWindow()
 
252
                      ? state->current
 
253
                      : QRect(state->current.topLeft(), dockwidget->sizeHint());
 
254
 
 
255
    const QPoint globalPos = event->globalPos();
 
256
    const int dl = globalPos.x() - state->current.left(),
 
257
              dr = state->current.right() - globalPos.x(),
 
258
       halfWidth = state->floating.width() / 2;
 
259
    state->offset = mapFrom(dockwidget,
 
260
                            (dl < dr)
 
261
                            ? QPoint(qMin(dl, halfWidth), 0)
 
262
                            : QPoint(state->floating.width() - qMin(dr, halfWidth), 0));
 
263
    state->offset = mapTo(dockwidget, QPoint(state->offset.x(), event->pos().y()));
 
264
 
 
265
    state->canDrop = true;
 
266
 
 
267
    state->rubberband->setGeometry(state->current);
 
268
    state->rubberband->show();
 
269
 
 
270
#ifdef Q_WS_WIN
 
271
    /* Work around windows expose bug when windows are partially covered by
 
272
     * a top level transparent object.
 
273
     */
 
274
    dockwidget->update();
 
275
    QWidgetList children = qFindChildren<QWidget *>(dockwidget);
 
276
    for (int i=0; i<children.size(); ++i)
 
277
        children.at(i)->update();
 
278
#endif
 
279
}
 
280
 
 
281
void QDockWidgetTitle::mouseMoveEvent(QMouseEvent *event)
 
282
{
 
283
    if (!state)
 
284
        return;
 
285
 
 
286
    QRect target;
 
287
 
 
288
    if (!(event->modifiers() & Qt::ControlModifier)) {
 
289
        // see if there is a main window under us, and ask it to place the tool window
 
290
        QWidget *widget = QApplication::widgetAt(event->globalPos());
 
291
        if (widget) {
 
292
            while (widget && !qobject_cast<QMainWindow *>(widget)) {
 
293
                if (widget->isWindow()) {
 
294
                    widget = 0;
 
295
                    break;
 
296
                }
 
297
                widget = widget->parentWidget();
 
298
            }
 
299
 
 
300
            if (widget) {
 
301
                QMainWindow *mainwindow = qobject_cast<QMainWindow *>(widget);
 
302
                if (mainwindow && mainwindow == dockwidget->parentWidget()) {
 
303
                    QMainWindowLayout *layout =
 
304
                        qobject_cast<QMainWindowLayout *>(dockwidget->parentWidget()->layout());
 
305
                    Q_ASSERT(layout != 0);
 
306
                    QRect request = state->origin;
 
307
                    request.moveTopLeft(event->globalPos() - state->offset);
 
308
                    target = layout->placeDockWidget(dockwidget, request, event->globalPos());
 
309
                    layout->resetLayoutInfo();
 
310
                }
 
311
            }
 
312
        }
 
313
    }
 
314
 
 
315
    state->canDrop = target.isValid();
 
316
    if (!state->canDrop) {
 
317
        if (hasFeature(dockwidget, QDockWidget::DockWidgetFloatable)) {
 
318
            /*
 
319
              main window refused to accept the tool window,
 
320
              recalculate absolute position as if the tool window
 
321
              was to be dropped to toplevel
 
322
            */
 
323
            target = state->floating;
 
324
            target.moveTopLeft(event->globalPos() - state->offset);
 
325
        } else {
 
326
            /*
 
327
              cannot float the window, so put it back into it's
 
328
              original position
 
329
            */
 
330
            target = state->origin;
 
331
        }
 
332
    }
 
333
 
 
334
    if (state->current == target)
 
335
        return;
 
336
 
 
337
    state->rubberband->setGeometry(target);
 
338
    state->current = target;
 
339
}
 
340
 
 
341
void QDockWidgetTitle::mouseReleaseEvent(QMouseEvent *event)
 
342
{
 
343
    if (event->button() != Qt::LeftButton)
 
344
        return;
 
345
    if (!state)
 
346
        return;
 
347
 
 
348
    QMainWindowLayout *layout =
 
349
        qobject_cast<QMainWindowLayout *>(dockwidget->parentWidget()->layout());
 
350
    if (!layout)
 
351
        return;
 
352
    layout->discardLayoutInfo();
 
353
 
 
354
    delete state->rubberband;
 
355
 
 
356
    QWidget *focus = qApp->focusWidget();
 
357
 
 
358
    // calculate absolute position if the tool window was to be
 
359
    // dropped to toplevel
 
360
    QRect target;
 
361
    bool dropped = false;
 
362
    if (!(event->modifiers() & Qt::ControlModifier)) {
 
363
        // see if there is a main window under us, and ask it to drop the tool window
 
364
        QWidget *widget = QApplication::widgetAt(event->globalPos());
 
365
        if (state->canDrop && widget) {
 
366
            while (widget && !qobject_cast<QMainWindow *>(widget)) {
 
367
                if (widget->isWindow()) {
 
368
                    widget = 0;
 
369
                    break;
 
370
                }
 
371
                widget = widget->parentWidget();
 
372
            }
 
373
 
 
374
            if (widget) {
 
375
                QMainWindow *mainwindow = qobject_cast<QMainWindow *>(widget);
 
376
                if (mainwindow && mainwindow == dockwidget->parentWidget()) {
 
377
                    QMainWindowLayout *layout =
 
378
                        qobject_cast<QMainWindowLayout *>(dockwidget->parentWidget()->layout());
 
379
                    Q_ASSERT(layout != 0);
 
380
                    QRect request = state->origin;
 
381
                    request.moveTopLeft(event->globalPos() - state->offset);
 
382
                    layout->dropDockWidget(dockwidget, request, event->globalPos());
 
383
                    dropped = true;
 
384
                }
 
385
            }
 
386
        }
 
387
    }
 
388
 
 
389
    if (!dropped && hasFeature(dockwidget, QDockWidget::DockWidgetFloatable)) {
 
390
        target = state->floating;
 
391
        target.moveTopLeft(event->globalPos() - state->offset);
 
392
 
 
393
        if (!dockwidget->isFloating()) {
 
394
            dockwidget->hide();
 
395
            dockwidget->setFloating(true);
 
396
            dockwidget->setGeometry(target);
 
397
            dockwidget->show();
 
398
        } else {
 
399
            // move to new location
 
400
            dockwidget->setGeometry(target);
 
401
        }
 
402
    }
 
403
 
 
404
    // restore focus
 
405
    if (focus)
 
406
        focus->setFocus();
 
407
 
 
408
    delete state;
 
409
    state = 0;
 
410
}
 
411
 
 
412
void QDockWidgetTitle::contextMenuEvent(QContextMenuEvent *event)
 
413
{
 
414
    if (state)
 
415
        event->accept();
 
416
    else
 
417
        QWidget::contextMenuEvent(event);
 
418
}
 
419
 
 
420
void QDockWidgetTitle::paintEvent(QPaintEvent *)
 
421
{
 
422
    QPainter p(this);
 
423
 
 
424
    QStyleOptionDockWidget opt;
 
425
    opt.rect = rect();
 
426
    opt.palette = palette();
 
427
    if (isEnabled()) {
 
428
        opt.state |= QStyle::State_Enabled;
 
429
        if (underMouse())
 
430
            opt.state |= QStyle::State_MouseOver;
 
431
    }
 
432
    opt.title = dockwidget->windowTitle();
 
433
    opt.closable = hasFeature(dockwidget, QDockWidget::DockWidgetClosable);
 
434
    opt.movable = hasFeature(dockwidget, QDockWidget::DockWidgetMovable);
 
435
    opt.floatable = hasFeature(dockwidget, QDockWidget::DockWidgetFloatable);
 
436
    style()->drawControl(QStyle::CE_DockWidgetTitle, &opt, &p, this);
 
437
}
 
438
 
 
439
void QDockWidgetTitle::updateButtons()
 
440
{
 
441
    if (hasFeature(dockwidget, QDockWidget::DockWidgetFloatable)) {
 
442
        if (!floatButton) {
 
443
            floatButton = new QDockWidgetTitleButton(this);
 
444
            floatButton->setIcon(style()->standardPixmap(QStyle::SP_TitleBarMaxButton));
 
445
            connect(floatButton, SIGNAL(clicked()), SLOT(toggleTopLevel()));
 
446
 
 
447
            box->insertWidget(1, floatButton);
 
448
 
 
449
            if (!dockwidget->isHidden())
 
450
                floatButton->show();
 
451
        }
 
452
    } else {
 
453
        delete floatButton;
 
454
        floatButton = 0;
 
455
    }
 
456
 
 
457
    if (hasFeature(dockwidget, QDockWidget::DockWidgetClosable)) {
 
458
        if (!closeButton) {
 
459
            closeButton = new QDockWidgetTitleButton(this);
 
460
            closeButton->setIcon(style()->standardPixmap(QStyle::SP_TitleBarCloseButton));
 
461
            connect(closeButton, SIGNAL(clicked()), dockwidget, SLOT(close()));
 
462
 
 
463
            box->insertWidget(2, closeButton);
 
464
 
 
465
            if (!dockwidget->isHidden())
 
466
                closeButton->show();
 
467
        }
 
468
    } else {
 
469
        delete closeButton;
 
470
        closeButton = 0;
 
471
    }
 
472
}
 
473
 
 
474
void QDockWidgetTitle::updateWindowTitle()
 
475
{
 
476
    const QFontMetrics fm(font());
 
477
    spacer->changeSize(fm.width(dockwidget->windowTitle()) + box->margin() * 2, fm.lineSpacing(),
 
478
                       QSizePolicy::Expanding, QSizePolicy::Fixed);
 
479
 
 
480
    update();
 
481
}
 
482
 
 
483
void QDockWidgetTitle::toggleTopLevel()
 
484
{
 
485
    QPoint p = dockwidget->mapToGlobal(QPoint(height(), height()));
 
486
    bool visible = dockwidget->isVisible();
 
487
    if (visible)
 
488
        dockwidget->hide();
 
489
    dockwidget->setFloating(!dockwidget->isFloating());
 
490
    if (dockwidget->isWindow())
 
491
        dockwidget->move(p);
 
492
    if (visible)
 
493
        dockwidget->show();
 
494
}
 
495
 
 
496
 
 
497
 
 
498
 
 
499
 
 
500
/*
 
501
  Private class
 
502
*/
 
503
 
 
504
void QDockWidgetPrivate::init() {
 
505
    Q_Q(QDockWidget);
 
506
 
 
507
    int fw = q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth);
 
508
    top = new QVBoxLayout(q);
 
509
    top->setSpacing(fw);
 
510
    top->setMargin(qMax(fw, 3));
 
511
 
 
512
    title = new QDockWidgetTitle(q);
 
513
    top->insertWidget(0, title);
 
514
 
 
515
    box = new QVBoxLayout;
 
516
    top->addLayout(box);
 
517
 
 
518
    resizer = new QWidgetResizeHandler(q);
 
519
    resizer->setMovingEnabled(false);
 
520
    resizer->setActive(false);
 
521
 
 
522
    toggleViewAction = new QAction(q);
 
523
    toggleViewAction->setCheckable(true);
 
524
    toggleViewAction->setText(q->windowTitle());
 
525
    QObject::connect(toggleViewAction, SIGNAL(triggered(bool)), q, SLOT(toggleView(bool)));
 
526
}
 
527
 
 
528
void QDockWidgetPrivate::toggleView(bool b)
 
529
{
 
530
    Q_Q(QDockWidget);
 
531
    if (b == q->isHidden()) {
 
532
        if (b)
 
533
            q->show();
 
534
        else
 
535
            q->close();
 
536
    }
 
537
}
 
538
 
 
539
 
 
540
 
 
541
/*!
 
542
    \class QDockWidget
 
543
 
 
544
    \brief The QDockWidget class provides a widget that can be docked
 
545
    inside a QMainWindow or floated as a top-level window on the
 
546
    desktop.
 
547
 
 
548
    \ingroup application
 
549
 
 
550
    QDockWidget provides the concept of dock widgets, also know as
 
551
    tool palettes or utility windows.  Dock windows are secondary
 
552
    windows placed in the \e {dock widget area} around the
 
553
    \l{QMainWindow::centralWidget()}{central widget} in a
 
554
    QMainWindow.
 
555
 
 
556
    \image mainwindow-docks.png
 
557
 
 
558
    Dock windows can be moved inside their current area, moved into
 
559
    new areas and floated (e.g. undocked) by the end-user.  The
 
560
    QDockWidget API allows the programmer to restrict the dock widgets
 
561
    ability to move, float and close, as well as the areas in which
 
562
    they can be placed.
 
563
 
 
564
    \section1 Appearance
 
565
 
 
566
    A QDockWidget consists of a title bar and the content area.  The
 
567
    titlebar displays the dock widgets \link QWidget::windowTitle()
 
568
    window title\endlink, a \e float button and a \e close button.
 
569
    Depending on the state of the QDockWidget, the \e float and \e
 
570
    close buttons may be either disabled or not shown at all.
 
571
 
 
572
    The visual appearance of the title bar and buttons is dependent
 
573
    on the \l{QStyle}{style} in use.
 
574
 
 
575
    \sa QMainWindow
 
576
*/
 
577
 
 
578
/*!
 
579
    \enum QDockWidget::DockWidgetFeature
 
580
 
 
581
    \value DockWidgetClosable   The dock widget can be closed.
 
582
    \value DockWidgetMovable    The dock widget can be moved between docks
 
583
                                by the user.
 
584
    \value DockWidgetFloatable  The dock widget can be detached from the
 
585
                                main window, and floated as an independent
 
586
                                window.
 
587
 
 
588
    \value AllDockWidgetFeatures  The dock widget can be closed, moved,
 
589
                                  and floated.
 
590
    \value NoDockWidgetFeatures   The dock widget cannot be closed, moved,
 
591
                                  or floated.
 
592
 
 
593
    \omitvalue DockWidgetFeatureMask
 
594
    \omitvalue Reserved
 
595
*/
 
596
 
 
597
/*!
 
598
    Constructs a QDockWidget with parent \a parent and window flags \a
 
599
    flags. The dock widget will be placed in the left dock widget
 
600
    area.
 
601
*/
 
602
QDockWidget::QDockWidget(QWidget *parent, Qt::WFlags flags)
 
603
    : QWidget(*new QDockWidgetPrivate, parent, flags)
 
604
{
 
605
    Q_D(QDockWidget);
 
606
    d->init();
 
607
}
 
608
 
 
609
/*!
 
610
    Constructs a QDockWidget with parent \a parent and window flags \a
 
611
    flags. The dock widget will be placed in the left dock widget
 
612
    area.
 
613
 
 
614
    The window title is set to \a title. This title is used when the
 
615
    QDockWidget is docked and undocked. It is also used in the context
 
616
    menu provided by QMainWindow.
 
617
 
 
618
    \sa setWindowTitle()
 
619
*/
 
620
QDockWidget::QDockWidget(const QString &title, QWidget *parent, Qt::WFlags flags)
 
621
    : QWidget(*new QDockWidgetPrivate, parent, flags)
 
622
{
 
623
    Q_D(QDockWidget);
 
624
    d->init();
 
625
    setWindowTitle(title);
 
626
}
 
627
 
 
628
/*!
 
629
    Destroys the dock widget.
 
630
*/
 
631
QDockWidget::~QDockWidget()
 
632
{ }
 
633
 
 
634
/*!
 
635
    Returns the widget for the dock widget. This function returns zero
 
636
    if the widget has not been set.
 
637
 
 
638
    \sa setWidget()
 
639
*/
 
640
QWidget *QDockWidget::widget() const
 
641
{
 
642
    Q_D(const QDockWidget);
 
643
    return d->widget;
 
644
}
 
645
 
 
646
/*!
 
647
    Sets the widget for the dock widget to \a widget.
 
648
 
 
649
    \sa widget()
 
650
*/
 
651
void QDockWidget::setWidget(QWidget *widget)
 
652
{
 
653
    Q_D(QDockWidget);
 
654
    if (d->widget)
 
655
        d->box->removeWidget(d->widget);
 
656
    d->widget = widget;
 
657
    if (d->widget)
 
658
        d->box->insertWidget(1, d->widget);
 
659
}
 
660
 
 
661
/*!
 
662
    \property QDockWidget::features
 
663
    \brief whether the dock widget is movable, closable, and floatable
 
664
 
 
665
    \sa DockWidgetFeature
 
666
*/
 
667
 
 
668
void QDockWidget::setFeatures(QDockWidget::DockWidgetFeatures features)
 
669
{
 
670
    Q_D(QDockWidget);
 
671
    features &= DockWidgetFeatureMask;
 
672
    if (d->features == features)
 
673
        return;
 
674
    d->features = features;
 
675
    d->title->updateButtons();
 
676
    d->title->update();
 
677
    emit featuresChanged(d->features);
 
678
}
 
679
 
 
680
QDockWidget::DockWidgetFeatures QDockWidget::features() const
 
681
{
 
682
    Q_D(const QDockWidget);
 
683
    return d->features;
 
684
}
 
685
 
 
686
/*!
 
687
    \property QDockWidget::floating
 
688
    \brief whether the dock widget is floating
 
689
 
 
690
    A floating dock widget is presented to the user as an independent
 
691
    window "on top" of its parent QMainWindow, instead of being
 
692
    docked in the QMainWindow.
 
693
 
 
694
    \sa isWindow()
 
695
*/
 
696
void QDockWidget::setFloating(bool floating)
 
697
{
 
698
    Q_D(QDockWidget);
 
699
    if (floating == isFloating())
 
700
        return;
 
701
 
 
702
    const bool visible = isVisible();
 
703
 
 
704
    setWindowFlags(Qt::FramelessWindowHint | (floating ? Qt::Tool : Qt::Widget));
 
705
 
 
706
    if (floating) {
 
707
        if (QMainWindowLayout *layout = qobject_cast<QMainWindowLayout *>(parentWidget()->layout()))
 
708
            layout->invalidate();
 
709
    }
 
710
 
 
711
    d->resizer->setActive(floating);
 
712
 
 
713
    if (visible)
 
714
        show();
 
715
 
 
716
    emit topLevelChanged(isWindow());
 
717
}
 
718
 
 
719
/*!
 
720
    \property QDockWidget::allowedAreas
 
721
    \brief areas where the dock widget may be placed
 
722
 
 
723
    The default is Qt::AllDockWidgetAreas.
 
724
 
 
725
    \sa Qt::DockWidgetArea
 
726
*/
 
727
 
 
728
void QDockWidget::setAllowedAreas(Qt::DockWidgetAreas areas)
 
729
{
 
730
    Q_D(QDockWidget);
 
731
    areas &= Qt::DockWidgetArea_Mask;
 
732
    if (areas == d->allowedAreas)
 
733
        return;
 
734
    d->allowedAreas = areas;
 
735
    emit allowedAreasChanged(d->allowedAreas);
 
736
}
 
737
 
 
738
Qt::DockWidgetAreas QDockWidget::allowedAreas() const
 
739
{
 
740
    Q_D(const QDockWidget);
 
741
    return d->allowedAreas;
 
742
}
 
743
 
 
744
/*!
 
745
    \fn bool QDockWidget::isAreaAllowed(Qt::DockWidgetArea area) const
 
746
 
 
747
    Returns true if this dock widget can be placed in the given \a area;
 
748
    otherwise returns false.
 
749
*/
 
750
 
 
751
/*! \reimp */
 
752
void QDockWidget::changeEvent(QEvent *event)
 
753
{
 
754
    Q_D(QDockWidget);
 
755
    switch (event->type()) {
 
756
    case QEvent::WindowTitleChange:
 
757
        d->title->updateWindowTitle();
 
758
        d->toggleViewAction->setText(windowTitle());
 
759
        break;
 
760
    default:
 
761
        break;
 
762
    }
 
763
    QWidget::changeEvent(event);
 
764
}
 
765
 
 
766
/*! \reimp */
 
767
void QDockWidget::closeEvent(QCloseEvent *event)
 
768
{
 
769
    Q_D(QDockWidget);
 
770
    if (!(d->features & DockWidgetClosable))
 
771
        event->ignore();
 
772
}
 
773
 
 
774
/*! \reimp */
 
775
void QDockWidget::paintEvent(QPaintEvent *event)
 
776
{
 
777
    Q_UNUSED(event)
 
778
    QStyleOptionFrame opt;
 
779
    opt.init(this);
 
780
    QPainter p(this);
 
781
    style()->drawPrimitive(QStyle::PE_FrameDockWidget, &opt, &p, this);
 
782
}
 
783
 
 
784
/*! \reimp */
 
785
bool QDockWidget::event(QEvent *event)
 
786
{
 
787
    Q_D(QDockWidget);
 
788
    switch (event->type()) {
 
789
    case QEvent::Hide:
 
790
        if (!isHidden())
 
791
            break;
 
792
        // fallthrough intended
 
793
    case QEvent::Show:
 
794
        d->toggleViewAction->setChecked(event->type() == QEvent::Show);
 
795
        break;
 
796
    case QEvent::StyleChange: {
 
797
        int fw = style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth);
 
798
        d->top->setSpacing(fw);
 
799
        d->top->setMargin(qMax(fw, 3));
 
800
    } break;
 
801
    default:
 
802
        break;
 
803
    }
 
804
    return QWidget::event(event);
 
805
}
 
806
 
 
807
/*!
 
808
  Returns a checkable action that can be used to show or close this
 
809
  dock widget.
 
810
 
 
811
  The action's text is set to the dock widget's window title.
 
812
 
 
813
  \sa QAction::text QWidget::windowTitle
 
814
 */
 
815
QAction * QDockWidget::toggleViewAction() const
 
816
{
 
817
    Q_D(const QDockWidget);
 
818
    return d->toggleViewAction;
 
819
}
 
820
 
 
821
/*!
 
822
    \fn void QDockWidget::featuresChanged(DockWidgetFeatures features)
 
823
 
 
824
    This signal is emitted when the \l features property changes. The
 
825
    \a features parameter gives the new value of the property.
 
826
*/
 
827
 
 
828
/*!
 
829
    \fn void QDockWidget::topLevelChanged(bool topLevel)
 
830
 
 
831
    This signal is emitted when the \l floating property changes.
 
832
    The \a topLevel parameter is true if the dock widget is now floating;
 
833
    otherwise it is false.
 
834
 
 
835
    \sa isWindow()
 
836
*/
 
837
 
 
838
/*!
 
839
    \fn void QDockWidget::allowedAreasChanged(Qt::DockWidgetAreas allowedAreas)
 
840
 
 
841
    This signal is emitted when the \l allowedAreas property changes. The
 
842
    \a allowedAreas parameter gives the new value of the property.
 
843
*/
 
844
 
 
845
#include "qdockwidget.moc"
 
846
#include "moc_qdockwidget.cpp"