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

« back to all changes in this revision

Viewing changes to src/gui/widgets/qtoolbar.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 "qtoolbar.h"
 
30
 
 
31
#include <qapplication.h>
 
32
#include <qevent.h>
 
33
#include <qlayout.h>
 
34
#include <qmainwindow.h>
 
35
#include <qmenu.h>
 
36
#include <qpainter.h>
 
37
#include <qrubberband.h>
 
38
#include <qstyle.h>
 
39
#include <qstyleoption.h>
 
40
#include <qtoolbutton.h>
 
41
#ifdef Q_WS_MAC
 
42
#include <private/qt_mac_p.h>
 
43
#endif
 
44
 
 
45
#include <private/qmainwindowlayout_p.h>
 
46
 
 
47
#include "qtoolbar_p.h"
 
48
#include "qtoolbarextension_p.h"
 
49
#include "qtoolbarhandle_p.h"
 
50
#include "qtoolbarseparator_p.h"
 
51
 
 
52
static QStyleOptionFrame getStyleOption(QToolBar *tb)
 
53
{
 
54
    QStyleOptionFrame opt;
 
55
    opt.init(tb);
 
56
    if (tb->orientation() == Qt::Horizontal)
 
57
        opt.state |= QStyle::State_Horizontal;
 
58
    opt.lineWidth = tb->style()->pixelMetric(QStyle::PM_ToolBarFrameWidth);
 
59
    return opt;
 
60
}
 
61
 
 
62
/*
 
63
    QToolBarPrivate
 
64
*/
 
65
 
 
66
void QToolBarPrivate::init()
 
67
{
 
68
    Q_Q(QToolBar);
 
69
    movable = true;
 
70
    q->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
 
71
    q->setBackgroundRole(QPalette::Button);
 
72
 
 
73
 
 
74
    QStyleOptionFrame opt = getStyleOption(q);
 
75
 
 
76
    QBoxLayout *layout = new QBoxLayout(QBoxLayout::LeftToRight, q);
 
77
    QStyle *style = q->style();
 
78
 
 
79
    int e = style->pixelMetric(QStyle::PM_ToolBarIconSize);
 
80
    iconSize = QSize(e, e);
 
81
 
 
82
    layout->setAlignment(Qt::AlignLeft);
 
83
    layout->setMargin(style->pixelMetric(QStyle::PM_ToolBarFrameWidth, &opt, q)
 
84
                      + style->pixelMetric(QStyle::PM_ToolBarItemMargin, &opt, q));
 
85
    layout->setSpacing(style->pixelMetric(QStyle::PM_ToolBarItemSpacing, &opt, q));
 
86
 
 
87
    handle = new QToolBarHandle(q);
 
88
    QObject::connect(q, SIGNAL(orientationChanged(Orientation)),
 
89
                     handle, SLOT(setOrientation(Orientation)));
 
90
    layout->addWidget(handle);
 
91
    handle->setVisible(movable && (qobject_cast<QMainWindow *>(q->parentWidget()) != 0));
 
92
 
 
93
    extension = new QToolBarExtension(q);
 
94
    QObject::connect(q, SIGNAL(orientationChanged(Orientation)),
 
95
                     extension, SLOT(setOrientation(Orientation)));
 
96
    extension->setFocusPolicy(Qt::NoFocus);
 
97
    extension->hide();
 
98
 
 
99
#ifdef Q_WS_MAC
 
100
    if (q->parentWidget()) {
 
101
        // Make sure that the window has the "toolbar" button.
 
102
        extern WindowPtr qt_mac_window_for(const QWidget *); // qwidget_mac.cpp
 
103
        ChangeWindowAttributes(qt_mac_window_for(q->parentWidget()), kWindowToolbarButtonAttribute,
 
104
                               kWindowNoAttributes);
 
105
    }
 
106
#endif
 
107
 
 
108
    toggleViewAction = new QAction(q);
 
109
    toggleViewAction->setCheckable(true);
 
110
    QObject::connect(toggleViewAction, SIGNAL(triggered(bool)), q, SLOT(toggleView(bool)));
 
111
}
 
112
 
 
113
void QToolBarPrivate::toggleView(bool b)
 
114
{
 
115
    Q_Q(QToolBar);
 
116
    if (b == q->isHidden()) {
 
117
        if (b)
 
118
            q->show();
 
119
        else
 
120
            q->close();
 
121
    }
 
122
}
 
123
 
 
124
void QToolBarPrivate::updateIconSize(const QSize &sz)
 
125
{
 
126
    Q_Q(QToolBar);
 
127
    if (!explicitIconSize) {
 
128
        // iconSize not explicitly set
 
129
        q->setIconSize(sz);
 
130
        explicitIconSize = false;
 
131
    }
 
132
}
 
133
 
 
134
void QToolBarPrivate::updateToolButtonStyle(Qt::ToolButtonStyle style)
 
