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