8#include <private/qdialog_p.h>
24#if QT_CONFIG(dialogbuttonbox)
25#include "qdialogbuttonbox.h"
28#if QT_CONFIG(accessibility)
29#include "qaccessible.h"
34#include "private/qmenu_p.h"
36#include "private/qpushbutton_p.h"
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
192
193
194
195
196
197
198
199
202
203
205QPushButton::QPushButton(QWidget *parent)
206 : QAbstractButton(*
new QPushButtonPrivate, parent)
213
214
215
217QPushButton::QPushButton(
const QString &text, QWidget *parent)
218 : QPushButton(parent)
225
226
227
228
229
230
231QPushButton::QPushButton(
const QIcon& icon,
const QString &text, QWidget *parent)
232 : QPushButton(*
new QPushButtonPrivate, parent)
239
240QPushButton::QPushButton(QPushButtonPrivate &dd, QWidget *parent)
241 : QAbstractButton(dd, parent)
248
249
250QPushButton::~QPushButton()
255QDialog *QPushButtonPrivate::dialogParent()
const
257 Q_Q(
const QPushButton);
258 const QWidget *p = q;
259 while (p && !p->isWindow()) {
260 p = p->parentWidget();
261 if (
const QDialog *dialog = qobject_cast<
const QDialog *>(p))
262 return const_cast<QDialog *>(dialog);
269
270
271
272
273
274
275void QPushButton::initStyleOption(QStyleOptionButton *option)
const
280 Q_D(
const QPushButton);
281 option->initFrom(
this);
282 option->features = QStyleOptionButton::None;
284 option->features |= QStyleOptionButton::Flat;
287 option->features |= QStyleOptionButton::HasMenu;
290 option->features |= QStyleOptionButton::AutoDefaultButton;
291 if (d->defaultButton)
292 option->features |= QStyleOptionButton::DefaultButton;
293 if (d->down || d->menuOpen)
294 option->state |= QStyle::State_Sunken;
296 option->state |= QStyle::State_On;
297 if (!d->flat && !d->down)
298 option->state |= QStyle::State_Raised;
299 if (underMouse() && hasMouseTracking())
300 option->state.setFlag(QStyle::State_MouseOver, d->hovering);
301 option->text = d->text;
302 option->icon = d->icon;
303 option->iconSize = iconSize();
306void QPushButton::setAutoDefault(
bool enable)
309 uint state = enable ? QPushButtonPrivate::On : QPushButtonPrivate::Off;
310 if (d->autoDefault != QPushButtonPrivate::Auto && d->autoDefault == state)
312 d->autoDefault = state;
313 d->sizeHint = QSize();
318bool QPushButton::autoDefault()
const
320 Q_D(
const QPushButton);
321 if (d->autoDefault == QPushButtonPrivate::Auto)
322 return ( d->dialogParent() !=
nullptr );
323 return d->autoDefault;
326void QPushButton::setDefault(
bool enable)
329 if (d->defaultButton == enable)
331 d->defaultButton = enable;
333 if (d->defaultButton) {
334 if (QDialog *dlg = d->dialogParent())
335 dlg->d_func()->setMainDefault(
this);
339#if QT_CONFIG(accessibility)
340 QAccessible::State s;
341 s.defaultButton =
true;
342 QAccessibleStateChangeEvent event(
this, s);
343 QAccessible::updateAccessibility(&event);
347bool QPushButton::isDefault()
const
349 Q_D(
const QPushButton);
350 return d->defaultButton;
354
355
356QSize QPushButton::sizeHint()
const
358 Q_D(
const QPushButton);
359 if (d->sizeHint.isValid() && d->lastAutoDefault == autoDefault())
361 d->lastAutoDefault = autoDefault();
366 QStyleOptionButton opt;
367 initStyleOption(&opt);
370#if !defined(QT_NO_ICON) && QT_CONFIG(dialogbuttonbox)
371 bool showButtonBoxIcons = qobject_cast<QDialogButtonBox*>(parentWidget())
372 && style()->styleHint(QStyle::SH_DialogButtonBox_ButtonsHaveIcons,
nullptr,
this);
374 if (!icon().isNull() || showButtonBoxIcons) {
375 int ih = opt.iconSize.height();
376 int iw = opt.iconSize.width() + 4;
382 bool empty = s.isEmpty();
384 s = QStringLiteral(
"XXXX");
385 QFontMetrics fm = fontMetrics();
386 QSize sz = fm.size(Qt::TextShowMnemonic, s);
390 h = qMax(h, sz.height());
391 opt.rect.setSize(QSize(w, h));
394 w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt,
this);
396 d->sizeHint = style()->sizeFromContents(QStyle::CT_PushButton, &opt, QSize(w, h),
this);
401
402
403QSize QPushButton::minimumSizeHint()
const
410
411void QPushButton::paintEvent(QPaintEvent *)
413 QStylePainter p(
this);
414 QStyleOptionButton option;
415 initStyleOption(&option);
416 p.drawControl(QStyle::CE_PushButton, option);
421void QPushButton::keyPressEvent(QKeyEvent *e)
427 if (autoDefault() || d->defaultButton) {
433 QAbstractButton::keyPressEvent(e);
438
439
440void QPushButton::focusInEvent(QFocusEvent *e)
443 if (e->reason() != Qt::PopupFocusReason && autoDefault() && !d->defaultButton) {
444 d->defaultButton =
true;
446 QDialog *dlg = qobject_cast<QDialog*>(window());
448 dlg->d_func()->setDefault(
this);
451 QAbstractButton::focusInEvent(e);
455
456
457void QPushButton::focusOutEvent(QFocusEvent *e)
460 if (e->reason() != Qt::PopupFocusReason && autoDefault() && d->defaultButton) {
462 QDialog *dlg = qobject_cast<QDialog*>(window());
464 dlg->d_func()->setDefault(
nullptr);
466 d->defaultButton =
false;
470 QAbstractButton::focusOutEvent(e);
472 if (d->menu && d->menu->isVisible())
478
479
480void QPushButton::mouseMoveEvent(QMouseEvent *e)
484 if (testAttribute(Qt::WA_Hover)) {
487 hit = hitButton(e->position().toPoint());
489 if (hit != d->hovering) {
495 QAbstractButton::mouseMoveEvent(e);
499
500
501bool QPushButton::hitButton(
const QPoint &pos)
const
503 QStyleOptionButton option;
504 initStyleOption(&option);
505 const QRect bevel = style()->subElementRect(QStyle::SE_PushButtonBevel, &option,
this);
506 return bevel.contains(pos);
511
512
513
514
515
516
517
518
519
520
521
522
523
524void QPushButton::setMenu(QMenu* menu)
530 if (menu && !d->menu) {
531 QObjectPrivate::connect(
this, &QPushButton::pressed,
532 d, &QPushButtonPrivate::popupPressed, Qt::UniqueConnection);
535 removeAction(d->menu->menuAction());
538 addAction(d->menu->menuAction());
540 d->resetLayoutItemMargins();
541 d->sizeHint = QSize();
547
548
549
550
551
552QMenu* QPushButton::menu()
const
554 Q_D(
const QPushButton);
559
560
561
562
563void QPushButton::showMenu()
572void QPushButtonPrivate::popupPressed()
578 menu->setNoReplayFor(q);
580 QPoint menuPos = adjustedMenuPosition();
582 QMenuPrivate::get(menu)->causedPopup.widget = q;
587 QObject::connect(menu, &QMenu::aboutToHide,
588 q, [q,
this]{ menuOpen =
false; q->setDown(
false); }, Qt::SingleShotConnection);
589 menu->popup(menuPos);
592QPoint QPushButtonPrivate::adjustedMenuPosition()
596 bool horizontal =
true;
597#if QT_CONFIG(toolbar)
598 QToolBar *tb = qobject_cast<QToolBar*>(parent);
599 if (tb && tb->orientation() == Qt::Vertical)
604 QRect rect = item.geometry();
605 rect.setRect(rect.x() - q->x(), rect.y() - q->y(), rect.width(), rect.height());
607 QSize menuSize = menu->sizeHint();
608 QPoint globalPos = q->mapToGlobal(rect.topLeft());
609 int x = globalPos.x();
610 int y = globalPos.y();
611 const QRect availableGeometry = QWidgetPrivate::availableScreenGeometry(q, q->mapToGlobal(rect.center()));
613 if (globalPos.y() + rect.height() + menuSize.height() <= availableGeometry.bottom()) {
615 }
else if (globalPos.y() - menuSize.height() >= availableGeometry.y()) {
616 y -= menuSize.height();
618 if (q->layoutDirection() == Qt::RightToLeft)
619 x += rect.width() - menuSize.width();
621 if (globalPos.x() + rect.width() + menu->sizeHint().width() <= availableGeometry.right()) {
623 }
else if (globalPos.x() - menuSize.width() >= availableGeometry.x()) {
624 x -= menuSize.width();
633void QPushButtonPrivate::init()
636 q->setAttribute(Qt::WA_MacShowFocusRect);
637 resetLayoutItemMargins();
640void QPushButtonPrivate::resetLayoutItemMargins()
643 QStyleOptionButton opt;
644 q->initStyleOption(&opt);
645 setLayoutItemMargins(QStyle::SE_PushButtonLayoutItem, &opt);
648void QPushButton::setFlat(
bool flat)
654 d->resetLayoutItemMargins();
655 d->sizeHint = QSize();
660bool QPushButton::isFlat()
const
662 Q_D(
const QPushButton);
667bool QPushButton::event(QEvent *e)
670 if (e->type() == QEvent::ParentChange) {
672 if (QDialog *dialog = d->dialogParent()) {
673 if (d->defaultButton)
674 dialog->d_func()->setMainDefault(
this);
677 }
else if (e->type() == QEvent::StyleChange
679 || e->type() == QEvent::MacSizeChange
682 d->resetLayoutItemMargins();
684 }
else if (e->type() == QEvent::PolishRequest) {
687 return QAbstractButton::event(e);
692#include "moc_qpushbutton.cpp"