src/gui/widgets/qtoolbar.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtGui module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "qtoolbar.h"
00025 
00026 #ifndef QT_NO_TOOLBAR
00027 
00028 #include <qapplication.h>
00029 #include <qcombobox.h>
00030 #include <qevent.h>
00031 #include <qlayout.h>
00032 #include <qmainwindow.h>
00033 #include <qmenu.h>
00034 #include <qmenubar.h>
00035 #include <qpainter.h>
00036 #include <qrubberband.h>
00037 #include <qsignalmapper.h>
00038 #include <qstyle.h>
00039 #include <qstyleoption.h>
00040 #include <qtoolbutton.h>
00041 #include <qwidgetaction.h>
00042 #include <private/qwidgetaction_p.h>
00043 #ifdef Q_WS_MAC
00044 #include <private/qt_mac_p.h>
00045 #endif
00046 
00047 #include <private/qmainwindowlayout_p.h>
00048 
00049 #include "qtoolbar_p.h"
00050 #include "qtoolbarextension_p.h"
00051 #include "qtoolbarhandle_p.h"
00052 #include "qtoolbarseparator_p.h"
00053 
00054 #include  "qdebug.h"
00055 static int positionForArea(Qt::ToolBarArea area)
00056 {
00057     switch (area) {
00058     case Qt::LeftToolBarArea: return 0;
00059     case Qt::RightToolBarArea: return 1;
00060     case Qt::TopToolBarArea: return 2;
00061     case Qt::BottomToolBarArea: return 3;
00062     default: return -1;
00063     }
00064 }
00065 
00066 static QStyleOptionToolBar getStyleOption(QToolBar *toolBar)
00067 {
00068     QStyleOptionToolBar option;
00069     option.init(toolBar);
00070     if (toolBar->orientation() == Qt::Horizontal)
00071         option.state |= QStyle::State_Horizontal;
00072     option.lineWidth = toolBar->style()->pixelMetric(QStyle::PM_ToolBarFrameWidth);
00073     option.features = toolBar->isMovable() ? QStyleOptionToolBar::Movable : QStyleOptionToolBar::None;
00074 
00075     // Add more styleoptions if the toolbar has been added to a mainwindow.
00076     QMainWindow *mainWindow = qobject_cast<QMainWindow *>(toolBar->parent());
00077 
00078     if (!mainWindow)
00079         return option;
00080 
00081     QMainWindowLayout *layout = qobject_cast<QMainWindowLayout *>(mainWindow->layout());
00082     Q_ASSERT_X(layout != 0, "QToolBarPrivate::getStyleOption()",
00083                "QMainWindow->layout() != QMainWindowLayout");
00084 
00085     // Determine the toolbar area.
00086     int layoutIndex = layout->indexOf(toolBar);
00087     if (layoutIndex != -1)
00088         option.toolBarArea = layout->toolBarArea(toolBar);
00089 
00090     // Find the toolbar line, and position within the line.
00091     int toolBarTotalLineCount = 0;
00092     int toolBarLineCount = 0;
00093 
00094 
00095   foreach (QMainWindowLayout::ToolBarLineInfo lineInfo, layout->tb_layout_info) {
00096 
00097         if (lineInfo.pos != positionForArea(option.toolBarArea))
00098             continue;
00099         int toolBarIndex = -1;
00100         bool lineVisible = false;
00101 
00102         for (int i = 0; i < lineInfo.list.size(); ++i){
00103             QMainWindowLayout::ToolBarLayoutInfo layoutInfo = lineInfo.list.at(i);
00104 
00105             if (layoutInfo.item->widget()->isVisible())
00106                 lineVisible = true;
00107 
00108             if (layoutInfo.item->widget() == toolBar) {
00109                 // This is our toolbar, so we now have the line and position.
00110                 toolBarLineCount = toolBarTotalLineCount;
00111 
00112                 // We have to determine how many visible toolbars there are in this line
00113                 int visibleLines = 0;
00114                 for (int j = 0; j < lineInfo.list.size(); ++j){
00115                     QMainWindowLayout::ToolBarLayoutInfo info = lineInfo.list.at(j);
00116                     if (info.item->widget() == toolBar)
00117                         toolBarIndex = visibleLines;
00118                     if (info.item->widget()->isVisible())
00119                         visibleLines++;
00120                 }
00121 
00122                 // Determine the position within this toolbar line
00123                 if (toolBarIndex == 0) {
00124                     if (visibleLines == 1)
00125                         option.positionWithinLine = QStyleOptionToolBar::OnlyOne;
00126                     else
00127                         option.positionWithinLine = QStyleOptionToolBar::Beginning;
00128                 } else if (toolBarIndex < visibleLines - 1) {
00129                     option.positionWithinLine = QStyleOptionToolBar::Middle;
00130                 } else if (toolBarIndex == visibleLines - 1) {
00131                     option.positionWithinLine = QStyleOptionToolBar::End;
00132                 }
00133                 break;
00134             }
00135         }
00136     if(lineVisible)
00137             ++toolBarTotalLineCount;
00138   }
00139 
00140   Q_ASSERT_X(toolBarLineCount >= 0, "QToolBarPrivate::getStyleOption()",
00141          "toolbar not found in layout");
00142 
00143 
00144 
00145     if (option.toolBarArea== Qt::BottomToolBarArea || option.toolBarArea==Qt::RightToolBarArea){
00146         toolBarLineCount = toolBarTotalLineCount-toolBarLineCount-1;
00147     }
00148 
00149   // Determine the line position of this toolbar
00150   if (toolBarLineCount == 0) {
00151     if (toolBarTotalLineCount == 1)
00152             option.positionOfLine = QStyleOptionToolBar::OnlyOne;
00153     else
00154       option.positionOfLine = QStyleOptionToolBar::Beginning;
00155   } else if (toolBarLineCount < toolBarTotalLineCount - 1) {
00156     option.positionOfLine = QStyleOptionToolBar::Middle;
00157   } else if (toolBarLineCount == toolBarTotalLineCount - 1) {
00158     option.positionOfLine = QStyleOptionToolBar::End;
00159   }
00160 
00161     return option;
00162 }
00163 
00164 
00165 /*
00166 static QStyleOptionFrame getStyleOption(QToolBar *tb)
00167 {
00168     QStyleOptionFrame opt;
00169     opt.init(tb);
00170     if (tb->orientation() == Qt::Horizontal)
00171         opt.state |= QStyle::State_Horizontal;
00172     opt.lineWidth = tb->style()->pixelMetric(QStyle::PM_ToolBarFrameWidth);
00173     return opt;
00174 }
00175 */
00176 
00177 /*
00178     QToolBarPrivate
00179 */
00180 
00181 void QToolBarPrivate::init()
00182 {
00183     Q_Q(QToolBar);
00184     movable = true;
00185     q->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
00186     q->setBackgroundRole(QPalette::Button);
00187 
00188 
00189     QStyleOptionToolBar opt = getStyleOption(q);
00190 
00191     QBoxLayout *layout = new QBoxLayout(QBoxLayout::LeftToRight, q);
00192     QStyle *style = q->style();
00193 
00194     int e = style->pixelMetric(QStyle::PM_ToolBarIconSize);
00195     iconSize = QSize(e, e);
00196 
00197     layout->setAlignment(Qt::AlignLeft);
00198     layout->setMargin(style->pixelMetric(QStyle::PM_ToolBarFrameWidth, &opt, q)
00199                       + style->pixelMetric(QStyle::PM_ToolBarItemMargin, &opt, q));
00200     layout->setSpacing(style->pixelMetric(QStyle::PM_ToolBarItemSpacing, &opt, q));
00201 
00202     handle = new QToolBarHandle(q);
00203     QObject::connect(q, SIGNAL(orientationChanged(Qt::Orientation)),
00204                      handle, SLOT(setOrientation(Qt::Orientation)));
00205     layout->addWidget(handle);
00206     handle->setVisible(movable && (qobject_cast<QMainWindow *>(q->parentWidget()) != 0));
00207 
00208     extension = new QToolBarExtension(q);
00209     QObject::connect(q, SIGNAL(orientationChanged(Qt::Orientation)),
00210                      extension, SLOT(setOrientation(Qt::Orientation)));
00211     extension->setFocusPolicy(Qt::NoFocus);
00212     extension->hide();
00213 
00214 #ifdef Q_WS_MAC
00215     if (q->parentWidget() && q->parentWidget()->isWindow()) {
00216         // Make sure that the window has the "toolbar" button.
00217         reinterpret_cast<QToolBar *>(q->parentWidget())->d_func()->createWinId(); // Please let me create your winId...
00218         extern WindowPtr qt_mac_window_for(const QWidget *); // qwidget_mac.cpp
00219         ChangeWindowAttributes(qt_mac_window_for(q->parentWidget()), kWindowToolbarButtonAttribute,
00220                                kWindowNoAttributes);
00221     }
00222 #endif
00223 
00224     toggleViewAction = new QAction(q);
00225     toggleViewAction->setCheckable(true);
00226     QObject::connect(toggleViewAction, SIGNAL(triggered(bool)), q, SLOT(_q_toggleView(bool)));
00227 }
00228 
00229 void QToolBarPrivate::_q_toggleView(bool b)
00230 {
00231     Q_Q(QToolBar);
00232     if (b == q->isHidden()) {
00233         if (b)
00234             q->show();
00235         else
00236             q->close();
00237     }
00238 }
00239 
00240 void QToolBarPrivate::_q_updateIconSize(const QSize &sz)
00241 {
00242     Q_Q(QToolBar);
00243     if (!explicitIconSize) {
00244         // iconSize not explicitly set
00245         q->setIconSize(sz);
00246         explicitIconSize = false;
00247     }
00248 }
00249 
00250 void QToolBarPrivate::_q_updateToolButtonStyle(Qt::ToolButtonStyle style)
00251 {
00252     Q_Q(QToolBar);
00253     if (!explicitToolButtonStyle) {
00254         q->setToolButtonStyle(style);
00255         explicitToolButtonStyle = false;
00256     }
00257 }
00258 
00259 QToolBarItem QToolBarPrivate::createItem(QAction *action)
00260 {
00261     Q_Q(QToolBar);
00262     QToolBarItem item;
00263     item.action = action;
00264     item.hidden = false;
00265     item.hasCustomWidget = false;
00266 
00267     QWidgetAction *widgetAction = qobject_cast<QWidgetAction *>(action);
00268     if (widgetAction) {
00269         item.widget = widgetAction->requestWidget(q);
00270         if (item.widget) {
00271             item.hasCustomWidget = true;
00272             return item;
00273         }
00274     }
00275     if (action->isSeparator()) {
00276         item.widget = new QToolBarSeparator(q);
00277         QObject::connect(q, SIGNAL(orientationChanged(Qt::Orientation)),
00278                          item.widget, SLOT(setOrientation(Qt::Orientation)));
00279     } else {
00280         QToolButton *button = new QToolButton(q);
00281         button->setAutoRaise(true);
00282         button->setFocusPolicy(Qt::NoFocus);
00283         button->setIconSize(iconSize);
00284         button->setToolButtonStyle(toolButtonStyle);
00285         QObject::connect(q, SIGNAL(iconSizeChanged(QSize)),
00286                          button, SLOT(setIconSize(QSize)));
00287         QObject::connect(q, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
00288                          button, SLOT(setToolButtonStyle(Qt::ToolButtonStyle)));
00289         button->setDefaultAction(action);
00290         QObject::connect(button, SIGNAL(triggered(QAction*)), q, SIGNAL(actionTriggered(QAction*)));
00291         item.widget = button;
00292     }
00293 
00294     return item;
00295 }
00296 
00297 /*
00298     Returns the position of \a action. This function returns -1 if \a
00299     action is not found.
00300 */
00301 int QToolBarPrivate::indexOf(QAction *action) const
00302 {
00303     for (int i = 0; i < items.size(); ++i) {
00304         const QToolBarItem &item = items.at(i);
00305         if (item.action == action)
00306             return i;
00307     }
00308     return -1;
00309 }
00310 
00410 QToolBar::QToolBar(QWidget *parent)
00411     : QWidget(*new QToolBarPrivate, parent, 0)
00412 {
00413     Q_D(QToolBar);
00414     d->init();
00415 }
00416 
00425 QToolBar::QToolBar(const QString &title, QWidget *parent)
00426     : QWidget(*new QToolBarPrivate, parent, 0)
00427 {
00428     Q_D(QToolBar);
00429     d->init();
00430     setWindowTitle(title);
00431 }
00432 
00433 #ifdef QT3_SUPPORT
00434 
00437 QToolBar::QToolBar(QWidget *parent, const char *name)
00438     : QWidget(*new QToolBarPrivate, parent, 0)
00439 {
00440     Q_D(QToolBar);
00441     d->init();
00442     setObjectName(QString::fromAscii(name));
00443 }
00444 #endif
00445 
00449 QToolBar::~QToolBar()
00450 {
00451     // Remove the toolbar button if there is nothing left.
00452     QMainWindow *mainwindow = qobject_cast<QMainWindow *>(parentWidget());
00453     if (mainwindow) {
00454         QMainWindowLayout *mainwin_layout = qobject_cast<QMainWindowLayout *>(mainwindow->layout());
00455         mainwin_layout->removeToolBarInfo(this);
00456         mainwin_layout->relayout();
00457 #ifdef Q_WS_MAC
00458         if (mainwin_layout && mainwin_layout->tb_layout_info.isEmpty()
00459                 && mainwindow->testAttribute(Qt::WA_WState_Created))
00460             ChangeWindowAttributes(qt_mac_window_for(mainwindow), kWindowNoAttributes,
00461                                    kWindowToolbarButtonAttribute);
00462 #endif
00463     }
00464     Q_D(QToolBar);
00465     while (!d->items.isEmpty()) {
00466         const QToolBarItem item = d->items.takeFirst();
00467         QWidgetAction *widgetAction = qobject_cast<QWidgetAction *>(item.action);
00468         if (item.hasCustomWidget && widgetAction) {
00469             widgetAction->releaseWidget(item.widget);
00470         }
00471     }
00472 }
00473 
00486 void QToolBar::setMovable(bool movable)
00487 {
00488     Q_D(QToolBar);
00489     if (!movable == !d->movable)
00490         return;
00491     d->movable = movable;
00492     d->handle->setVisible(d->movable && (qobject_cast<QMainWindow *>(parentWidget()) != 0));
00493     emit movableChanged(d->movable);
00494 }
00495 
00496 bool QToolBar::isMovable() const
00497 { Q_D(const QToolBar); return d->movable; }
00498 
00511 void QToolBar::setAllowedAreas(Qt::ToolBarAreas areas)
00512 {
00513     Q_D(QToolBar);
00514     areas &= Qt::ToolBarArea_Mask;
00515     if (areas == d->allowedAreas)
00516         return;
00517     d->allowedAreas = areas;
00518     emit allowedAreasChanged(d->allowedAreas);
00519 }
00520 
00521 Qt::ToolBarAreas QToolBar::allowedAreas() const
00522 { Q_D(const QToolBar); return d->allowedAreas; }
00523 
00533 void QToolBar::setOrientation(Qt::Orientation orientation)
00534 {
00535     Q_D(QToolBar);
00536     if (orientation == d->orientation)
00537         return;
00538 
00539     d->orientation = orientation;
00540 
00541     QBoxLayout *box = qobject_cast<QBoxLayout *>(layout());
00542     Q_ASSERT_X(box != 0, "QToolBar::setOrientation", "internal error");
00543 
00544     switch (d->orientation) {
00545     case Qt::Vertical:
00546   box->setDirection(QBoxLayout::TopToBottom);
00547         box->setAlignment(Qt::AlignTop);
00548   setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
00549   break;
00550 
00551     case Qt::Horizontal:
00552   box->setDirection(QBoxLayout::LeftToRight);
00553         box->setAlignment(Qt::AlignLeft);
00554   setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
00555   break;
00556     }
00557 
00558     emit orientationChanged(d->orientation);
00559 }
00560 
00561 Qt::Orientation QToolBar::orientation() const
00562 { Q_D(const QToolBar); return d->orientation; }
00563 
00570 QSize QToolBar::iconSize() const
00571 { Q_D(const QToolBar); return d->iconSize; }
00572 
00573 void QToolBar::setIconSize(const QSize &iconSize)
00574 {
00575     Q_D(QToolBar);
00576     QSize sz = iconSize;
00577     if (!sz.isValid()) {
00578         QMainWindow *mw = qobject_cast<QMainWindow *>(parentWidget());
00579         if (mw && mw->layout()) {
00580             QLayout *layout = mw->layout();
00581             int i = 0;
00582             QLayoutItem *item = 0;
00583             do {
00584                 item = layout->itemAt(i++);
00585                 if (item && (item->widget() == this))
00586                     sz = mw->iconSize();
00587             } while (!sz.isValid() && item != 0);
00588         }
00589     }
00590     if (!sz.isValid()) {
00591         const int metric = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
00592         sz = QSize(metric, metric);
00593     }
00594     if (d->iconSize != sz) {
00595         d->iconSize = sz;
00596         setMinimumSize(0, 0);
00597         emit iconSizeChanged(d->iconSize);
00598     }
00599     d->explicitIconSize = iconSize.isValid();
00600 }
00601 
00609 Qt::ToolButtonStyle QToolBar::toolButtonStyle() const
00610 { Q_D(const QToolBar); return d->toolButtonStyle; }
00611 
00612 void QToolBar::setToolButtonStyle(Qt::ToolButtonStyle toolButtonStyle)
00613 {
00614     Q_D(QToolBar);
00615     d->explicitToolButtonStyle = true;
00616     if (d->toolButtonStyle == toolButtonStyle)
00617         return;
00618     d->toolButtonStyle = toolButtonStyle;
00619     setMinimumSize(0, 0);
00620     emit toolButtonStyleChanged(d->toolButtonStyle);
00621 }
00622 
00628 void QToolBar::clear()
00629 {
00630     QList<QAction *> actions = this->actions();
00631     for(int i = 0; i < actions.size(); i++)
00632         removeAction(actions.at(i));
00633 }
00634 
00641 QAction *QToolBar::addAction(const QString &text)
00642 {
00643     QAction *action = new QAction(text, this);
00644     addAction(action);
00645     return action;
00646 }
00647 
00654 QAction *QToolBar::addAction(const QIcon &icon, const QString &text)
00655 {
00656     QAction *action = new QAction(icon, text, this);
00657     addAction(action);
00658     return action;
00659 }
00660 
00669 QAction *QToolBar::addAction(const QString &text,
00670                              const QObject *receiver, const char* member)
00671 {
00672     QAction *action = new QAction(text, this);
00673     QObject::connect(action, SIGNAL(triggered()), receiver, member);
00674     addAction(action);
00675     return action;
00676 }
00677 
00686 QAction *QToolBar::addAction(const QIcon &icon, const QString &text,
00687                              const QObject *receiver, const char* member)
00688 {
00689     QAction *action = new QAction(icon, text, this);
00690     QObject::connect(action, SIGNAL(triggered()), receiver, member);
00691     addAction(action);
00692     return action;
00693 }
00694 
00700 QAction *QToolBar::addSeparator()
00701 {
00702     QAction *action = new QAction(this);
00703     action->setSeparator(true);
00704     addAction(action);
00705     return action;
00706 }
00707 
00714 QAction *QToolBar::insertSeparator(QAction *before)
00715 {
00716     QAction *action = new QAction(this);
00717     action->setSeparator(true);
00718     insertAction(before, action);
00719     return action;
00720 }
00721 
00732 QAction *QToolBar::addWidget(QWidget *widget)
00733 {
00734     QWidgetAction *action = new QWidgetAction(this);
00735     action->setDefaultWidget(widget);
00736     action->d_func()->autoCreated = true;
00737     addAction(action);
00738     return action;
00739 }
00740 
00751 QAction *QToolBar::insertWidget(QAction *before, QWidget *widget)
00752 {
00753     QWidgetAction *action = new QWidgetAction(this);
00754     action->setDefaultWidget(widget);
00755     action->d_func()->autoCreated = true;
00756     insertAction(before, action);
00757     return action;
00758 }
00759 
00766 QRect QToolBar::actionGeometry(QAction *action) const
00767 {
00768     Q_D(const QToolBar);
00769     for (int i = 0; i < d->items.size(); ++i) {
00770         const QToolBarItem &item = d->items.at(i);
00771         if (item.action == action)
00772             return item.widget->geometry();
00773     }
00774     return QRect();
00775 }
00776 
00783 QAction *QToolBar::actionAt(const QPoint &p) const
00784 {
00785     Q_D(const QToolBar);
00786     QWidget *widget = childAt(p);
00787     for (int i = 0; i < d->items.size(); ++i) {
00788         const QToolBarItem &item = d->items.at(i);
00789         if (item.widget == widget)
00790             return item.action;
00791     }
00792     return 0;
00793 }
00794 
00803 void QToolBar::actionEvent(QActionEvent *event)
00804 {
00805     Q_D(QToolBar);
00806     QAction *action = event->action();
00807     QWidgetAction *widgetAction = qobject_cast<QWidgetAction *>(action);
00808 
00809     switch (event->type()) {
00810     case QEvent::ActionAdded:
00811         {
00812             Q_ASSERT_X(!widgetAction || d->indexOf(widgetAction) == -1,
00813                        "QToolBar", "widgets cannot be inserted multiple times");
00814 
00815             QToolBarItem item = d->createItem(action);
00816             bool visible = item.action->isVisible();
00817             // reparent the action to this toolbar if it has been created
00818             // using the addAction(text) etc. convenience functions, to
00819             // preserve Qt 4.1.x behavior. The widget is already
00820             // reparented to us due to the createWidget call inside
00821             // createItem()
00822             if (widgetAction && widgetAction->d_func()->autoCreated)
00823                     widgetAction->setParent(this);
00824             // make sure the layout doesn't show() the widget too soon
00825             item.widget->hide();
00826             if (event->before()) {
00827                 int index = d->indexOf(event->before());
00828                 Q_ASSERT_X(index >= 0 && index < d->items.size(), "QToolBar::insertAction",
00829                            "internal error");
00830                 d->items.insert(index, item);
00831                 qobject_cast<QBoxLayout *>(layout())->insertWidget(index + 1, item.widget);
00832             } else {
00833                 d->items.append(item);
00834                 qobject_cast<QBoxLayout *>(layout())->insertWidget(d->items.size(), item.widget);
00835             }
00836             item.widget->setVisible(visible);
00837             if (isVisible())
00838                 QApplication::postEvent(this, new QResizeEvent(size(), size()));
00839             break;
00840         }
00841 
00842     case QEvent::ActionChanged:
00843         {
00844             int index = d->indexOf(action);
00845             Q_ASSERT_X(index >= 0 && index < d->items.size(),
00846                        "QToolBar::actionEvent", "internal error");
00847             const QToolBarItem &item = d->items.at(index);
00848             if (!item.hidden) {
00849                 item.widget->setVisible(item.action->isVisible());
00850             } else {
00851                 // more elephant shaving
00852                 if (isVisible())
00853                     QApplication::postEvent(this, new QResizeEvent(size(), size()));
00854             }
00855 
00856             break;
00857         }
00858 
00859     case QEvent::ActionRemoved:
00860         {
00861             int index = d->indexOf(action);
00862             Q_ASSERT_X(index >= 0 && index < d->items.size(),
00863                        "QToolBar::removeAction", "internal error");
00864             QToolBarItem item = d->items.takeAt(index);
00865             layout()->removeWidget(item.widget);
00866             if (widgetAction && item.hasCustomWidget) {
00867                 widgetAction->releaseWidget(item.widget);
00868             } else {
00869                 // destroy the QToolButton/QToolBarSeparator
00870                 item.widget->hide();
00871                 item.widget->deleteLater();
00872             }
00873             // show all widgets that might be hidden in the extension
00874             // menu, so that QLayout can recalculate their positions
00875             for (int i = 0; i< d->items.size(); ++i)
00876                 d->items[i].widget->show();
00877 
00878             if (isVisible())
00879                 QApplication::postEvent(this, new QResizeEvent(size(), size()));
00880             break;
00881         }
00882 
00883     default:
00884   Q_ASSERT_X(false, "QToolBar::actionEvent", "internal error");
00885     }
00886 }
00887 
00889 void QToolBar::changeEvent(QEvent *event)
00890 {
00891     Q_D(QToolBar);
00892     switch (event->type()) {
00893     case QEvent::WindowTitleChange:
00894         d->toggleViewAction->setText(windowTitle());
00895         break;
00896     case QEvent::StyleChange:
00897         {
00898             QStyleOptionToolBar opt = getStyleOption(this);
00899             d->layout->setMargin(style()->pixelMetric(QStyle::PM_ToolBarFrameWidth, &opt, this)
00900                                  + style()->pixelMetric(QStyle::PM_ToolBarItemMargin, &opt, this));
00901             d->layout->setSpacing(style()->pixelMetric(QStyle::PM_ToolBarItemSpacing, &opt, this));
00902             break;
00903         }
00904     default:
00905         break;
00906     }
00907     QWidget::changeEvent(event);
00908 }
00909 
00911 void QToolBar::childEvent(QChildEvent *event)
00912 {
00913     Q_D(QToolBar);
00914     QWidget *widget = qobject_cast<QWidget *>(event->child());
00915     if (widget && event->type() == QEvent::ChildRemoved) {
00916         for (int i = 0; i < d->items.size(); ++i) {
00917             const QToolBarItem &item = d->items.at(i);
00918             QWidgetAction *widgetAction = 0;
00919             if (item.widget == widget
00920                 && (widgetAction = qobject_cast<QWidgetAction *>(item.action))) {
00921                 removeAction(widgetAction);
00922                 // ### should we delete the action, or is it the programmer's responsibility?
00923                 // delete widgetAction;
00924             }
00925         }
00926     }
00927     QWidget::childEvent(event);
00928 }
00929 
00931 void QToolBar::paintEvent(QPaintEvent *event)
00932 {
00933     Q_UNUSED(event);
00934     QPainter p(this);
00935     QStyleOptionToolBar opt = getStyleOption(this);
00936     style()->drawControl(QStyle::CE_ToolBar, &opt, &p, this);
00937 }
00938 
00940 void QToolBar::resizeEvent(QResizeEvent *event)
00941 {
00942     Q_D(QToolBar);
00943     if (d->inResizeEvent)
00944         return;
00945     d->inResizeEvent = true;
00946 
00947     QBoxLayout *box = qobject_cast<QBoxLayout *>(layout());
00948     Qt::Orientation orientation = (box->direction() == QBoxLayout::LeftToRight
00949                                    || box->direction() == QBoxLayout::RightToLeft)
00950                                   ? Qt::Horizontal
00951                                   : Qt::Vertical;
00952     const int margin = box->margin();
00953     int i = 0;
00954     int extension_size = 0;
00955     int hidden_count = 0;
00956     int max_item_extent = 0;
00957     i = d->items.size(); // note: the toolbar handle is not counted
00958     while (i > 0) {
00959   QWidget *w = box->itemAt(i)->widget();
00960   bool hide = false;
00961   if (QApplication::layoutDirection() == Qt::RightToLeft && orientation == Qt::Horizontal) {
00962             if (w->isHidden()) {
00963                 if (box->itemAt(i-1) && !box->itemAt(i-1)->widget()->isHidden()) {
00964                     QWidget *pw = box->itemAt(i-1)->widget();
00965                     hide = pw->pos().x() < (extension_size + w->size().width() + margin + box->spacing());
00966                 } else {
00967                     // calculate the pos of the hidden item
00968                     int pos = 0;
00969                     for (int k = 1; k < i; ++k) { // idx 0 == handle
00970                         QWidget * pw = box->itemAt(k)->widget();
00971                         if (pw == w)
00972                             break;
00973                         pos = pw->isHidden()
00974                               ? pos - pw->size().width() - box->spacing()
00975                               : pw->pos().x();
00976                     }
00977                     pos = pos - w->size().width() - box->spacing();
00978                     hide = pos < extension_size + margin;
00979                 }
00980             } else {
00981                 hide = w->pos().x() < extension_size + margin;
00982             }
00983   } else {
00984       hide = pick(orientation, w->pos()) + pick(orientation, w->size())
00985        >= pick(orientation, size()) - extension_size;
00986   }
00987   if (hide && i > 1) { // never hide the first item in the tb
00988       w->hide();
00989             if (d->items[i - 1].action->isVisible()) {
00990                 d->items[i - 1].hidden = true;
00991                 ++hidden_count;
00992             }
00993       // the size of the extension menu button needs to be
00994       // considered when buttons in the toolbar are hidden
00995       extension_size = pick(orientation, d->extension->sizeHint());
00996   } else {
00997             w->setVisible(d->items[i - 1].action->isVisible());
00998             d->items[i - 1].hidden = false;
00999             if (orientation == Qt::Horizontal)
01000                 max_item_extent = qMax(max_item_extent, w->sizeHint().height());
01001             else
01002                 max_item_extent = qMax(max_item_extent, w->sizeHint().width());
01003   }
01004   --i;
01005     }
01006 
01007     int box_spacing = (d->items.size() > 1) ? box->spacing()*2 : box->spacing();
01008     int item_min_size = (orientation == Qt::Horizontal) ? d->iconSize.width() : d->iconSize.height();
01009     if (!d->items.isEmpty()) {
01010         QSize sz(d->items[0].widget->sizeHint());
01011 #ifndef QT_NO_MENUBAR
01012         if (qobject_cast<QMenuBar *>(d->items[0].widget))
01013             sz = d->items[0].widget->minimumSizeHint();
01014 #endif
01015         item_min_size = (orientation == Qt::Horizontal) ? sz.width() : sz.height();
01016     }
01017     if (orientation == Qt::Horizontal) {
01018         setMinimumSize(d->handle->sizeHint().width() + box_spacing + extension_size + margin*2
01019                        + item_min_size, max_item_extent + margin*2);
01020     } else {
01021         setMinimumSize(max_item_extent + margin*2,
01022                        d->handle->sizeHint().height() + box_spacing + extension_size
01023                        + margin*2 + item_min_size);
01024     }
01025 
01026     if (hidden_count > 0) {
01027   if (orientation == Qt::Horizontal) {
01028       int x = QApplication::layoutDirection() == Qt::RightToLeft
01029         ? margin
01030         : width() - d->extension->sizeHint().width() - margin;
01031       d->extension->setGeometry(x, margin, d->extension->sizeHint().width(), max_item_extent);
01032         } else {
01033       d->extension->setGeometry(margin,
01034               height() - d->extension->sizeHint().height() - margin,
01035               max_item_extent,
01036               d->extension->sizeHint().height());
01037         }
01038 
01039 #ifndef QT_NO_MENU
01040   QMenu *pop = d->extension->menu();
01041   if (!pop) {
01042       pop = new QMenu(this);
01043       d->extension->setMenu(pop);
01044   }
01045   pop->clear();
01046   for(int i = 0; i < d->items.size(); ++i) {
01047             const QToolBarItem &item = d->items.at(i);
01048             if (!item.hidden) continue;
01049 
01050             if (!qobject_cast<QWidgetAction *>(item.action)) {
01051                 pop->addAction(item.action);
01052             } else {
01053 #if !defined(QT_NO_SIGNALMAPPER) && !defined(QT_NO_COMBOBOX)
01054                 if (QComboBox *cb = qobject_cast<QComboBox *>(item.widget)) {
01055                     QMenu *cb_menu = new QMenu(cb->windowTitle(), pop);
01056                     QSignalMapper *cb_mapper = new QSignalMapper(cb_menu);
01057                     pop->addMenu(cb_menu);
01058                     QActionGroup *ag = new QActionGroup(cb_menu);
01059                     ag->setExclusive(true);
01060                     for (int i=0; i<cb->count(); ++i) {
01061                         QAction *ac = cb_menu->addAction(cb->itemIcon(i), cb->itemText(i));
01062                         ac->setActionGroup(ag);
01063                         ac->setCheckable(true);
01064                         ac->setChecked(cb->currentIndex() == i);
01065                         connect(ac, SIGNAL(triggered(bool)), cb_mapper, SLOT(map()));
01066                         cb_mapper->setMapping(ac, i);
01067                         cb_mapper->setMapping(ac, cb->itemText(i));
01068                     }
01069                     connect(cb_mapper, SIGNAL(mapped(int)), cb, SIGNAL(activated(int)));
01070                     connect(cb_mapper, SIGNAL(mapped(int)), cb, SLOT(setCurrentIndex(int)));
01071                     connect(cb_mapper, SIGNAL(mapped(QString)), cb, SIGNAL(activated(QString)));
01072                 } else
01073 #endif // QT_NO_SIGNALMAPPER
01074                     if (QToolButton *tb = qobject_cast<QToolButton *>(item.widget)) {
01075                         QAction *ac = pop->addAction(tb->icon(), tb->text());
01076                         connect(ac, SIGNAL(triggered()), tb, SLOT(click()));
01077                     } else {
01078                         QList<QAbstractButton *> children = qFindChildren<QAbstractButton *>(item.widget);
01079                         QList<QAbstractButton *>::const_iterator it = children.constBegin();
01080                         while (it != children.constEnd()) {
01081                             QAction *ac = pop->addAction((*it)->icon(), (*it)->text());
01082                             ac->setCheckable((*it)->isCheckable());
01083                             ac->setChecked((*it)->isChecked());
01084                             ac->setEnabled((*it)->isEnabled());
01085                             connect(ac, SIGNAL(triggered()), *it, SLOT(click()));
01086                             ++it;
01087                         }
01088                     }
01089             }
01090         }
01091         if (pop->actions().size() > 0) {
01092             d->extension->show();
01093             d->extension->setEnabled(true);
01094         } else {
01095             // show a disabled ext btn in the case where widgets in
01096             // the toolbar are hidden but not put into the ext menu -
01097             // this indicates that some items in the tb is hidden
01098             d->extension->show();
01099             d->extension->setEnabled(false);
01100         }
01101 #endif // QT_NO_MENU
01102     } else if (!d->extension->isHidden()) {
01103   if (d->extension->menu())
01104       d->extension->menu()->clear();
01105   d->extension->hide();
01106     }
01107     QWidget::resizeEvent(event);
01108 
01109     d->inResizeEvent = false;
01110 }
01111 
01113 bool QToolBar::event(QEvent *event)
01114 {
01115     Q_D(QToolBar);
01116 
01117     switch (event->type()) {
01118     case QEvent::Hide:
01119         if (!isHidden())
01120             break;
01121         // fallthrough intended
01122     case QEvent::Show:
01123         d->toggleViewAction->setChecked(event->type() == QEvent::Show);
01124         break;
01125     case QEvent::ParentChange:
01126         d->handle->setVisible(d->movable && (qobject_cast<QMainWindow *>(parentWidget()) != 0));
01127         break;
01128     case QEvent::StyleChange:
01129         if (!d->explicitIconSize)
01130             setIconSize(QSize());
01131         break;
01132     default:
01133         break;
01134     }
01135     return QWidget::event(event);
01136 }
01137 
01146 QAction *QToolBar::toggleViewAction() const
01147 { Q_D(const QToolBar); return d->toggleViewAction; }
01148 
01168 QWidget *QToolBar::widgetForAction(QAction *action) const
01169 {
01170     Q_D(const QToolBar);
01171 
01172     int index = d->indexOf(action);
01173     if (index < 0 || index >= d->items.size())
01174         return 0;
01175 
01176     return d->items.at(index).widget;
01177 }
01178 
01179 #include "moc_qtoolbar.cpp"
01180 #endif // QT_NO_TOOLBAR

Generated on Thu Mar 15 11:57:09 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1