135
{
 
136
    Q_Q(QToolBar);
 
137
    if (!explicitToolButtonStyle) {
 
138
        q->setToolButtonStyle(style);
 
139
        explicitToolButtonStyle = false;
 
140
    }
 
141
}
 
142
 
 
143
QToolBarItem QToolBarPrivate::createItem(QAction *action)
 
144
{
 
145
    Q_Q(QToolBar);
 
146
    QToolBarItem item;
 
147
    item.action = action;
 
148
    item.hidden = false;
 
149
 
 
150
    QToolBarWidgetAction *widgetAction = qobject_cast<QToolBarWidgetAction *>(action);
 
151
    if (widgetAction) {
 
152
        item.widget = widgetAction->widget();
 
153
    } else if (action->isSeparator()) {
 
154
        item.widget = new QToolBarSeparator(q);
 
155
        QObject::connect(q, SIGNAL(orientationChanged(Orientation)),
 
156
                         item.widget, SLOT(setOrientation(Orientation)));
 
157
    } else {
 
158
        QToolButton *button = new QToolButton(q);
 
159
        button->setAutoRaise(true);
 
160
        button->setFocusPolicy(Qt::NoFocus);
 
161
        button->setIconSize(iconSize);
 
162
        button->setToolButtonStyle(toolButtonStyle);
 
163
        QObject::connect(q, SIGNAL(iconSizeChanged(QSize)),
 
164
                         button, SLOT(setIconSize(QSize)));
 
165
        QObject::connect(q, SIGNAL(toolButtonStyleChanged(ToolButtonStyle)),
 
166
                         button, SLOT(setToolButtonStyle(ToolButtonStyle)));
 
167
        button->setDefaultAction(action);
 
168
        QObject::connect(button, SIGNAL(triggered(QAction*)), q, SIGNAL(actionTriggered(QAction*)));
 
169
        if (action->menu())
 
170
            button->setPopupMode(QToolButton::MenuButtonPopup);
 
171
        item.widget = button;
 
172
    }
 
173
 
 
174
    return item;
 
175
}
 
176
 
 
177
/*
 
178
    Returns the position of \a action. This function returns -1 if \a
 
179
    action is not found.
 
180
*/
 
181
int QToolBarPrivate::indexOf(QAction *action) const
 
182
{
 
183
    for (int i = 0; i < items.size(); ++i) {
 
184
        const QToolBarItem &item = items.at(i);
 
185
        if (item.action == action)
 
186
            return i;
 
187
    }
 
188
    return -1;
 
189
}
 
190
 
 
191
/*!
 
192
    \class QToolBar
 
193
 
 
194
    \brief The QToolBar class provides a movable panel that contains a
 
195
    set of controls.
 
196
 
 
197
    \ingroup application
 
198
    \mainclass
 
199
 
 
200
    Toolbar buttons are added by adding \e actions, using addAction()
 
201
    or insertAction(). Groups of buttons can be separated using
 
202
    addSeparator() or insertSeparator(). If a toolbar button is not
 
203
    appropriate, a widget can be inserted instead using addWidget() or
 
204
    insertWidget(); examples of suitable widgets are QSpinBox,
 
205
    QDoubleSpinBox, and QComboBox. When a toolbar button is pressed it
 
206
    emits the actionTriggered() signal. Toolbars may only be added to
 
207
    QMainWindow and QMainWindow subclasses.
 
208
 
 
209
    A toolbar can be fixed in place in a particular area (e.g. at the
 
210
    top of the window), or it can be movable (isMovable()) between
 
211
    toolbar areas; see allowedAreas() and isAreaAllowed().
 
212
 
 
213
    \sa QToolButton
 
214
*/
 
215
 
 
216
/*!
 
217
    \fn bool QToolBar::isAreaAllowed(Qt::ToolBarArea area) const
 
218
 
 
219
    Returns true if this toolbar is dockable in the given \a area;
 
220
    otherwise returns false.
 
221
*/
 
222
 
 
223
/*!
 
224
    \fn void QToolBar::actionTriggered(QAction *action)
 
225
 
 
226
    This signal is emitted when a toolbar button is pressed. The
 
227
    parameter holds the toolbar button's associated \a action.
 
228
*/
 
229
 
 
230
/*!
 
231
    \fn void QToolBar::allowedAreasChanged(Qt::ToolBarAreas allowedAreas)
 
232
 
 
233
    This signal is emitted when the collection of allowed areas for the
 
234
    toolbar is changed. The new areas in which the toolbar can be positioned
 
235
    are specified by \a allowedAreas.
 
236
 
 
237
    \sa allowedAreas
 
238
*/
 
239
 
 
240
/*!
 
241
    \fn void QToolBar::iconSizeChanged(const QSize &iconSize)
 
242
 
 
243
    This signal is emitted when the icon size is changed.  The \a
 
244
    iconSize parameter holds the toolbar's new icon size.
 
245
 
 
246
    \sa iconSize QMainWindow::iconSize
 
247
*/
 
