src/gui/kernel/qwidgetaction.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qwidgetaction.h"
       
    43 #include "qdebug.h"
       
    44 
       
    45 #ifndef QT_NO_ACTION
       
    46 #include "qwidgetaction_p.h"
       
    47 
       
    48 QT_BEGIN_NAMESPACE
       
    49 
       
    50 /*!
       
    51     \class QWidgetAction
       
    52     \since 4.2
       
    53     \brief The QWidgetAction class extends QAction by an interface
       
    54     for inserting custom widgets into action based containers, such
       
    55     as toolbars.
       
    56 
       
    57     \ingroup mainwindow-classes
       
    58 
       
    59     Most actions in an application are represented as items in menus or
       
    60     buttons in toolbars. However sometimes more complex widgets are
       
    61     necessary. For example a zoom action in a word processor may be
       
    62     realized using a QComboBox in a QToolBar, presenting a range
       
    63     of different zoom levels. QToolBar provides QToolBar::insertWidget()
       
    64     as convenience function for inserting a single widget.
       
    65     However if you want to implement an action that uses custom
       
    66     widgets for visualization in multiple containers then you have to
       
    67     subclass QWidgetAction.
       
    68 
       
    69     If a QWidgetAction is added for example to a QToolBar then
       
    70     QWidgetAction::createWidget() is called. Reimplementations of that
       
    71     function should create a new custom widget with the specified parent.
       
    72 
       
    73     If the action is removed from a container widget then
       
    74     QWidgetAction::deleteWidget() is called with the previously created custom
       
    75     widget as argument. The default implementation hides the widget and deletes
       
    76     it using QObject::deleteLater().
       
    77 
       
    78     If you have only one single custom widget then you can set it as default
       
    79     widget using setDefaultWidget(). That widget will then be used if the
       
    80     action is added to a QToolBar, or in general to an action container that
       
    81     supports QWidgetAction. If a QWidgetAction with only a default widget is
       
    82     added to two toolbars at the same time then the default widget is shown
       
    83     only in the first toolbar the action was added to. QWidgetAction takes
       
    84     over ownership of the default widget.
       
    85 
       
    86     Note that it is up to the widget to activate the action, for example by
       
    87     reimplementing mouse event handlers and calling QAction::trigger().
       
    88 
       
    89     \bold {Mac OS X}: If you add a widget to a menu in the application's menu
       
    90     bar on Mac OS X, the widget will be added and it will function but with some
       
    91     limitations:
       
    92     \list 1
       
    93         \o The widget is reparented away from the QMenu to the native menu
       
    94             view. If you show the menu in some other place (e.g. as a popup menu),
       
    95             the widget will not be there.
       
    96         \o Focus/Keyboard handling of the widget is not possible.
       
    97         \o Due to Apple's design, mouse tracking on the widget currently does
       
    98             not work.
       
    99         \o Connecting the triggered() signal to a slot that opens a modal
       
   100             dialog will cause a crash in Mac OS X 10.4 (known bug acknowledged
       
   101             by Apple), a workaround is to use a QueuedConnection instead of a
       
   102             DirectConnection.
       
   103     \endlist
       
   104 
       
   105     \sa QAction, QActionGroup, QWidget
       
   106 */
       
   107 
       
   108 /*!
       
   109     Constructs an action with \a parent.
       
   110 */
       
   111 QWidgetAction::QWidgetAction(QObject *parent)
       
   112     : QAction(*(new QWidgetActionPrivate), parent)
       
   113 {
       
   114 }
       
   115 
       
   116 /*!
       
   117     Destroys the object and frees allocated resources.
       
   118 */
       
   119 QWidgetAction::~QWidgetAction()
       
   120 {
       
   121     Q_D(QWidgetAction);
       
   122     for (int i = 0; i < d->createdWidgets.count(); ++i)
       
   123         disconnect(d->createdWidgets.at(i), SIGNAL(destroyed(QObject*)),
       
   124                    this, SLOT(_q_widgetDestroyed(QObject*)));
       
   125     QList<QWidget *> widgetsToDelete = d->createdWidgets;
       
   126     d->createdWidgets.clear();
       
   127     qDeleteAll(widgetsToDelete);
       
   128     delete d->defaultWidget;
       
   129 }
       
   130 
       
   131 /*!
       
   132     Sets \a widget to be the default widget. The ownership is
       
   133     transferred to QWidgetAction. Unless createWidget() is
       
   134     reimplemented by a subclass to return a new widget the default
       
   135     widget is used when a container widget requests a widget through
       
   136     requestWidget().
       
   137 */
       
   138 void QWidgetAction::setDefaultWidget(QWidget *widget)
       
   139 {
       
   140     Q_D(QWidgetAction);
       
   141     if (widget == d->defaultWidget || d->defaultWidgetInUse)
       
   142         return;
       
   143     delete d->defaultWidget;
       
   144     d->defaultWidget = widget;
       
   145     if (!widget)
       
   146         return;
       
   147 
       
   148     setVisible(!(widget->isHidden() && widget->testAttribute(Qt::WA_WState_ExplicitShowHide)));
       
   149     d->defaultWidget->hide();
       
   150     d->defaultWidget->setParent(0);
       
   151     d->defaultWidgetInUse = false;
       
   152     if (!isEnabled())
       
   153         d->defaultWidget->setEnabled(false);
       
   154 }
       
   155 
       
   156 /*!
       
   157     Returns the default widget.
       
   158 */
       
   159 QWidget *QWidgetAction::defaultWidget() const
       
   160 {
       
   161     Q_D(const QWidgetAction);
       
   162     return d->defaultWidget;
       
   163 }
       
   164 
       
   165 /*!
       
   166     Returns a widget that represents the action, with the given \a
       
   167     parent.
       
   168 
       
   169     Container widgets that support actions can call this function to
       
   170     request a widget as visual representation of the action.
       
   171 
       
   172     \sa releaseWidget(), createWidget(), defaultWidget()
       
   173 */
       
   174 QWidget *QWidgetAction::requestWidget(QWidget *parent)
       
   175 {
       
   176     Q_D(QWidgetAction);
       
   177 
       
   178     QWidget *w = createWidget(parent);
       
   179     if (!w) {
       
   180         if (d->defaultWidgetInUse || !d->defaultWidget)
       
   181             return 0;
       
   182         d->defaultWidget->setParent(parent);
       
   183         d->defaultWidgetInUse = true;
       
   184         return d->defaultWidget;
       
   185     }
       
   186 
       
   187     connect(w, SIGNAL(destroyed(QObject*)),
       
   188             this, SLOT(_q_widgetDestroyed(QObject*)));
       
   189     d->createdWidgets.append(w);
       
   190     return w;
       
   191 }
       
   192 
       
   193 /*!
       
   194     Releases the specified \a widget.
       
   195 
       
   196     Container widgets that support actions call this function when a widget
       
   197     action is removed.
       
   198 
       
   199     \sa requestWidget(), deleteWidget(), defaultWidget()
       
   200 */
       
   201 void QWidgetAction::releaseWidget(QWidget *widget)
       
   202 {
       
   203     Q_D(QWidgetAction);
       
   204 
       
   205     if (widget == d->defaultWidget) {
       
   206         d->defaultWidget->hide();
       
   207         d->defaultWidget->setParent(0);
       
   208         d->defaultWidgetInUse = false;
       
   209         return;
       
   210     }
       
   211 
       
   212     if (!d->createdWidgets.contains(widget))
       
   213         return;
       
   214 
       
   215     disconnect(widget, SIGNAL(destroyed(QObject *)),
       
   216                this, SLOT(_q_widgetDestroyed(QObject *)));
       
   217     d->createdWidgets.removeAll(widget);
       
   218     deleteWidget(widget);
       
   219 }
       
   220 
       
   221 /*!
       
   222     \reimp
       
   223 */
       
   224 bool QWidgetAction::event(QEvent *event)
       
   225 {
       
   226     Q_D(QWidgetAction);
       
   227     if (event->type() == QEvent::ActionChanged) {
       
   228         if (d->defaultWidget)
       
   229             d->defaultWidget->setEnabled(isEnabled());
       
   230         for (int i = 0; i < d->createdWidgets.count(); ++i)
       
   231             d->createdWidgets.at(i)->setEnabled(isEnabled());
       
   232     }
       
   233     return QAction::event(event);
       
   234 }
       
   235 
       
   236 /*!
       
   237     \reimp
       
   238  */
       
   239 bool QWidgetAction::eventFilter(QObject *obj, QEvent *event)
       
   240 {
       
   241     return QAction::eventFilter(obj,event);
       
   242 }
       
   243 
       
   244 /*!
       
   245     This function is called whenever the action is added to a container widget
       
   246     that supports custom widgets. If you don't want a custom widget to be
       
   247     used as representation of the action in the specified \a parent widget then
       
   248     0 should be returned.
       
   249 
       
   250     \sa deleteWidget()
       
   251 */
       
   252 QWidget *QWidgetAction::createWidget(QWidget *parent)
       
   253 {
       
   254     Q_UNUSED(parent)
       
   255     return 0;
       
   256 }
       
   257 
       
   258 /*!
       
   259     This function is called whenever the action is removed from a
       
   260     container widget that displays the action using a custom \a
       
   261     widget previously created using createWidget(). The default
       
   262     implementation hides the \a widget and schedules it for deletion
       
   263     using QObject::deleteLater().
       
   264 
       
   265     \sa createWidget()
       
   266 */
       
   267 void QWidgetAction::deleteWidget(QWidget *widget)
       
   268 {
       
   269     widget->hide();
       
   270     widget->deleteLater();
       
   271 }
       
   272 
       
   273 /*!
       
   274     Returns the list of widgets that have been using createWidget() and
       
   275     are currently in use by widgets the action has been added to.
       
   276 */
       
   277 QList<QWidget *> QWidgetAction::createdWidgets() const
       
   278 {
       
   279     Q_D(const QWidgetAction);
       
   280     return d->createdWidgets;
       
   281 }
       
   282 
       
   283 QT_END_NAMESPACE
       
   284 
       
   285 #include "moc_qwidgetaction.cpp"
       
   286 
       
   287 #endif // QT_NO_ACTION