src/gui/widgets/qpushbutton.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 "qapplication.h"
       
    43 #include "qbitmap.h"
       
    44 #include "qdesktopwidget.h"
       
    45 #include "qdialog.h"
       
    46 #include <private/qdialog_p.h>
       
    47 #include "qdrawutil.h"
       
    48 #include "qevent.h"
       
    49 #include "qfontmetrics.h"
       
    50 #include "qmenu.h"
       
    51 #include "qstylepainter.h"
       
    52 #include "qpixmap.h"
       
    53 #include "qpointer.h"
       
    54 #include "qpushbutton.h"
       
    55 #include "qstyle.h"
       
    56 #include "qstyleoption.h"
       
    57 #include "qtoolbar.h"
       
    58 #include "qdebug.h"
       
    59 #include "qlayoutitem.h"
       
    60 #include "qdialogbuttonbox.h"
       
    61 
       
    62 #ifndef QT_NO_ACCESSIBILITY
       
    63 #include "qaccessible.h"
       
    64 #endif
       
    65 
       
    66 #include "private/qpushbutton_p.h"
       
    67 
       
    68 QT_BEGIN_NAMESPACE
       
    69 
       
    70 
       
    71 /*!
       
    72     \class QPushButton
       
    73     \brief The QPushButton widget provides a command button.
       
    74 
       
    75     \ingroup basicwidgets
       
    76 
       
    77 
       
    78     The push button, or command button, is perhaps the most commonly
       
    79     used widget in any graphical user interface. Push (click) a button
       
    80     to command the computer to perform some action, or to answer a
       
    81     question. Typical buttons are OK, Apply, Cancel, Close, Yes, No
       
    82     and Help.
       
    83 
       
    84     A command button is rectangular and typically displays a text
       
    85     label describing its action. A shortcut key can be specified by
       
    86     preceding the preferred character with an ampersand in the
       
    87     text. For example:
       
    88 
       
    89     \snippet doc/src/snippets/code/src_gui_widgets_qpushbutton.cpp 0
       
    90 
       
    91     In this example the shortcut is \e{Alt+D}. See the \l
       
    92     {QShortcut#mnemonic}{QShortcut} documentation for details (to
       
    93     display an actual ampersand, use '&&').
       
    94 
       
    95     Push buttons display a textual label, and optionally a small
       
    96     icon. These can be set using the constructors and changed later
       
    97     using setText() and setIcon().  If the button is disabled the
       
    98     appearance of the text and icon will be manipulated with respect
       
    99     to the GUI style to make the button look "disabled".
       
   100 
       
   101     A push button emits the signal clicked() when it is activated by
       
   102     the mouse, the Spacebar or by a keyboard shortcut. Connect to
       
   103     this signal to perform the button's action. Push buttons also
       
   104     provide less commonly used signals, for example, pressed() and
       
   105     released().
       
   106 
       
   107     Command buttons in dialogs are by default auto-default buttons,
       
   108     i.e. they become the default push button automatically when they
       
   109     receive the keyboard input focus. A default button is a push
       
   110     button that is activated when the user presses the Enter or Return
       
   111     key in a dialog. You can change this with setAutoDefault(). Note
       
   112     that auto-default buttons reserve a little extra space which is
       
   113     necessary to draw a default-button indicator. If you do not want
       
   114     this space around your buttons, call setAutoDefault(false).
       
   115 
       
   116     Being so central, the button widget has grown to accommodate a
       
   117     great many variations in the past decade. The Microsoft style
       
   118     guide now shows about ten different states of Windows push buttons
       
   119     and the text implies that there are dozens more when all the
       
   120     combinations of features are taken into consideration.
       
   121 
       
   122     The most important modes or states are:
       
   123     \list
       
   124     \i Available or not (grayed out, disabled).
       
   125     \i Standard push button, toggling push button or menu button.
       
   126     \i On or off (only for toggling push buttons).
       
   127     \i Default or normal. The default button in a dialog can generally
       
   128        be "clicked" using the Enter or Return key.
       
   129     \i Auto-repeat or not.
       
   130     \i Pressed down or not.
       
   131     \endlist
       
   132 
       
   133     As a general rule, use a push button when the application or
       
   134     dialog window performs an action when the user clicks on it (such
       
   135     as Apply, Cancel, Close and Help) \e and when the widget is
       
   136     supposed to have a wide, rectangular shape with a text label.
       
   137     Small, typically square buttons that change the state of the
       
   138     window rather than performing an action (such as the buttons in
       
   139     the top-right corner of the QFileDialog) are not command buttons,
       
   140     but tool buttons. Qt provides a special class (QToolButton) for
       
   141     these buttons.
       
   142 
       
   143     If you need toggle behavior (see setCheckable()) or a button
       
   144     that auto-repeats the activation signal when being pushed down
       
   145     like the arrows in a scroll bar (see setAutoRepeat()), a command
       
   146     button is probably not what you want. When in doubt, use a tool
       
   147     button.
       
   148 
       
   149     A variation of a command button is a menu button. These provide
       
   150     not just one command, but several, since when they are clicked
       
   151     they pop up a menu of options. Use the method setMenu() to
       
   152     associate a popup menu with a push button.
       
   153 
       
   154     Other classes of buttons are option buttons (see QRadioButton) and
       
   155     check boxes (see QCheckBox).
       
   156 
       
   157     \table 100%
       
   158     \row \o \inlineimage macintosh-pushbutton.png Screenshot of a Macintosh style push button
       
   159          \o A push button shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
       
   160 
       
   161          Note that when a button's width becomes smaller than 50 or
       
   162          its height becomes smaller than 30, the button's corners are
       
   163          changed from round to square. Use the setMinimumSize()
       
   164          function to prevent this behavior.
       
   165 
       
   166     \row \o \inlineimage windowsxp-pushbutton.png Screenshot of a Windows XP style push button
       
   167          \o A push button shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
       
   168     \row \o \inlineimage plastique-pushbutton.png Screenshot of a Plastique style push button
       
   169          \o A push button shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
       
   170     \endtable
       
   171 
       
   172     In Qt, the QAbstractButton base class provides most of the modes
       
   173     and other API, and QPushButton provides GUI logic.
       
   174     See QAbstractButton for more information about the API.
       
   175 
       
   176     \sa QToolButton, QRadioButton, QCheckBox, {fowler}{GUI Design Handbook: Push Button}
       
   177 */
       
   178 
       
   179 /*!
       
   180     \property QPushButton::autoDefault
       
   181     \brief whether the push button is an auto default button
       
   182 
       
   183     If this property is set to true then the push button is an auto
       
   184     default button.
       
   185 
       
   186     In some GUI styles a default button is drawn with an extra frame
       
   187     around it, up to 3 pixels or more. Qt automatically keeps this
       
   188     space free around auto-default buttons, i.e. auto-default buttons
       
   189     may have a slightly larger size hint.
       
   190 
       
   191     This property's default is true for buttons that have a QDialog
       
   192     parent; otherwise it defaults to false.
       
   193 
       
   194     See the \l default property for details of how \l default and
       
   195     auto-default interact.
       
   196 */
       
   197 
       
   198 /*!
       
   199     \property QPushButton::default
       
   200     \brief whether the push button is the default button
       
   201 
       
   202     Default and autodefault buttons decide what happens when the user
       
   203     presses enter in a dialog.
       
   204 
       
   205     A button with this property set to true (i.e., the dialog's
       
   206     \e default button,) will automatically be pressed when the user presses enter,
       
   207     with one exception: if an \a autoDefault button currently has focus, the autoDefault
       
   208     button is pressed. When the dialog has \l autoDefault buttons but no default button,
       
   209     pressing enter will press either the \l autoDefault button that currently has focus, or if no
       
   210     button has focus, the next \l autoDefault button in the focus chain.
       
   211 
       
   212     In a dialog, only one push button at a time can be the default
       
   213     button. This button is then displayed with an additional frame
       
   214     (depending on the GUI style).
       
   215 
       
   216     The default button behavior is provided only in dialogs. Buttons
       
   217     can always be clicked from the keyboard by pressing Spacebar when
       
   218     the button has focus.
       
   219 
       
   220     If the default property is set to false on the current default button
       
   221     while the dialog is visible, a new default will automatically be
       
   222     assigned the next time a pushbutton in the dialog receives focus.
       
   223 
       
   224     This property's default is false.
       
   225 */
       
   226 
       
   227 /*!
       
   228     \property QPushButton::flat
       
   229     \brief whether the button border is raised
       
   230 
       
   231     This property's default is false. If this property is set, most
       
   232     styles will not paint the button background unless the button is
       
   233     being pressed. setAutoFillBackground() can be used to ensure that
       
   234     the background is filled using the QPalette::Button brush.
       
   235 */
       
   236 
       
   237 /*!
       
   238     Constructs a push button with no text and a \a parent.
       
   239 */
       
   240 
       
   241 QPushButton::QPushButton(QWidget *parent)
       
   242     : QAbstractButton(*new QPushButtonPrivate, parent)
       
   243 {
       
   244     Q_D(QPushButton);
       
   245     d->init();
       
   246 }
       
   247 
       
   248 /*!
       
   249     Constructs a push button with the parent \a parent and the text \a
       
   250     text.
       
   251 */
       
   252 
       
   253 QPushButton::QPushButton(const QString &text, QWidget *parent)
       
   254     : QAbstractButton(*new QPushButtonPrivate, parent)
       
   255 {
       
   256     Q_D(QPushButton);
       
   257     setText(text);
       
   258     d->init();
       
   259 }
       
   260 
       
   261 
       
   262 /*!
       
   263     Constructs a push button with an \a icon and a \a text, and a \a parent.
       
   264 
       
   265     Note that you can also pass a QPixmap object as an icon (thanks to
       
   266     the implicit type conversion provided by C++).
       
   267 
       
   268 */
       
   269 QPushButton::QPushButton(const QIcon& icon, const QString &text, QWidget *parent)
       
   270     : QAbstractButton(*new QPushButtonPrivate, parent)
       
   271 {
       
   272     Q_D(QPushButton);
       
   273     setText(text);
       
   274     setIcon(icon);
       
   275     d->init();
       
   276 }
       
   277 
       
   278 /*! \internal
       
   279  */
       
   280 QPushButton::QPushButton(QPushButtonPrivate &dd, QWidget *parent)
       
   281     : QAbstractButton(dd, parent)
       
   282 {
       
   283     Q_D(QPushButton);
       
   284     d->init();
       
   285 }
       
   286 
       
   287 /*!
       
   288     Destroys the push button.
       
   289 */
       
   290 QPushButton::~QPushButton()
       
   291 {
       
   292 }
       
   293 
       
   294 QDialog *QPushButtonPrivate::dialogParent() const
       
   295 {
       
   296     Q_Q(const QPushButton);
       
   297     const QWidget *p = q;
       
   298     while (p && !p->isWindow()) {
       
   299         p = p->parentWidget();
       
   300         if (const QDialog *dialog = qobject_cast<const QDialog *>(p))
       
   301             return const_cast<QDialog *>(dialog);
       
   302     }
       
   303     return 0;
       
   304 }
       
   305 
       
   306 /*!
       
   307     Initialize \a option with the values from this QPushButton. This method is useful
       
   308     for subclasses when they need a QStyleOptionButton, but don't want to fill
       
   309     in all the information themselves.
       
   310 
       
   311     \sa QStyleOption::initFrom()
       
   312 */
       
   313 void QPushButton::initStyleOption(QStyleOptionButton *option) const
       
   314 {
       
   315     if (!option)
       
   316         return;
       
   317 
       
   318     Q_D(const QPushButton);
       
   319     option->initFrom(this);
       
   320     option->features = QStyleOptionButton::None;
       
   321     if (d->flat)
       
   322         option->features |= QStyleOptionButton::Flat;
       
   323 #ifndef QT_NO_MENU
       
   324     if (d->menu)
       
   325         option->features |= QStyleOptionButton::HasMenu;
       
   326 #endif
       
   327     if (autoDefault() || d->defaultButton)
       
   328         option->features |= QStyleOptionButton::AutoDefaultButton;
       
   329     if (d->defaultButton)
       
   330         option->features |= QStyleOptionButton::DefaultButton;
       
   331     if (d->down || d->menuOpen)
       
   332         option->state |= QStyle::State_Sunken;
       
   333     if (d->checked)
       
   334         option->state |= QStyle::State_On;
       
   335     if (!d->flat && !d->down)
       
   336         option->state |= QStyle::State_Raised;
       
   337     option->text = d->text;
       
   338     option->icon = d->icon;
       
   339     option->iconSize = iconSize();
       
   340 }
       
   341 
       
   342 void QPushButton::setAutoDefault(bool enable)
       
   343 {
       
   344     Q_D(QPushButton);
       
   345     uint state = enable ? QPushButtonPrivate::On : QPushButtonPrivate::Off;
       
   346     if (d->autoDefault != QPushButtonPrivate::Auto && d->autoDefault == state)
       
   347         return;
       
   348     d->autoDefault = state;
       
   349     d->sizeHint = QSize();
       
   350     update();
       
   351     updateGeometry();
       
   352 }
       
   353 
       
   354 bool QPushButton::autoDefault() const
       
   355 {
       
   356     Q_D(const QPushButton);
       
   357     if(d->autoDefault == QPushButtonPrivate::Auto)
       
   358         return ( d->dialogParent() != 0 );
       
   359     return d->autoDefault;
       
   360 }
       
   361 
       
   362 void QPushButton::setDefault(bool enable)
       
   363 {
       
   364     Q_D(QPushButton);
       
   365     if (d->defaultButton == enable)
       
   366         return;
       
   367     d->defaultButton = enable;
       
   368     if (d->defaultButton) {
       
   369         if (QDialog *dlg = d->dialogParent())
       
   370             dlg->d_func()->setMainDefault(this);
       
   371     }
       
   372     update();
       
   373 #ifndef QT_NO_ACCESSIBILITY
       
   374     QAccessible::updateAccessibility(this, 0, QAccessible::StateChanged);
       
   375 #endif
       
   376 }
       
   377 
       
   378 bool QPushButton::isDefault() const
       
   379 {
       
   380     Q_D(const QPushButton);
       
   381     return d->defaultButton;
       
   382 }
       
   383 
       
   384 /*!
       
   385     \reimp
       
   386 */
       
   387 QSize QPushButton::sizeHint() const
       
   388 {
       
   389     Q_D(const QPushButton);
       
   390     if (d->sizeHint.isValid() && d->lastAutoDefault == autoDefault())
       
   391         return d->sizeHint;
       
   392     d->lastAutoDefault = autoDefault();
       
   393     ensurePolished();
       
   394 
       
   395     int w = 0, h = 0;
       
   396 
       
   397     QStyleOptionButton opt;
       
   398     initStyleOption(&opt);
       
   399 
       
   400     // calculate contents size...
       
   401 #ifndef QT_NO_ICON
       
   402 
       
   403     bool showButtonBoxIcons = qobject_cast<QDialogButtonBox*>(parentWidget())
       
   404                           && style()->styleHint(QStyle::SH_DialogButtonBox_ButtonsHaveIcons);
       
   405 
       
   406     if (!icon().isNull() || showButtonBoxIcons) {
       
   407         int ih = opt.iconSize.height();
       
   408         int iw = opt.iconSize.width() + 4;
       
   409         w += iw;
       
   410         h = qMax(h, ih);
       
   411     }
       
   412 #endif
       
   413     QString s(text());
       
   414     bool empty = s.isEmpty();
       
   415     if (empty)
       
   416         s = QString::fromLatin1("XXXX");
       
   417     QFontMetrics fm = fontMetrics();
       
   418     QSize sz = fm.size(Qt::TextShowMnemonic, s);
       
   419     if(!empty || !w)
       
   420         w += sz.width();
       
   421     if(!empty || !h)
       
   422         h = qMax(h, sz.height());
       
   423     opt.rect.setSize(QSize(w, h)); // PM_MenuButtonIndicator depends on the height
       
   424 #ifndef QT_NO_MENU
       
   425     if (menu())
       
   426         w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt, this);
       
   427 #endif
       
   428     d->sizeHint = (style()->sizeFromContents(QStyle::CT_PushButton, &opt, QSize(w, h), this).
       
   429                   expandedTo(QApplication::globalStrut()));
       
   430     return d->sizeHint;
       
   431 }
       
   432 
       
   433 /*!
       
   434     \reimp
       
   435  */
       
   436 QSize QPushButton::minimumSizeHint() const
       
   437 {
       
   438     return sizeHint();
       
   439 }
       
   440 
       
   441 
       
   442 /*!\reimp
       
   443 */
       
   444 void QPushButton::paintEvent(QPaintEvent *)
       
   445 {
       
   446     QStylePainter p(this);
       
   447     QStyleOptionButton option;
       
   448     initStyleOption(&option);
       
   449     p.drawControl(QStyle::CE_PushButton, option);
       
   450 }
       
   451 
       
   452 
       
   453 /*! \reimp */
       
   454 void QPushButton::keyPressEvent(QKeyEvent *e)
       
   455 {
       
   456     Q_D(QPushButton);
       
   457     switch (e->key()) {
       
   458     case Qt::Key_Enter:
       
   459     case Qt::Key_Return:
       
   460         if (autoDefault() || d->defaultButton) {
       
   461             click();
       
   462             break;
       
   463         }
       
   464         // fall through
       
   465     default:
       
   466         QAbstractButton::keyPressEvent(e);
       
   467     }
       
   468 }
       
   469 
       
   470 /*!
       
   471     \reimp
       
   472 */
       
   473 void QPushButton::focusInEvent(QFocusEvent *e)
       
   474 {
       
   475     Q_D(QPushButton);
       
   476     if (e->reason() != Qt::PopupFocusReason && autoDefault() && !d->defaultButton) {
       
   477         d->defaultButton = true;
       
   478         QDialog *dlg = qobject_cast<QDialog*>(window());
       
   479         if (dlg)
       
   480             dlg->d_func()->setDefault(this);
       
   481     }
       
   482     QAbstractButton::focusInEvent(e);
       
   483 }
       
   484 
       
   485 /*!
       
   486     \reimp
       
   487 */
       
   488 void QPushButton::focusOutEvent(QFocusEvent *e)
       
   489 {
       
   490     Q_D(QPushButton);
       
   491     if (e->reason() != Qt::PopupFocusReason && autoDefault() && d->defaultButton) {
       
   492         QDialog *dlg = qobject_cast<QDialog*>(window());
       
   493         if (dlg)
       
   494             dlg->d_func()->setDefault(0);
       
   495         else
       
   496             d->defaultButton = false;
       
   497     }
       
   498 
       
   499     QAbstractButton::focusOutEvent(e);
       
   500 #ifndef QT_NO_MENU
       
   501     if (d->menu && d->menu->isVisible())        // restore pressed status
       
   502         setDown(true);
       
   503 #endif
       
   504 }
       
   505 
       
   506 #ifndef QT_NO_MENU
       
   507 /*!
       
   508     Associates the popup menu \a menu with this push button. This
       
   509     turns the button into a menu button, which in some styles will
       
   510     produce a small triangle to the right of the button's text.
       
   511 
       
   512     Ownership of the menu is \e not transferred to the push button.
       
   513 
       
   514     \table 100%
       
   515     \row
       
   516     \o \inlineimage plastique-pushbutton-menu.png Screenshot of a Plastique style push button with popup menu.
       
   517     \o \inlineimage cleanlooks-pushbutton-menu.png Screenshot of a Cleanlooks style push button with popup menu.
       
   518     \o Push buttons with popup menus shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}
       
   519     (left) and \l{Cleanlooks Style Widget Gallery}{Cleanlooks widget style} (right).
       
   520     \endtable
       
   521 
       
   522     \sa menu()
       
   523 */
       
   524 void QPushButton::setMenu(QMenu* menu)
       
   525 {
       
   526     Q_D(QPushButton);
       
   527     if (menu == d->menu)
       
   528         return;
       
   529 
       
   530     if (menu && !d->menu) {
       
   531         connect(this, SIGNAL(pressed()), this, SLOT(_q_popupPressed()), Qt::UniqueConnection);
       
   532     }
       
   533     if (d->menu)
       
   534         removeAction(d->menu->menuAction());
       
   535     d->menu = menu;
       
   536     if (d->menu)
       
   537         addAction(d->menu->menuAction());
       
   538 
       
   539     d->resetLayoutItemMargins();
       
   540     d->sizeHint = QSize();
       
   541     update();
       
   542     updateGeometry();
       
   543 }
       
   544 
       
   545 /*!
       
   546     Returns the button's associated popup menu or 0 if no popup menu
       
   547     has been set.
       
   548 
       
   549     \sa setMenu()
       
   550 */
       
   551 QMenu* QPushButton::menu() const
       
   552 {
       
   553     Q_D(const QPushButton);
       
   554     return d->menu;
       
   555 }
       
   556 
       
   557 /*!
       
   558     Shows (pops up) the associated popup menu. If there is no such
       
   559     menu, this function does nothing. This function does not return
       
   560     until the popup menu has been closed by the user.
       
   561 */
       
   562 void QPushButton::showMenu()
       
   563 {
       
   564     Q_D(QPushButton);
       
   565     if (!d || !d->menu)
       
   566         return;
       
   567     setDown(true);
       
   568     d->_q_popupPressed();
       
   569 }
       
   570 
       
   571 void QPushButtonPrivate::_q_popupPressed()
       
   572 {
       
   573     Q_Q(QPushButton);
       
   574     if (!down || !menu)
       
   575         return;
       
   576 
       
   577     menu->setNoReplayFor(q);
       
   578     bool horizontal = true;
       
   579 #if !defined(QT_NO_TOOLBAR)
       
   580     QToolBar *tb = qobject_cast<QToolBar*>(parent);
       
   581     if (tb && tb->orientation() == Qt::Vertical)
       
   582         horizontal = false;
       
   583 #endif
       
   584     QWidgetItem item(q);
       
   585     QRect rect = item.geometry();
       
   586     rect.setRect(rect.x() - q->x(), rect.y() - q->y(), rect.width(), rect.height());
       
   587 
       
   588     QSize menuSize = menu->sizeHint();
       
   589     QPoint globalPos = q->mapToGlobal(rect.topLeft());
       
   590     int x = globalPos.x();
       
   591     int y = globalPos.y();
       
   592     if (horizontal) {
       
   593         if (globalPos.y() + rect.height() + menuSize.height() <= QApplication::desktop()->availableGeometry(q).height()) {
       
   594             y += rect.height();
       
   595         } else {
       
   596             y -= menuSize.height();
       
   597         }
       
   598         if (q->layoutDirection() == Qt::RightToLeft)
       
   599             x += rect.width() - menuSize.width();
       
   600     } else {
       
   601         if (globalPos.x() + rect.width() + menu->sizeHint().width() <= QApplication::desktop()->availableGeometry(q).width())
       
   602             x += rect.width();
       
   603         else
       
   604             x -= menuSize.width();
       
   605     }
       
   606     QPointer<QPushButton> guard(q);
       
   607 
       
   608     //Because of a delay in menu effects, we must keep track of the
       
   609     //menu visibility to avoid flicker on button release
       
   610     menuOpen = true;
       
   611     menu->exec(QPoint(x, y));
       
   612     if (guard) {
       
   613         menuOpen = false;
       
   614         q->setDown(false);
       
   615     }
       
   616 }
       
   617 #endif // QT_NO_MENU
       
   618 
       
   619 void QPushButtonPrivate::resetLayoutItemMargins()
       
   620 {
       
   621     Q_Q(QPushButton);
       
   622     QStyleOptionButton opt;
       
   623     q->initStyleOption(&opt);
       
   624     setLayoutItemMargins(QStyle::SE_PushButtonLayoutItem, &opt);
       
   625 }
       
   626 
       
   627 void QPushButton::setFlat(bool flat)
       
   628 {
       
   629     Q_D(QPushButton);
       
   630     if (d->flat == flat)
       
   631         return;
       
   632     d->flat = flat;
       
   633 	d->resetLayoutItemMargins();
       
   634     d->sizeHint = QSize();
       
   635     update();
       
   636     updateGeometry();
       
   637 }
       
   638 
       
   639 bool QPushButton::isFlat() const
       
   640 {
       
   641     Q_D(const QPushButton);
       
   642     return d->flat;
       
   643 }
       
   644 
       
   645 /*! \reimp */
       
   646 bool QPushButton::event(QEvent *e)
       
   647 {
       
   648     Q_D(QPushButton);
       
   649     if (e->type() == QEvent::ParentChange) {
       
   650         if (QDialog *dialog = d->dialogParent()) {
       
   651             if (d->defaultButton)
       
   652                 dialog->d_func()->setMainDefault(this);
       
   653         }
       
   654     } else if (e->type() == QEvent::StyleChange
       
   655 #ifdef Q_WS_MAC
       
   656                || e->type() == QEvent::MacSizeChange
       
   657 #endif
       
   658                ) {
       
   659 		d->resetLayoutItemMargins();
       
   660 		updateGeometry();
       
   661     } else if (e->type() == QEvent::PolishRequest) {
       
   662         updateGeometry();
       
   663     }
       
   664     return QAbstractButton::event(e);
       
   665 }
       
   666 
       
   667 #ifdef QT3_SUPPORT
       
   668 /*!
       
   669     Use one of the constructors that doesn't take the \a name
       
   670     argument and then use setObjectName() instead.
       
   671 */
       
   672 QPushButton::QPushButton(QWidget *parent, const char *name)
       
   673     : QAbstractButton(*new QPushButtonPrivate, parent)
       
   674 {
       
   675     Q_D(QPushButton);
       
   676     setObjectName(QString::fromAscii(name));
       
   677     d->init();
       
   678 }
       
   679 
       
   680 /*!
       
   681     Use one of the constructors that doesn't take the \a name
       
   682     argument and then use setObjectName() instead.
       
   683 */
       
   684 QPushButton::QPushButton(const QString &text, QWidget *parent, const char *name)
       
   685     : QAbstractButton(*new QPushButtonPrivate, parent)
       
   686 {
       
   687     Q_D(QPushButton);
       
   688     setObjectName(QString::fromAscii(name));
       
   689     setText(text);
       
   690     d->init();
       
   691 }
       
   692 
       
   693 /*!
       
   694     Use one of the constructors that doesn't take the \a name
       
   695     argument and then use setObjectName() instead.
       
   696 */
       
   697 QPushButton::QPushButton(const QIcon& icon, const QString &text, QWidget *parent, const char *name)
       
   698     : QAbstractButton(*new QPushButtonPrivate, parent)
       
   699 {
       
   700     Q_D(QPushButton);
       
   701     setObjectName(QString::fromAscii(name));
       
   702     setText(text);
       
   703     setIcon(icon);
       
   704     d->init();
       
   705 }
       
   706 #endif
       
   707 
       
   708 /*!
       
   709     \fn void QPushButton::openPopup()
       
   710 
       
   711     Use showMenu() instead.
       
   712 */
       
   713 
       
   714 /*!
       
   715     \fn bool QPushButton::isMenuButton() const
       
   716 
       
   717     Use menu() != 0 instead.
       
   718 */
       
   719 
       
   720 /*!
       
   721     \fn void QPushButton::setPopup(QMenu* popup)
       
   722 
       
   723     Use setMenu() instead.
       
   724 */
       
   725 
       
   726 /*!
       
   727     \fn QMenu* QPushButton::popup() const
       
   728 
       
   729     Use menu() instead.
       
   730 */
       
   731 
       
   732 QT_END_NAMESPACE
       
   733 
       
   734 #include "moc_qpushbutton.cpp"