248
 
 
249
/*!
 
250
    \fn void QToolBar::movableChanged(bool movable)
 
251
 
 
252
    This signal is emitted when the toolbar becomes movable or fixed.
 
253
    If the toolbar can be moved, \a movable is true; otherwise it is
 
254
    false.
 
255
 
 
256
    \sa movable
 
257
*/
 
258
 
 
259
/*!
 
260
    \fn void QToolBar::orientationChanged(Qt::Orientation orientation)
 
261
 
 
262
    This signal is emitted when the orientation of the toolbar changes.
 
263
    The new orientation is specified by the \a orientation given.
 
264
 
 
265
    \sa orientation
 
266
*/
 
267
 
 
268
/*!
 
269
    \fn void QToolBar::toolButtonStyleChanged(Qt::ToolButtonStyle toolButtonStyle)
 
270
 
 
271
    This signal is emitted when the tool button style is changed. The
 
272
    \a toolButtonStyle parameter holds the toolbar's new tool button
 
273
    style.
 
274
 
 
275
    \sa toolButtonStyle QMainWindow::toolButtonStyle
 
276
*/
 
277
 
 
278
/*!
 
279
    Constructs a QToolBar with the given \a parent.
 
280
*/
 
281
QToolBar::QToolBar(QWidget *parent)
 
282
    : QWidget(*new QToolBarPrivate, parent, 0)
 
283
{
 
284
    Q_D(QToolBar);
 
285
    d->init();
 
286
}
 
287
 
 
288
/*!
 
289
    Constructs a QToolBar with the given \a parent.
 
290
 
 
291
    The window title is set to \a title. This title is used when the
 
292
    toolbar is floating as an independent window. It is also shown
 
293
    in the context menu provided by QMainWindow.
 
294
 
 
295
    \sa setWindowTitle()
 
296
*/
 
297
QToolBar::QToolBar(const QString &title, QWidget *parent)
 
298
    : QWidget(*new QToolBarPrivate, parent, 0)
 
299
{
 
300
    Q_D(QToolBar);
 
301
    d->init();
 
302
    setWindowTitle(title);
 
303
}
 
304
 
 
305
#ifdef QT3_SUPPORT
 
306
/*! \obsolete
 
307
    Constructs a QToolBar with the given \a parent and \a name.
 
308
*/
 
309
QToolBar::QToolBar(QWidget *parent, const char *name)
 
310
    : QWidget(*new QToolBarPrivate, parent, 0)
 
311
{
 
312
    Q_D(QToolBar);
 
313
    d->init();
 
314
    setObjectName(name);
 
315
}
 
316
#endif
 
317
 
 
318
/*!
 
319
    Destroys the toolbar.
 
320
*/
 
321
QToolBar::~QToolBar()
 
322
{
 
323
    // Remove the toolbar button if there is nothing left.
 
324
    QMainWindow *mainwindow = qobject_cast<QMainWindow *>(parentWidget());
 
325
    if (mainwindow) {
 
326
        QMainWindowLayout *mainwin_layout = qobject_cast<QMainWindowLayout *>(mainwindow->layout());
 
327
        mainwin_layout->removeToolBarInfo(this);
 
328
        mainwin_layout->relayout();
 
329
#ifdef Q_WS_MAC
 
330
        if (mainwin_layout && mainwin_layout->tb_layout_info.isEmpty())
 
331
            ChangeWindowAttributes(qt_mac_window_for(mainwindow), kWindowNoAttributes,
 
332
                                   kWindowToolbarButtonAttribute);
 
333
#endif
 
334
    }
 
335
}
 
336
 
 
337
/*! \property QToolBar::movable
 
338
    \brief whether the user can move the toolbar within the toolbar area,
 
339
    or between toolbar areas
 
340
 
 
341
    By default, this property is true.
 
342
 
 
343
    This property only makes sense if the toolbar is in a
 
344
    QMainWindow.
 
345
 
 
346
    \sa allowedAreas
 
347
*/
 
348
 
 
349
void QToolBar::setMovable(bool movable)
 
350
{
 
351
    Q_D(QToolBar);
 
352
    if (!movable == !d->movable)
 
353
        return;
 
354
    d->movable = movable;
 
355
    d->handle->setVisible(d->movable && (qobject_cast<QMainWindow *>(parentWidget()) != 0));
 
356
    emit movableChanged(d->movable);
 
357
}
 
358
 
 
359
bool QToolBar::isMovable() const
 
360
{ Q_D(const QToolBar); return d->movable; }
 
