Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qpushbutton.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qapplication.h"
5#include "qbitmap.h"
6#if QT_CONFIG(dialog)
7#include <private/qdialog_p.h>
8#endif
9#include "qdrawutil.h"
10#include "qevent.h"
11#include "qfontmetrics.h"
12#include "qstylepainter.h"
13#include "qpixmap.h"
14#include "qpointer.h"
15#include "qpushbutton.h"
16#include "qstyle.h"
17#include "qstyleoption.h"
18#if QT_CONFIG(toolbar)
19#include "qtoolbar.h"
20#endif
21#include "qdebug.h"
22#include "qlayoutitem.h"
23#if QT_CONFIG(dialogbuttonbox)
24#include "qdialogbuttonbox.h"
25#endif
26
27#if QT_CONFIG(accessibility)
28#include "qaccessible.h"
29#endif
30
31#if QT_CONFIG(menu)
32#include "qmenu.h"
33#include "private/qmenu_p.h"
34#endif
35#include "private/qpushbutton_p.h"
36
38
39
204 : QAbstractButton(*new QPushButtonPrivate, parent)
205{
206 Q_D(QPushButton);
207 d->init();
208}
209
216 : QPushButton(parent)
217{
218 setText(text);
219}
220
221
230 : QPushButton(*new QPushButtonPrivate, parent)
231{
232 setText(text);
233 setIcon(icon);
234}
235
239 : QAbstractButton(dd, parent)
240{
241 Q_D(QPushButton);
242 d->init();
243}
244
251
252#if QT_CONFIG(dialog)
254{
255 Q_Q(const QPushButton);
256 const QWidget *p = q;
257 while (p && !p->isWindow()) {
258 p = p->parentWidget();
259 if (const QDialog *dialog = qobject_cast<const QDialog *>(p))
260 return const_cast<QDialog *>(dialog);
261 }
262 return nullptr;
263}
264#endif
265
274{
275 if (!option)
276 return;
277
278 Q_D(const QPushButton);
279 option->initFrom(this);
281 if (d->flat)
282 option->features |= QStyleOptionButton::Flat;
283#if QT_CONFIG(menu)
284 if (d->menu)
286#endif
287 if (autoDefault())
289 if (d->defaultButton)
291 if (d->down || d->menuOpen)
293 if (d->checked)
294 option->state |= QStyle::State_On;
295 if (!d->flat && !d->down)
297 if (underMouse() && hasMouseTracking())
298 option->state.setFlag(QStyle::State_MouseOver, d->hovering);
299 option->text = d->text;
300 option->icon = d->icon;
301 option->iconSize = iconSize();
302}
303
305{
306 Q_D(QPushButton);
308 if (d->autoDefault != QPushButtonPrivate::Auto && d->autoDefault == state)
309 return;
310 d->autoDefault = state;
311 d->sizeHint = QSize();
312 update();
314}
315
317{
318 Q_D(const QPushButton);
319 if (d->autoDefault == QPushButtonPrivate::Auto)
320 return ( d->dialogParent() != nullptr );
321 return d->autoDefault;
322}
323
325{
326 Q_D(QPushButton);
327 if (d->defaultButton == enable)
328 return;
329 d->defaultButton = enable;
330#if QT_CONFIG(dialog)
331 if (d->defaultButton) {
332 if (QDialog *dlg = d->dialogParent())
333 dlg->d_func()->setMainDefault(this);
334 }
335#endif
336 update();
337#if QT_CONFIG(accessibility)
339 s.defaultButton = true;
340 QAccessibleStateChangeEvent event(this, s);
341 QAccessible::updateAccessibility(&event);
342#endif
343}
344
346{
347 Q_D(const QPushButton);
348 return d->defaultButton;
349}
350
355{
356 Q_D(const QPushButton);
357 if (d->sizeHint.isValid() && d->lastAutoDefault == autoDefault())
358 return d->sizeHint;
359 d->lastAutoDefault = autoDefault();
361
362 int w = 0, h = 0;
363
366
367 // calculate contents size...
368#if !defined(QT_NO_ICON) && QT_CONFIG(dialogbuttonbox)
369 bool showButtonBoxIcons = qobject_cast<QDialogButtonBox*>(parentWidget())
371
372 if (!icon().isNull() || showButtonBoxIcons) {
373 int ih = opt.iconSize.height();
374 int iw = opt.iconSize.width() + 4;
375 w += iw;
376 h = qMax(h, ih);
377 }
378#endif
379 QString s(text());
380 bool empty = s.isEmpty();
381 if (empty)
382 s = QStringLiteral("XXXX");
384 QSize sz = fm.size(Qt::TextShowMnemonic, s);
385 if (!empty || !w)
386 w += sz.width();
387 if (!empty || !h)
388 h = qMax(h, sz.height());
389 opt.rect.setSize(QSize(w, h)); // PM_MenuButtonIndicator depends on the height
390#if QT_CONFIG(menu)
391 if (menu())
393#endif
394 d->sizeHint = style()->sizeFromContents(QStyle::CT_PushButton, &opt, QSize(w, h), this);
395 return d->sizeHint;
396}
397
402{
403 return sizeHint();
404}
405
406
416
417
420{
421 Q_D(QPushButton);
422 switch (e->key()) {
423 case Qt::Key_Enter:
424 case Qt::Key_Return:
425 if (autoDefault() || d->defaultButton) {
426 click();
427 break;
428 }
430 default:
432 }
433}
434
439{
440 Q_D(QPushButton);
441 if (e->reason() != Qt::PopupFocusReason && autoDefault() && !d->defaultButton) {
442 d->defaultButton = true;
443#if QT_CONFIG(dialog)
444 QDialog *dlg = qobject_cast<QDialog*>(window());
445 if (dlg)
446 dlg->d_func()->setDefault(this);
447#endif
448 }
450}
451
456{
457 Q_D(QPushButton);
458 if (e->reason() != Qt::PopupFocusReason && autoDefault() && d->defaultButton) {
459#if QT_CONFIG(dialog)
460 QDialog *dlg = qobject_cast<QDialog*>(window());
461 if (dlg)
462 dlg->d_func()->setDefault(nullptr);
463 else
464 d->defaultButton = false;
465#endif
466 }
467
469#if QT_CONFIG(menu)
470 if (d->menu && d->menu->isVisible()) // restore pressed status
471 setDown(true);
472#endif
473}
474
479{
480 Q_D(QPushButton);
481
483 bool hit = false;
484 if (underMouse())
485 hit = hitButton(e->position().toPoint());
486
487 if (hit != d->hovering) {
488 update(rect());
489 d->hovering = hit;
490 }
491 }
492
494}
495
500{
504 return bevel.contains(pos);
505}
506
507#if QT_CONFIG(menu)
521void QPushButton::setMenu(QMenu* menu)
522{
523 Q_D(QPushButton);
524 if (menu == d->menu)
525 return;
526
527 if (menu && !d->menu) {
530 }
531 if (d->menu)
532 removeAction(d->menu->menuAction());
533 d->menu = menu;
534 if (d->menu)
535 addAction(d->menu->menuAction());
536
537 d->resetLayoutItemMargins();
538 d->sizeHint = QSize();
539 update();
541}
542
549QMenu* QPushButton::menu() const
550{
551 Q_D(const QPushButton);
552 return d->menu;
553}
554
560void QPushButton::showMenu()
561{
562 Q_D(QPushButton);
563 if (!d || !d->menu)
564 return;
565 setDown(true);
566 d->popupPressed();
567}
568
570{
571 Q_Q(QPushButton);
572 if (!down || !menu)
573 return;
574
576
577 QPoint menuPos = adjustedMenuPosition();
578
579 QMenuPrivate::get(menu)->causedPopup.widget = q;
580
581 //Because of a delay in menu effects, we must keep track of the
582 //menu visibility to avoid flicker on button release
583 menuOpen = true;
585 q, [q, this]{ menuOpen = false; q->setDown(false); }, Qt::SingleShotConnection);
586 menu->popup(menuPos);
587}
588
589QPoint QPushButtonPrivate::adjustedMenuPosition()
590{
591 Q_Q(QPushButton);
592
593 bool horizontal = true;
594#if QT_CONFIG(toolbar)
595 QToolBar *tb = qobject_cast<QToolBar*>(parent);
596 if (tb && tb->orientation() == Qt::Vertical)
597 horizontal = false;
598#endif
599
601 QRect rect = item.geometry();
602 rect.setRect(rect.x() - q->x(), rect.y() - q->y(), rect.width(), rect.height());
603
604 QSize menuSize = menu->sizeHint();
605 QPoint globalPos = q->mapToGlobal(rect.topLeft());
606 int x = globalPos.x();
607 int y = globalPos.y();
608 const QRect availableGeometry = QWidgetPrivate::availableScreenGeometry(q, q->mapToGlobal(rect.center()));
609 if (horizontal) {
610 if (globalPos.y() + rect.height() + menuSize.height() <= availableGeometry.bottom()) {
611 y += rect.height();
612 } else if (globalPos.y() - menuSize.height() >= availableGeometry.y()) {
613 y -= menuSize.height();
614 }
615 if (q->layoutDirection() == Qt::RightToLeft)
616 x += rect.width() - menuSize.width();
617 } else {
618 if (globalPos.x() + rect.width() + menu->sizeHint().width() <= availableGeometry.right()) {
619 x += rect.width();
620 } else if (globalPos.x() - menuSize.width() >= availableGeometry.x()) {
621 x -= menuSize.width();
622 }
623 }
624
625 return QPoint(x,y);
626}
627
628#endif // QT_CONFIG(menu)
629
631{
632 Q_Q(QPushButton);
633 q->setAttribute(Qt::WA_MacShowFocusRect);
635}
636
644
645void QPushButton::setFlat(bool flat)
646{
647 Q_D(QPushButton);
648 if (d->flat == flat)
649 return;
650 d->flat = flat;
651 d->resetLayoutItemMargins();
652 d->sizeHint = QSize();
653 update();
655}
656
658{
659 Q_D(const QPushButton);
660 return d->flat;
661}
662
665{
666 Q_D(QPushButton);
667 if (e->type() == QEvent::ParentChange) {
668#if QT_CONFIG(dialog)
669 if (QDialog *dialog = d->dialogParent()) {
670 if (d->defaultButton)
671 dialog->d_func()->setMainDefault(this);
672 }
673#endif
674 } else if (e->type() == QEvent::StyleChange
675#ifdef Q_OS_MAC
676 || e->type() == QEvent::MacSizeChange
677#endif
678 ) {
679 d->resetLayoutItemMargins();
681 } else if (e->type() == QEvent::PolishRequest) {
683 }
684 return QAbstractButton::event(e);
685}
686
688
689#include "moc_qpushbutton.cpp"
The QAbstractButton class is the abstract base class of button widgets, providing functionality commo...
void mouseMoveEvent(QMouseEvent *e) override
\reimp
QIcon icon
the icon shown on the button
void click()
Performs a click.
void focusInEvent(QFocusEvent *e) override
\reimp
void setIcon(const QIcon &icon)
bool event(QEvent *e) override
\reimp
void pressed()
This signal is emitted when the button is pressed down.
void keyPressEvent(QKeyEvent *e) override
\reimp
void setText(const QString &text)
QSize iconSize
the icon size used for this button.
void focusOutEvent(QFocusEvent *e) override
\reimp
QString text
the text shown on the button
\inmodule QtGui
The QDialog class is the base class of dialog windows.
Definition qdialog.h:19
\inmodule QtCore
Definition qcoreevent.h:45
@ ParentChange
Definition qcoreevent.h:80
@ PolishRequest
Definition qcoreevent.h:110
@ StyleChange
Definition qcoreevent.h:136
@ MacSizeChange
Definition qcoreevent.h:217
Type type() const
Returns the event type.
Definition qcoreevent.h:304
The QFocusEvent class contains event parameters for widget focus events.
Definition qevent.h:470
Qt::FocusReason reason() const
Returns the reason for this focus event.
Definition qevent.cpp:1569
\reentrant \inmodule QtGui
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
The QKeyEvent class describes a key event.
Definition qevent.h:424
int key() const
Returns the code of the key that was pressed or released.
Definition qevent.h:434
static QMenuPrivate * get(QMenu *m)
Definition qmenu_p.h:309
The QMenu class provides a menu widget for use in menu bars, context menus, and other popup menus.
Definition qmenu.h:26
QSize sizeHint() const override
\reimp
Definition qmenu.cpp:2269
void popup(const QPoint &pos, QAction *at=nullptr)
Displays the menu so that the action atAction will be at the specified global position p.
Definition qmenu.cpp:2310
void aboutToHide()
void setNoReplayFor(QWidget *widget)
Definition qmenu.cpp:3703
\inmodule QtGui
Definition qevent.h:196
QObject * parent
Definition qobject.h:73
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:299
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:486
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:404
\inmodule QtCore\reentrant
Definition qpoint.h:25
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:130
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:135
QDialog * dialogParent() const
QPointer< QMenu > menu
The QPushButton widget provides a command button.
Definition qpushbutton.h:20
bool autoDefault
whether the push button is an auto default button
Definition qpushbutton.h:23
void keyPressEvent(QKeyEvent *) override
\reimp
bool hitButton(const QPoint &pos) const override
\reimp
void setDefault(bool)
QSize minimumSizeHint() const override
\reimp
void mouseMoveEvent(QMouseEvent *) override
\reimp
void paintEvent(QPaintEvent *) override
\reimp
~QPushButton()
Destroys the push button.
void setFlat(bool)
virtual void initStyleOption(QStyleOptionButton *option) const
Initialize option with the values from this QPushButton.
void focusInEvent(QFocusEvent *) override
\reimp
bool flat
whether the button border is raised
Definition qpushbutton.h:25
void setAutoDefault(bool)
QPushButton(QWidget *parent=nullptr)
Constructs a push button with no text and a parent.
QSize sizeHint() const override
\reimp
bool isDefault() const
void focusOutEvent(QFocusEvent *) override
\reimp
bool event(QEvent *e) override
\reimp
bool isFlat() const
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:182
constexpr void setSize(const QSize &s) noexcept
Sets the size of the rectangle to the given size.
Definition qrect.h:387
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:185
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:188
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:179
QPointF position() const
Returns the position of the point in this event, relative to the widget or item that received the eve...
Definition qevent.h:119
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\variable QStyleOptionHeaderV2::textElideMode
The QStylePainter class is a convenience class for drawing QStyle elements inside a widget.
@ State_MouseOver
Definition qstyle.h:80
@ State_Sunken
Definition qstyle.h:69
@ State_On
Definition qstyle.h:72
@ State_Raised
Definition qstyle.h:68
@ CT_PushButton
Definition qstyle.h:547
virtual QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *w=nullptr) const =0
Returns the size of the element described by the specified option and type, based on the provided con...
@ SH_DialogButtonBox_ButtonsHaveIcons
Definition qstyle.h:656
virtual int styleHint(StyleHint stylehint, const QStyleOption *opt=nullptr, const QWidget *widget=nullptr, QStyleHintReturn *returnData=nullptr) const =0
Returns an integer representing the specified style hint for the given widget described by the provid...
@ CE_PushButton
Definition qstyle.h:171
virtual QRect subElementRect(SubElement subElement, const QStyleOption *option, const QWidget *widget=nullptr) const =0
Returns the sub-area for the given element as described in the provided style option.
@ PM_MenuButtonIndicator
Definition qstyle.h:416
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option=nullptr, const QWidget *widget=nullptr) const =0
Returns the value of the given pixel metric.
@ SE_PushButtonLayoutItem
Definition qstyle.h:294
@ SE_PushButtonBevel
Definition qstyle.h:320
The QToolBar class provides a movable panel that contains a set of controls.
Definition qtoolbar.h:23
The QWidgetItem class is a layout item that represents a widget.
Definition qlayoutitem.h:86
void setLayoutItemMargins(int left, int top, int right, int bottom)
static QRect availableScreenGeometry(const QWidget *widget)
Definition qwidget_p.h:474
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
QWidget * window() const
Returns the window for this widget, i.e.
Definition qwidget.cpp:4313
void updateGeometry()
Notifies the layout system that this widget has changed and may need to change geometry.
bool hasMouseTracking() const
Definition qwidget.h:856
QPoint pos
the position of the widget within its parent widget
Definition qwidget.h:111
QFontMetrics fontMetrics() const
Returns the font metrics for the widget's current font.
Definition qwidget.h:847
QRect rect
the internal geometry of the widget excluding any window frame
Definition qwidget.h:116
void ensurePolished() const
Ensures that the widget and its children have been polished by QStyle (i.e., have a proper font and p...
void update()
Updates the widget unless updates are disabled or the widget is hidden.
QStyle * style() const
Definition qwidget.cpp:2600
bool underMouse() const
Returns true if the widget is under the mouse cursor; otherwise returns false.
Definition qwidget.h:859
QWidget * parentWidget() const
Returns the parent of this widget, or \nullptr if it does not have any parent widget.
Definition qwidget.h:904
void removeAction(QAction *action)
Removes the action action from this widget's list of actions.
Definition qwidget.cpp:3186
void addAction(QAction *action)
Appends the action action to this widget's list of actions.
Definition qwidget.cpp:3117
bool testAttribute(Qt::WidgetAttribute) const
Returns true if attribute attribute is set on this widget; otherwise returns false.
Definition qwidget.h:910
QString text
rect
[4]
QStyleOptionButton opt
else opt state
[0]
Combined button and popup list for selecting options.
@ WA_Hover
Definition qnamespace.h:340
@ WA_MacShowFocusRect
Definition qnamespace.h:359
@ RightToLeft
@ Vertical
Definition qnamespace.h:100
@ TextShowMnemonic
Definition qnamespace.h:173
@ Key_Return
Definition qnamespace.h:667
@ Key_Enter
Definition qnamespace.h:668
@ SingleShotConnection
@ UniqueConnection
@ PopupFocusReason
#define Q_FALLTHROUGH()
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLboolean enable
GLint y
GLfloat GLfloat GLfloat GLfloat h
struct _cl_event * event
GLdouble s
[6]
Definition qopenglext.h:235
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLfloat GLfloat p
[1]
GLuint GLenum option
#define QStringLiteral(str)
unsigned int uint
Definition qtypes.h:34
QFileDialog dialog(this)
[1]
QGraphicsItem * item
QMenu menu
[5]