361
 
 
362
/*!
 
363
    \property QToolBar::allowedAreas
 
364
    \brief areas where the toolbar may be placed
 
365
 
 
366
    The default is \c Qt::AllToolBarAreas.
 
367
 
 
368
    This property only makes sense if the toolbar is in a
 
369
    QMainWindow.
 
370
 
 
371
    \sa movable
 
372
*/
 
373
 
 
374
void QToolBar::setAllowedAreas(Qt::ToolBarAreas areas)
 
375
{
 
376
    Q_D(QToolBar);
 
377
    areas &= Qt::ToolBarArea_Mask;
 
378
    if (areas == d->allowedAreas)
 
379
        return;
 
380
    d->allowedAreas = areas;
 
381
    emit allowedAreasChanged(d->allowedAreas);
 
382
}
 
383
 
 
384
Qt::ToolBarAreas QToolBar::allowedAreas() const
 
385
{ Q_D(const QToolBar); return d->allowedAreas; }
 
386
 
 
387
/*! \property QToolBar::orientation
 
388
    \brief orientation of the toolbar
 
389
 
 
390
    The default is \c Qt::Horizontal.
 
391
 
 
392
    The orientation is updated automatically when the toolbar is
 
393
    managed by QMainWindow.
 
394
*/
 
395
 
 
396
void QToolBar::setOrientation(Qt::Orientation orientation)
 
397
{
 
398
    Q_D(QToolBar);
 
399
    if (orientation == d->orientation)
 
400
        return;
 
401
 
 
402
    d->orientation = orientation;
 
403
 
 
404
    QBoxLayout *box = qobject_cast<QBoxLayout *>(layout());
 
405
    Q_ASSERT_X(box != 0, "QToolBar::setOrientation", "internal error");
 
406
 
 
407
    switch (d->orientation) {
 
408
    case Qt::Vertical:
 
409
        box->setDirection(QBoxLayout::TopToBottom);
 
410
        box->setAlignment(Qt::AlignTop);
 
411
        setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
 
412
        break;
 
413
 
 
414
    case Qt::Horizontal:
 
415
        box->setDirection(QBoxLayout::LeftToRight);
 
416
        box->setAlignment(Qt::AlignLeft);
 
417
        setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
 
418
        break;
 
419
    }
 
420
 
 
421
    emit orientationChanged(d->orientation);
 
422
}
 
423
 
 
424
Qt::Orientation QToolBar::orientation() const
 
425
{ Q_D(const QToolBar); return d->orientation; }
 
426
 
 
427
/*! \property QToolBar::iconSize
 
428
    \brief size of icons in the toolbar.
 
429
 
 
430
    The default is Qt::AutomaticIconSize.
 
431
*/
 
432
 
 
433
QSize QToolBar::iconSize() const
 
434
{ Q_D(const QToolBar); return d->iconSize; }
 
435
 
 
436
void QToolBar::setIconSize(const QSize &iconSize)
 
437
{
 
438
    Q_D(QToolBar);
 
439
    QSize sz = iconSize;
 
440
    if (!sz.isValid()) {
 
441
        QMainWindow *mw = qobject_cast<QMainWindow *>(parentWidget());
 
442
        if (mw && mw->layout()) {
 
443
            QLayout *layout = mw->layout();
 
444
            int i = 0;
 
445
            QLayoutItem *item = 0;
 
446
            do {
 
447
                item = layout->itemAt(i++);
 
448
                if (item->widget() == this)
 
449
                    sz = mw->iconSize();
 
450
            } while (!sz.isValid() && item != 0);
 
451
        }
 
452
    }
 
453
    if (!sz.isValid()) {
 
454
        const int metric = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
 
455
        sz = QSize(metric, metric);
 
456
    }
 
457
    if (d->iconSize != sz) {
 
458
        d->iconSize = sz;
 
459
        emit iconSizeChanged(d->iconSize);
 
460
    }
 
461
    d->explicitIconSize = iconSize.isValid();
 
462
}
 
463
 
 
464
/*! \property QToolBar::toolButtonStyle
 
465
    \brief style of toolbar buttons.
 
466
 
 
467
    The defaults is Qt::ToolButtonIconOnly.
 
468
*/
 
469
 
 
470
Qt::ToolButtonStyle QToolBar::toolButtonStyle() const
 
471
{ Q_D(const QToolBar); return d->toolButtonStyle; }
 
472
 
 
473
void QToolBar::setToolButtonStyle(Qt::ToolButtonStyle toolButtonStyle)
 
474
{
 
475
    Q_D(QToolBar);
 
476
    d->explicitToolButtonStyle = true;
 
477
    if (d->toolButtonStyle == toolButtonStyle)
 
478
        return;
 
479
    d->toolButtonStyle = toolButtonStyle;
 
480
    emit toolButtonStyleChanged(d->toolButtonStyle);
 
481
}
 
482
 
 
483
/*!
 
484
    Removes all actions from the toolbar.
 
485
 
 
486
    \sa removeAction()
 
487
*/
 
488
void QToolBar::clear()
 
489
{
 
490
    QList<QAction *> actions = this->actions();
 
491
    for(int i = 0; i < actions.size(); i++)
 
492
        removeAction(actions.at(i));
 
493
}
 
494
 
 
495
/*!
 
496
    \overload
 
497
 
 
498
    Creates a new action with the given \a text. This action is added to
 
499
    the end of the toolbar.
 
500
*/
 
501
QAction *QToolBar::addAction(const QString &text)
 
502
{
 
503
    QAction *action = new QAction(text, this);
 
504
    addAction(action);
 
505
    return action;
 
506
}
 
507
 
 
508
/*!
 
509
    \overload
 
510
 
 
511
    Creates a new action with the given \a icon and \a text. This
 
512
    action is added to the end of the toolbar.
 
513
*/
 
514
QAction *QToolBar::addAction(const QIcon &icon, const QString &text)
 
515
{
 
516
    QAction *action = new QAction(icon, text, this);
 
517
    addAction(action);
 
518
    return action;
 
519
}
 
520
 
 
521
/*!
 
522
    \overload
 
523
 
 
524
    Creates a new action with the given \a text. This action is added to
 
525
    the end of the toolbar. The action's \link QAction::triggered()
 
526
    triggered()\endlink signal is connected to \a member in \a
 
527
    receiver.
 
528
*/
 
529
QAction *QToolBar::addAction(const QString &text,
 
530
                             const QObject *receiver, const char* member)
 
531
{
 
532
    QAction *action = new QAction(text, this);
 
533
    QObject::connect(action, SIGNAL(triggered()), receiver, member);
 
534
    addAction(action);
 
535
    return action;
 
536
}
 
537
 
 
538
/*!
 
539
    \overload
 
540
 
 
541
    Creates a new action with the icon \a icon and text \a text. This
 
542
    action is added to the end of the toolbar. The action's \link
 
543
    QAction::triggered() triggered()\endlink signal is connected to \a
 
544
    member in \a receiver.
 
545
*/
 
546
QAction *QToolBar::addAction(const QIcon &icon, const QString &text,
 
547
                             const QObject *receiver, const char* member)
 
548
{
 
549
    QAction *action = new QAction(icon, text, this);
 
550
    QObject::connect(action, SIGNAL(triggered()), receiver, member);
 
551
    addAction(action);
 
552
    return action;
 
553
}
 
554
 
 
555
/*!
 
556
     Adds a separator to the end of the toolbar.
 
557
 
 
558
     \sa insertSeparator()
 
559
*/
 
560
QAction *QToolBar::addSeparator()
 
561
{
 
562
    QAction *action = new QAction(this);
 
563
    action->setSeparator(true);
 
564
    addAction(action);
 
565
    return action;
 
566
}
 
567
 
 
568
/*!
 
569
    Inserts a separator into the toolbar in front of the toolbar
 
570
    item associated with the \a before action.
 
571
 
 
572
    \sa addSeparator()
 
573
*/
 
574
QAction *QToolBar::insertSeparator(QAction *before)
 
575
{
 
576
    QAction *action = new QAction(this);
 
577
    action->setSeparator(true);
 
578
    insertAction(before, action);
 
579
    return action;
 
580
}
 
581
 
 
582
/*!
 
583
    Adds the given \a widget to the toolbar as the toolbar's last
 
584
    item.
 
585
 
 
586
    \sa insertWidget()
 
587
*/
 
588
QAction *QToolBar::addWidget(QWidget *widget)
 
589
{
 
590
    QToolBarWidgetAction *action = new QToolBarWidgetAction(widget, this);
 
591
    addAction(action);
 
592
    return action;
 
593
}
 
594
 
 
595
/*!
 
596
    Inserts the given \a widget in front of the toolbar item
 
597
    associated with the \a before action.
 
598
 
 
599
    \sa addWidget()
 
600
*/
 
601
QAction *QToolBar::insertWidget(QAction *before, QWidget *widget)
 
602
{
 
603
    QToolBarWidgetAction *action = new QToolBarWidgetAction(widget, this);
 
604
    insertAction(before, action);
 
605
    return action;
 
606
}
 
607
 
 
608
/*!
 
609
    \internal
 
610
 
 
611
    Returns the geometry of the toolbar item associated with the given
 
612
    \a action, or an invalid QRect if no matching item is found.
 
613
*/
 
614
QRect QToolBar::actionGeometry(QAction *action) const
 
615
{
 
616
    Q_D(const QToolBar);
 
617
    for (int i = 0; i < d->items.size(); ++i) {
 
618
        const QToolBarItem &item = d->items.at(i);
 
619
        if (item.action == action)
 
620
            return item.widget->geometry();
 
621
    }
 
622
    return QRect();
 
623
}
 
624
 
 
625
/*!
 
626
    Returns the action at point \a p. This function returns zero if no
 
627
    action was found.
 
628
 
 
629
    \sa QWidget::childAt()
 
630
*/
 
631
QAction *QToolBar::actionAt(const QPoint &p) const
 
632
{
 
633
    Q_D(const QToolBar);
 
634
    QWidget *widget = childAt(p);
 
635
    for (int i = 0; i < d->items.size(); ++i) {
 
636
        const QToolBarItem &item = d->items.at(i);
 
637
        if (item.widget == widget)
 
638
            return item.action;
 
639
    }
 
640
    return 0;
 
641
}
 
642
 
 
643
/*! \fn QAction *QToolBar::actionAt(int x, int y) const
 
644
    \overload
 
645
 
 
646
    Returns the action at the point \a x, \a y. This function returns
 
647
    zero if no action was found.
 
648
*/
 
649
 
 
650
/*! \reimp */
 
651
void QToolBar::actionEvent(QActionEvent *event)
 
652
{
 
653
    Q_D(QToolBar);
 
654
    QAction *action = event->action();
 
655
    QToolBarWidgetAction *widgetAction = qobject_cast<QToolBarWidgetAction *>(action);
 
656
 
 
657
    switch (event->type()) {
 
658
    case QEvent::ActionAdded:
 
659
        {
 
660
            if (d->ignoreActionAddedEvent)
 
661
                break;
 
662
 
 
663
            Q_ASSERT_X(!widgetAction || d->indexOf(widgetAction) == -1,
 
664
                       "QToolBar", "widgets cannot be inserted multiple times");
 
665
 
 
666
            QToolBarItem item = d->createItem(action);
 
667
            if (event->before()) {
 
668
                int index = d->indexOf(event->before());
 
669
                Q_ASSERT_X(index >= 0 && index < d->items.size(), "QToolBar::insertAction",
 
670
                           "internal error");
 
671
                d->items.insert(index, item);
 
672
                qobject_cast<QBoxLayout *>(layout())->insertWidget(index + 1, item.widget);
 
673
            } else {
 
674
                d->items.append(item);
 
675
                qobject_cast<QBoxLayout *>(layout())->insertWidget(d->items.size(), item.widget);
 
676
            }
 
677
            item.widget->setVisible(item.action->isVisible());
 
678
            break;
 
679
        }
 
680
 
 
681
    case QEvent::ActionChanged:
 
682
        {
 
683
            int index = d->indexOf(action);
 
684
            Q_ASSERT_X(index >= 0 && index < d->items.size(),
 
685
                       "QToolBar::actionEvent", "internal error");
 
686
            const QToolBarItem &item = d->items.at(index);
 
687
            if (!item.hidden)
 
688
                item.widget->setVisible(item.action->isVisible());
 
689
 
 
690
            break;
 
691
        }
 
692
 
 
693
    case QEvent::ActionRemoved:
 
694
        {
 
695
            int index = d->indexOf(action);
 
696
            Q_ASSERT_X(index >= 0 && index < d->items.size(),
 
697
                       "QToolBar::removeAction", "internal error");
 
698
            QToolBarItem item = d->items.takeAt(index);
 
699
            layout()->removeWidget(item.widget);
 
700
            if (!widgetAction) {
 
701
                // destroy the QToolButton/QToolBarSeparator
 
702
                delete item.widget;
 
703
            } else {
 
704
                if (!isHidden())
 
705
                    item.widget->hide();
 
706
            }
 
707
            break;
 
708
        }
 
709
 
 
710
    default:
 
711
        Q_ASSERT_X(false, "QToolBar::actionEvent", "internal error");
 
712
    }
 
713
}
 
714
 
 
715
/*! \reimp */
 
716
void QToolBar::changeEvent(QEvent *event)
 
717
{
 
718
    Q_D(QToolBar);
 
719
    switch (event->type()) {
 
720
    case QEvent::WindowTitleChange:
 
721
        d->toggleViewAction->setText(windowTitle());
 
722
        break;
 
723
    case QEvent::StyleChange:
 
724
        {
 
725
            QStyleOptionFrame opt = getStyleOption(this);
 
726
            d->layout->setMargin(style()->pixelMetric(QStyle::PM_ToolBarFrameWidth, &opt, this)
 
727
                                 + style()->pixelMetric(QStyle::PM_ToolBarItemMargin, &opt, this));
 
728
            d->layout->setSpacing(style()->pixelMetric(QStyle::PM_ToolBarItemSpacing, &opt, this));
 
729
            break;
 
730
        }
 
731
    default:
 
732
        break;
 
733
    }
 
734
    QWidget::changeEvent(event);
 
735
}
 
736
 
 
737
/*! \reimp */
 
738
void QToolBar::childEvent(QChildEvent *event)
 
739
{
 
740
    Q_D(QToolBar);
 
741
    QWidget *widget = qobject_cast<QWidget *>(event->child());
 
742
    if (widget) {
 
743
#if !defined(QT_NO_DEBUG)
 
744
        if (!widget->isWindow() && event->type() == QEvent::ChildPolished) {
 
745
            bool found = (d->handle == widget || d->extension == widget);
 
746
            for (int i = 0; !found && i < d->items.size(); ++i) {
 
747
                const QToolBarItem &item = d->items.at(i);
 
748
                if (item.widget == widget)
 
749
                    found = true;
 
750
            }
 
751
            if (!found)
 
752
                qWarning("QToolBar: child widget '%s::%s' not added, use QToolBar::addWidget()",
 
753
                         widget->objectName().toLocal8Bit().constData(), widget->metaObject()->className());
 
754
        } else
 
755
#endif
 
756
        if (event->type() == QEvent::ChildRemoved) {
 
757
            for (int i = 0; i < d->items.size(); ++i) {
 
758
                const QToolBarItem &item = d->items.at(i);
 
759
                QToolBarWidgetAction *widgetAction = 0;
 
760
                if (item.widget == widget
 
761
                    && (widgetAction = qobject_cast<QToolBarWidgetAction *>(item.action))) {
 
762
                    removeAction(widgetAction);
 
763
                    // ### should we delete the action, or is it the programmers reponsibility?
 
764
                    // delete widgetAction;
 
765
                }
 
766
            }
 
767
        }
 
768
    }
 
769
    QWidget::childEvent(event);
 
770
}
 
771
 
 
772
/*! \reimp */
 
773
void QToolBar::paintEvent(QPaintEvent *event)
 
774
{
 
775
    Q_UNUSED(event);
 
776
    QPainter p(this);
 
777
    QStyleOptionFrame opt = getStyleOption(this);
 
778
    style()->drawPrimitive(QStyle::PE_PanelToolBar, &opt, &p, this);
 
779
}
 
780
 
 
781
/*! \reimp */
 
782
void QToolBar::resizeEvent(QResizeEvent *event)
 
783
{
 
784
    Q_D(QToolBar);
 
785
    QBoxLayout *box = qobject_cast<QBoxLayout *>(layout());
 
786
    Qt::Orientation orientation = (box->direction() == QBoxLayout::LeftToRight
 
787
                                   || box->direction() == QBoxLayout::RightToLeft)
 
788
                                  ? Qt::Horizontal
 
789
                                  : Qt::Vertical;
 
790
    const int margin = box->margin();
 
791
    int i = 0;
 
792
    int extension_size = 0;
 
793
    int hidden_count = 0;
 
794
    int max_item_extent = 0;
 
795
    i = d->items.size(); // note: the toolbar handle is not counted
 
796
    while (i > 0) {
 
797
        QWidget *w = box->itemAt(i)->widget();
 
798
        bool hide = false;
 
799
        if (QApplication::layoutDirection() == Qt::RightToLeft && orientation == Qt::Horizontal) {
 
800
            if (w->isHidden()) {
 
801
                if (box->itemAt(i-1) && !box->itemAt(i-1)->widget()->isHidden()) {
 
802
                    QWidget *pw = box->itemAt(i-1)->widget();
 
803
                    hide = pw->pos().x() < (extension_size + w->size().width() + margin + box->spacing());
 
804
                } else {
 
805
                    // calculate the pos of the hidden item
 
806
                    int pos = 0;
 
807
                    for (int k = 1; k < i; ++k) { // idx 0 == handle
 
808
                        QWidget * pw = box->itemAt(k)->widget();
 
809
                        if (pw == w)
 
810
                            break;
 
811
                        pos = pw->isHidden()
 
812
                              ? pos - pw->size().width() - box->spacing()
 
813
                              : pw->pos().x();
 
814
                    }
 
815
                    pos = pos - w->size().width() - box->spacing();
 
816
                    hide = pos < extension_size + margin;
 
817
                }
 
818
            } else {
 
819
                hide = w->pos().x() < extension_size + margin;
 
820
            }
 
821
        } else {
 
822
            hide = pick(orientation, w->pos()) + pick(orientation, w->size())
 
823
                   >= pick(orientation, size()) - extension_size;
 
824
        }
 
825
        if (hide && i > 1) { // never hide the first item in the tb
 
826
            w->hide();
 
827
            d->items[i - 1].hidden = true;
 
828
            ++hidden_count;
 
829
            // the size of the extension menu button needs to be
 
830
            // considered when buttons in the toolbar are hidden
 
831
            extension_size = pick(orientation, d->extension->sizeHint());
 
832
        } else {
 
833
            w->setVisible(d->items[i - 1].action->isVisible());
 
834
            d->items[i - 1].hidden = false;
 
835
            if (orientation == Qt::Horizontal)
 
836
                max_item_extent = qMax(max_item_extent, w->sizeHint().height());
 
837
            else
 
838
                max_item_extent = qMax(max_item_extent, w->sizeHint().width());
 
839
        }
 
840
        --i;
 
841
    }
 
842
 
 
843
    if (orientation == Qt::Horizontal) {
 
844
        setMinimumSize(d->handle->sizeHint().width() + box->spacing()*2 + extension_size + margin*2
 
845
                       + (d->items.isEmpty()
 
846
                          ? d->iconSize.width()
 
847
                          : d->items[0].widget->sizeHint().width()),
 
848
                       max_item_extent + margin*2);
 
849
    } else {
 
850
        setMinimumSize(max_item_extent + margin*2,
 
851
                       d->handle->sizeHint().height() + box->spacing()*2 + extension_size
 
852
                       + margin*2 + (d->items.isEmpty()
 
853
                                     ? d->iconSize.height()
 
854
                                     : d->items[0].widget->sizeHint().height()));
 
855
    }
 
856
 
 
857
    if (hidden_count > 0) {
 
858
        if (orientation == Qt::Horizontal) {
 
859
            int x = QApplication::layoutDirection() == Qt::RightToLeft
 
860
                    ? margin
 
861
                    : width() - d->extension->sizeHint().width() - margin;
 
862
            d->extension->setGeometry(x, margin, d->extension->sizeHint().width(), max_item_extent);
 
863
        } else {
 
864
            d->extension->setGeometry(margin,
 
865
                                      height() - d->extension->sizeHint().height() - margin,
 
866
                                      max_item_extent,
 
867
                                      d->extension->sizeHint().height());
 
868
        }
 
869
 
 
870
        QMenu *pop = d->extension->menu();
 
871
        if (!pop) {
 
872
            pop = new QMenu(this);
 
873
            d->extension->setMenu(pop);
 
874
        }
 
875
        pop->clear();
 
876
        for(int i = 0; i < d->items.size(); ++i) {
 
877
            const QToolBarItem &item = d->items.at(i);
 
878
            if (!item.hidden) continue;
 
879
 
 
880
            if (!qobject_cast<QToolBarWidgetAction *>(item.action)) {
 
881
                pop->addAction(item.action);
 
882
            } else {
 
883
                // ### needs special handling of custom widgets and
 
884
                // ### e.g. combo boxes - only actions are supported in
 
885
                // ### the preview
 
886
            }
 
887
        }
 
888
        if (pop->actions().size() > 0) {
 
889
            d->extension->show();
 
890
            d->extension->setEnabled(true);
 
891
        } else {
 
892
            // show a disabled ext btn in the case where widgets in
 
893
            // the toolbar are hidden but not put into the ext menu -
 
894
            // this indicates that some items in the tb is hidden
 
895
            d->extension->show();
 
896
            d->extension->setEnabled(false);
 
897
        }
 
898
    } else if (!d->extension->isHidden()) {
 
899
        if (d->extension->menu())
 
900
            d->extension->menu()->clear();
 
901
        d->extension->hide();
 
902
    }
 
903
    QWidget::resizeEvent(event);
 
904
}
 
905
 
 
906
/*! \reimp */
 
907
bool QToolBar::event(QEvent *event)
 
908
{
 
909
    Q_D(QToolBar);
 
910
    switch (event->type()) {
 
911
    case QEvent::Hide:
 
912
        if (!isHidden())
 
913
            break;
 
914
        // fallthrough intended
 
915
    case QEvent::Show:
 
916
        d->toggleViewAction->setChecked(event->type() == QEvent::Show);
 
917
        break;
 
918
    case QEvent::ParentChange:
 
919
        d->handle->setVisible(d->movable && (qobject_cast<QMainWindow *>(parentWidget()) != 0));
 
920
        break;
 
921
    case QEvent::StyleChange:
 
922
        if (!d->explicitIconSize)
 
923
            setIconSize(QSize());
 
924
        break;
 
925
    default:
 
926
        break;
 
927
    }
 
928
    return QWidget::event(event);
 
929
}
 
930
 
 
931
/*!
 
932
    Returns a checkable action that can be used to show or hide this
 
933
    toolbar.
 
934
 
 
935
    The action's text is set to the toolbar's window title.
 
936
 
 
937
    \sa QAction::text QWidget::windowTitle
 
938
*/
 
939
QAction *QToolBar::toggleViewAction() const
 
940
{ Q_D(const QToolBar); return d->toggleViewAction; }
 
941
 
 
942
/*!
 
943
    \fn void QToolBar::setLabel(const QString &label)
 
944
 
 
945
    Use setWindowTitle() instead.
 
946
*/
 
947
 
 
948
/*!
 
949
    \fn QString QToolBar::label() const
 
950
 
 
951
    Use windowTitle() instead.
 
952
*/
 
953
 
 
954
 
 
955
#include "moc_qtoolbar.cpp"