Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickabstractbutton.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 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// Qt-Security score:significant reason:default
4
13#include "qquickicon_p_p.h"
16
17#include <QtCore/qloggingcategory.h>
18#include <QtGui/qstylehints.h>
19#include <QtGui/qguiapplication.h>
20#if QT_CONFIG(shortcut)
21# include <QtGui/private/qshortcutmap_p.h>
22#endif
23#if QT_CONFIG(accessibility)
24#include <QtGui/private/qaccessiblehelper_p.h>
25#endif
26#include <QtGui/private/qguiapplication_p.h>
27#include <QtGui/qpa/qplatformtheme.h>
28#include <QtQuick/private/qquickevents_p_p.h>
29#include <QtQuick/private/qquickevents_p_p.h>
30#include <QtQuick/private/qquickaccessibleattached_p.h>
31#include <QtQml/qqmllist.h>
32
34
35Q_STATIC_LOGGING_CATEGORY(lcAction, "qt.quick.controls.abstractbutton.action")
36
37/*!
38 \qmltype AbstractButton
39 \inherits Control
40//! \nativetype QQuickAbstractButton
41 \inqmlmodule QtQuick.Controls
42 \since 5.7
43 \ingroup qtquickcontrols-buttons
44 \brief Abstract base type providing functionality common to buttons.
45
46 AbstractButton provides the interface for controls with button-like
47 behavior; for example, push buttons and checkable controls like
48 radio buttons and check boxes. As an abstract control, it has no delegate
49 implementations, leaving them to the types that derive from it.
50
51 \sa ButtonGroup, {Button Controls}
52*/
53
54/*!
55 \qmlsignal QtQuick.Controls::AbstractButton::pressed()
56
57 This signal is emitted when the button is interactively pressed by the user via touch, mouse, or keyboard.
58*/
59
60/*!
61 \qmlsignal QtQuick.Controls::AbstractButton::released()
62
63 This signal is emitted when the button is interactively released by the user via touch, mouse, or keyboard.
64*/
65
66/*!
67 \qmlsignal QtQuick.Controls::AbstractButton::canceled()
68
69 This signal is emitted when the button loses mouse grab
70 while being pressed, or when it would emit the \l released
71 signal but the mouse cursor is not inside the button.
72*/
73
74/*!
75 \qmlsignal QtQuick.Controls::AbstractButton::clicked()
76
77 This signal is emitted when the button is interactively clicked by the user via touch, mouse, or keyboard.
78
79 \sa click(), animateClick(), {Call a C++ function from QML when a Button is clicked}
80*/
81
82/*!
83 \since QtQuick.Controls 2.2 (Qt 5.9)
84 \qmlsignal QtQuick.Controls::AbstractButton::toggled()
85
86 This signal is emitted when a checkable button is interactively toggled by the user via touch, mouse, or keyboard.
87*/
88
89/*!
90 \qmlsignal QtQuick.Controls::AbstractButton::pressAndHold()
91
92 This signal is emitted when the button is interactively pressed and held down by the user via touch or mouse.
93 It is not emitted when \l autoRepeat is enabled.
94*/
95
96/*!
97 \qmlsignal QtQuick.Controls::AbstractButton::doubleClicked()
98
99 This signal is emitted when the button is interactively double clicked by the user via touch or mouse.
100*/
101
102void QQuickAbstractButtonPrivate::init()
103{
104 Q_Q(QQuickAbstractButton);
105 q->setActiveFocusOnTab(true);
106#ifdef Q_OS_MACOS
107 q->setFocusPolicy(Qt::TabFocus);
108#else
109 q->setFocusPolicy(Qt::StrongFocus);
110#endif
111 q->setAcceptedMouseButtons(Qt::LeftButton);
112#if QT_CONFIG(quicktemplates2_multitouch)
113 q->setAcceptTouchEvents(true);
114#endif
115#if QT_CONFIG(cursor)
116 q->setCursor(Qt::ArrowCursor);
117#endif
118 setSizePolicy(QLayoutPolicy::Preferred, QLayoutPolicy::Fixed);
119}
120
121QPointF QQuickAbstractButtonPrivate::centerPressPoint() const
122{
123 return QPointF(qRound(width / 2), qRound(height / 2));
124}
125
126void QQuickAbstractButtonPrivate::setPressPoint(const QPointF &point)
127{
128 pressPoint = point;
129 setMovePoint(point);
130}
131
132void QQuickAbstractButtonPrivate::setMovePoint(const QPointF &point)
133{
134 Q_Q(QQuickAbstractButton);
135 bool xChange = !qFuzzyCompare(point.x(), movePoint.x());
136 bool yChange = !qFuzzyCompare(point.y(), movePoint.y());
137 movePoint = point;
138 if (xChange)
139 emit q->pressXChanged();
140 if (yChange)
141 emit q->pressYChanged();
142}
143
144bool QQuickAbstractButtonPrivate::handlePress(const QPointF &point, ulong timestamp)
145{
146 Q_Q(QQuickAbstractButton);
147 if (pressed)
148 return true;
149 QQuickControlPrivate::handlePress(point, timestamp);
150 setPressPoint(point);
151 q->setPressed(true);
152
153 emit q->pressed();
154
155 if (autoRepeat)
156 startRepeatDelay();
157 else if (touchId != -1 || Qt::LeftButton == (pressButtons & Qt::LeftButton))
158 startPressAndHold();
159 else
160 stopPressAndHold();
161
162 // Tool tips on desktop should hide when their parent item is pressed.
163 if (touchId == -1)
164 QQuickToolTipAttachedPrivate::maybeSetVisibleImplicitly(q, false);
165
166 return true;
167}
168
169bool QQuickAbstractButtonPrivate::handleMove(const QPointF &point, ulong timestamp)
170{
171 Q_Q(QQuickAbstractButton);
172 QQuickControlPrivate::handleMove(point, timestamp);
173 setMovePoint(point);
174 q->setPressed(keepPressed || q->contains(point));
175
176 if (!pressed && autoRepeat)
177 stopPressRepeat();
178 else if (holdTimer > 0 && (!pressed || QLineF(pressPoint, point).length() > QGuiApplication::styleHints()->startDragDistance()))
179 stopPressAndHold();
180 return true;
181}
182
183bool QQuickAbstractButtonPrivate::handleRelease(const QPointF &point, ulong timestamp)
184{
185 Q_Q(QQuickAbstractButton);
186 // Store this here since the base class' handleRelease clears it.
187 const int pressTouchId = touchId;
188
189 QQuickControlPrivate::handleRelease(point, timestamp);
190 bool wasPressed = pressed;
191 setPressPoint(point);
192 q->setPressed(false);
193 pressButtons = Qt::NoButton;
194
195 const bool touchDoubleClick = pressTouchId != -1 && lastTouchReleaseTimestamp != 0
196 && QQuickDeliveryAgentPrivate::isWithinDoubleClickInterval(timestamp - lastTouchReleaseTimestamp)
197 && isDoubleClickConnected();
198
199 if (!wasHeld && wasPressed && (keepPressed || q->contains(point)))
200 q->nextCheckState();
201
202 if (wasPressed) {
203 if (wasHeld && pressTouchId != -1) {
204 // We were potentially showing a tool tip on long press; if we were, hide it now that
205 // we're no longer pressed.
206 QQuickToolTipAttachedPrivate::maybeSetVisibleImplicitly(q, false);
207 }
208
209 emit q->released();
210 if (!wasHeld && !wasDoubleClick)
211 trigger(touchDoubleClick);
212 } else {
213 emit q->canceled();
214 }
215
216 if (autoRepeat)
217 stopPressRepeat();
218 else
219 stopPressAndHold();
220
221 if (!touchDoubleClick) {
222 // This is not a double click yet, but it is potentially the
223 // first release before a double click.
224 if (pressTouchId != -1) {
225 // The corresponding press for this release was a touch press.
226 // Keep track of the timestamp of the release so that we can
227 // emit doubleClicked() if another one comes afterwards.
228 lastTouchReleaseTimestamp = timestamp;
229 }
230 } else {
231 // We just did a double click, so clear the release timestamp
232 // to prepare for any possible future double clicks.
233 lastTouchReleaseTimestamp = 0;
234 }
235
236 wasDoubleClick = false;
237 return true;
238}
239
240void QQuickAbstractButtonPrivate::handleUngrab()
241{
242 Q_Q(QQuickAbstractButton);
243 QQuickControlPrivate::handleUngrab();
244 pressButtons = Qt::NoButton;
245 if (!pressed)
246 return;
247
248 q->setPressed(false);
249 stopPressRepeat();
250 stopPressAndHold();
251 wasDoubleClick = false;
252 lastTouchReleaseTimestamp = 0;
253 emit q->canceled();
254}
255
256bool QQuickAbstractButtonPrivate::acceptKeyClick(Qt::Key key) const
257{
258 const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::ButtonPressKeys).value<QList<Qt::Key>>();
259 return buttonPressKeys.contains(key);
260}
261
262bool QQuickAbstractButtonPrivate::isPressAndHoldConnected()
263{
264 Q_Q(QQuickAbstractButton);
265 static const QMetaMethod method = [&]() {
266 const auto signal = &QQuickAbstractButton::pressAndHold;
267 return QMetaMethod::fromSignal(signal);
268 }();
269 return q->isSignalConnected(method);
270}
271
272bool QQuickAbstractButtonPrivate::isDoubleClickConnected()
273{
274 Q_Q(QQuickAbstractButton);
275 static const QMetaMethod method = [&]() {
276 const auto signal = &QQuickAbstractButton::doubleClicked;
277 return QMetaMethod::fromSignal(signal);
278 }();
279 return q->isSignalConnected(method);
280}
281
282void QQuickAbstractButtonPrivate::startPressAndHold()
283{
284 Q_Q(QQuickAbstractButton);
285 wasHeld = false;
286 stopPressAndHold();
287 if (isPressAndHoldConnected())
288 holdTimer = q->startTimer(QGuiApplication::styleHints()->mousePressAndHoldInterval());
289}
290
291void QQuickAbstractButtonPrivate::stopPressAndHold()
292{
293 Q_Q(QQuickAbstractButton);
294 if (holdTimer > 0) {
295 q->killTimer(holdTimer);
296 holdTimer = 0;
297 }
298}
299
300void QQuickAbstractButtonPrivate::startRepeatDelay()
301{
302 Q_Q(QQuickAbstractButton);
303 stopPressRepeat();
304 delayTimer = q->startTimer(repeatDelay);
305}
306
307void QQuickAbstractButtonPrivate::startPressRepeat()
308{
309 Q_Q(QQuickAbstractButton);
310 stopPressRepeat();
311 repeatTimer = q->startTimer(repeatInterval);
312}
313
314void QQuickAbstractButtonPrivate::stopPressRepeat()
315{
316 Q_Q(QQuickAbstractButton);
317 if (delayTimer > 0) {
318 q->killTimer(delayTimer);
319 delayTimer = 0;
320 }
321 if (repeatTimer > 0) {
322 q->killTimer(repeatTimer);
323 repeatTimer = 0;
324 }
325}
326
327#if QT_CONFIG(shortcut)
328void QQuickAbstractButtonPrivate::grabShortcut()
329{
330 Q_Q(QQuickAbstractButton);
331 if (shortcut.isEmpty())
332 return;
333
334 shortcutId = QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(q, shortcut, Qt::WindowShortcut, QQuickShortcutContext::matcher);
335
336 if (!q->isEnabled())
337 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(false, shortcutId, q);
338}
339
340void QQuickAbstractButtonPrivate::ungrabShortcut()
341{
342 Q_Q(QQuickAbstractButton);
343 if (!shortcutId)
344 return;
345
346 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(shortcutId, q);
347 shortcutId = 0;
348}
349#endif
350
351void QQuickAbstractButtonPrivate::actionTextChange()
352{
353 Q_Q(QQuickAbstractButton);
354 if (explicitText)
355 return;
356
357 q->buttonChange(QQuickAbstractButton::ButtonTextChange);
358}
359
360void QQuickAbstractButtonPrivate::setText(const QString &newText, QQml::PropertyUtils::State propertyState)
361{
362 Q_Q(QQuickAbstractButton);
363 const QString oldText = q->text();
364 explicitText = isExplicitlySet(propertyState);
365 text = newText;
366 if (oldText == q->text())
367 return;
368
369 q->buttonChange(QQuickAbstractButton::ButtonTextChange);
370}
371
372void QQuickAbstractButtonPrivate::updateEffectiveIcon()
373{
374 Q_Q(QQuickAbstractButton);
375 // We store effectiveIcon because we need to be able to tell if the icon has actually changed.
376 // If we only stored our icon and the action's icon, and resolved in the getter, we'd have
377 // no way of knowing what the old value was here. As an added benefit, we only resolve when
378 // something has changed, as opposed to doing it unconditionally in the icon() getter.
379 QQuickIcon newEffectiveIcon = action ? icon.resolve(action->icon()) : icon;
380
381 bool unchanged = newEffectiveIcon == effectiveIcon;
382 if (action) {
383 // We can't rely purely on QQuickIcon::operator== for our unchanged check, because it
384 // doesn't account for the color being resolved. QQuickIconLabelPrivate::syncImage and
385 // createImage rely on the color's resolve mask to determine if a color was set on it
386 // that should override the style default (see QQuickIconLabel::defaultIconColor for
387 // more info). If we didn't check the resolve mask
388 // and the user set the color to transparent (the default), the resolveMask of d->icon
389 // wouldn't indicate that the color was resolved and iconChanged wouldn't be emitted,
390 // leading to the user's request being ignored.
391 const bool actionIconColorResolved = QQuickIconPrivate::isResolved(action->icon(),
392 QQuickIconPrivate::ColorResolved);
393 const bool iconColorResolved = QQuickIconPrivate::isResolved(icon,
394 QQuickIconPrivate::ColorResolved);
395
396 unchanged = newEffectiveIcon == effectiveIcon;
397
398 // Only set it to false if there was a change in icon color that would otherwise
399 // be undetectable.
400 if (unchanged && !iconColorResolved && actionIconColorResolved)
401 unchanged = false;
402
403 // We need to mark the effective icon's color as resolved, too.
404 if (actionIconColorResolved)
405 newEffectiveIcon.resolveColor();
406 }
407
408 // Always update effectiveIcon because the color may have been resolved in icon,
409 // which isn't accounted for QQuickIcon::operator==.
410 effectiveIcon = newEffectiveIcon;
411
412 if (unchanged)
413 return;
414
415 if (action && !QQuickIconPrivate::isResolved(effectiveIcon, QQuickIconPrivate::ColorResolved)) {
416 // A color wasn't set on the button's icon (which should always win over an Action's).
417 if (QQuickIconPrivate::isResolved(action->icon(), QQuickIconPrivate::ColorResolved)) {
418 // A color was set on the action's icon; mark the effective icon's color as being
419 // explicitly set so that QQuickIconLabel can detect that it's set and respect it.
420 effectiveIcon.resolveColor();
421 }
422 }
423
424 emit q->iconChanged();
425}
426
427void QQuickAbstractButtonPrivate::click()
428{
429 Q_Q(QQuickAbstractButton);
430 if (effectiveEnable)
431 emit q->clicked();
432}
433
434void QQuickAbstractButtonPrivate::accessiblePressAction()
435{
436 trigger();
437}
438
439void QQuickAbstractButtonPrivate::trigger(bool doubleClick)
440{
441 Q_Q(QQuickAbstractButton);
442 const bool wasEnabled = effectiveEnable;
443 if (action && action->isEnabled())
444 QQuickActionPrivate::get(action)->trigger(q, false);
445 if (wasEnabled && (!action || !action->isEnabled())) {
446 if (!doubleClick)
447 emit q->clicked();
448 else
449 emit q->doubleClicked();
450 }
451}
452
453void QQuickAbstractButtonPrivate::toggle(bool value)
454{
455 Q_Q(QQuickAbstractButton);
456 const bool wasChecked = checked;
457 q->setChecked(value);
458 if (wasChecked != checked)
459 emit q->toggled();
460}
461
462void QQuickAbstractButtonPrivate::cancelIndicator()
463{
464 Q_Q(QQuickAbstractButton);
465 quickCancelDeferred(q, indicatorName());
466}
467
468void QQuickAbstractButtonPrivate::executeIndicator(bool complete)
469{
470 Q_Q(QQuickAbstractButton);
471 if (indicator.wasExecuted())
472 return;
473
474 if (!indicator || complete)
475 quickBeginDeferred(q, indicatorName(), indicator);
476 if (complete)
477 quickCompleteDeferred(q, indicatorName(), indicator);
478}
479
480void QQuickAbstractButtonPrivate::itemImplicitWidthChanged(QQuickItem *item)
481{
482 Q_Q(QQuickAbstractButton);
483 QQuickControlPrivate::itemImplicitWidthChanged(item);
484 if (item == indicator)
485 emit q->implicitIndicatorWidthChanged();
486}
487
488void QQuickAbstractButtonPrivate::itemImplicitHeightChanged(QQuickItem *item)
489{
490 Q_Q(QQuickAbstractButton);
491 QQuickControlPrivate::itemImplicitHeightChanged(item);
492 if (item == indicator)
493 emit q->implicitIndicatorHeightChanged();
494}
495
496void QQuickAbstractButtonPrivate::itemDestroyed(QQuickItem *item)
497{
498 Q_Q(QQuickAbstractButton);
499 QQuickControlPrivate::itemDestroyed(item);
500 if (item == indicator) {
501 indicator = nullptr;
502 emit q->implicitIndicatorWidthChanged();
503 emit q->implicitIndicatorHeightChanged();
504 }
505}
506
507QQuickAbstractButton *QQuickAbstractButtonPrivate::findCheckedButton() const
508{
509 Q_Q(const QQuickAbstractButton);
510 if (group)
511 return group->checkedButton();
512
513 const QList<QQuickAbstractButton *> buttons = findExclusiveButtons();
514 // TODO: A singular QRadioButton can be unchecked, which seems logical,
515 // because there's nothing to be exclusive with. However, a RadioButton
516 // from QtQuick.Controls 1.x can never be unchecked, which is the behavior
517 // that QQuickRadioButton adopted. Uncommenting the following count check
518 // gives the QRadioButton behavior. Notice that tst_radiobutton.qml needs
519 // to be updated.
520 if (!autoExclusive /*|| buttons.count() == 1*/)
521 return nullptr;
522
523 for (QQuickAbstractButton *button : buttons) {
524 if (button->isChecked() && button != q)
525 return button;
526 }
527 return checked ? const_cast<QQuickAbstractButton *>(q) : nullptr;
528}
529
530QList<QQuickAbstractButton *> QQuickAbstractButtonPrivate::findExclusiveButtons() const
531{
532 QList<QQuickAbstractButton *> buttons;
533 if (group) {
534 QQmlListProperty<QQuickAbstractButton> groupButtons = group->buttons();
535 int count = groupButtons.count(&groupButtons);
536 for (int i = 0; i < count; ++i) {
537 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(groupButtons.at(&groupButtons, i));
538 if (button)
539 buttons += button;
540 }
541 } else if (parentItem) {
542 const auto childItems = parentItem->childItems();
543 for (QQuickItem *child : childItems) {
544 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(child);
545 if (button && button->autoExclusive() && !QQuickAbstractButtonPrivate::get(button)->group)
546 buttons += button;
547 }
548 }
549 return buttons;
550}
551
552QQuickAbstractButton::QQuickAbstractButton(QQuickItem *parent)
553 : QQuickControl(*(new QQuickAbstractButtonPrivate), parent)
554{
555 Q_D(QQuickAbstractButton);
556 d->init();
557}
558
559QQuickAbstractButton::QQuickAbstractButton(QQuickAbstractButtonPrivate &dd, QQuickItem *parent)
560 : QQuickControl(dd, parent)
561{
562 Q_D(QQuickAbstractButton);
563 d->init();
564}
565
566QQuickAbstractButton::~QQuickAbstractButton()
567{
568 Q_D(QQuickAbstractButton);
569 d->removeImplicitSizeListener(d->indicator);
570 if (d->group) {
571 auto *attached = qobject_cast<QQuickButtonGroupAttached *>(
572 qmlAttachedPropertiesObject<QQuickButtonGroup>(this, false));
573 if (attached)
574 attached->setGroup(nullptr);
575 else
576 d->group->removeButton(this);
577 }
578#if QT_CONFIG(shortcut)
579 d->ungrabShortcut();
580#endif
581}
582
583/*!
584 \qmlproperty string QtQuick.Controls::AbstractButton::text
585
586 This property holds a textual description of the button.
587
588 \note The text is used for accessibility purposes, so it makes sense to
589 set a textual description even if the content item is an image.
590
591 \sa icon, display, {Control::contentItem}{contentItem}
592*/
593QString QQuickAbstractButton::text() const
594{
595 Q_D(const QQuickAbstractButton);
596 return d->explicitText || !d->action ? d->text : d->action->text();
597}
598
599void QQuickAbstractButton::setText(const QString &text)
600{
601 Q_D(QQuickAbstractButton);
602 d->setText(text, QQml::PropertyUtils::State::ExplicitlySet);
603}
604
605void QQuickAbstractButton::resetText()
606{
607 Q_D(QQuickAbstractButton);
608 d->setText(QString(), QQml::PropertyUtils::State::ImplicitlySet);
609}
610
611/*!
612 \qmlproperty bool QtQuick.Controls::AbstractButton::down
613
614 This property holds whether the button is visually down.
615
616 Unless explicitly set, this property follows the value of \l pressed. To
617 return to the default value, set this property to \c undefined.
618
619 \sa pressed
620*/
621bool QQuickAbstractButton::isDown() const
622{
623 Q_D(const QQuickAbstractButton);
624 return d->down;
625}
626
627void QQuickAbstractButton::setDown(bool down)
628{
629 Q_D(QQuickAbstractButton);
630 d->explicitDown = true;
631
632 if (d->down == down)
633 return;
634
635 d->down = down;
636 emit downChanged();
637}
638
639void QQuickAbstractButton::resetDown()
640{
641 Q_D(QQuickAbstractButton);
642 if (!d->explicitDown)
643 return;
644
645 setDown(d->pressed);
646 d->explicitDown = false;
647}
648
649/*!
650 \qmlproperty bool QtQuick.Controls::AbstractButton::pressed
651 \readonly
652
653 This property holds whether the button is physically pressed. A button can
654 be pressed by either touch or key events.
655
656 \sa down
657*/
658bool QQuickAbstractButton::isPressed() const
659{
660 Q_D(const QQuickAbstractButton);
661 return d->pressed;
662}
663
664void QQuickAbstractButton::setPressed(bool isPressed)
665{
666 Q_D(QQuickAbstractButton);
667 if (d->pressed == isPressed)
668 return;
669
670 d->pressed = isPressed;
671 setAccessibleProperty("pressed", isPressed);
672 emit pressedChanged();
673 buttonChange(ButtonPressedChanged);
674
675 if (!d->explicitDown) {
676 setDown(d->pressed);
677 d->explicitDown = false;
678 }
679}
680
681/*!
682 \qmlproperty bool QtQuick.Controls::AbstractButton::checked
683
684 This property holds whether the button is checked.
685
686 Since Qt 6.2, setting this property no longer affects the
687 \l {AbstractButton::}{checkable} property. Explicitly set the
688 \c checkable property if needed.
689
690 \sa checkable
691*/
692bool QQuickAbstractButton::isChecked() const
693{
694 Q_D(const QQuickAbstractButton);
695 return d->checked;
696}
697
698void QQuickAbstractButton::setChecked(bool checked)
699{
700 Q_D(QQuickAbstractButton);
701 if (d->checked == checked)
702 return;
703
704 d->checked = checked;
705 if (d->action)
706 d->action->setChecked(checked);
707 setAccessibleProperty("checked", checked);
708 buttonChange(ButtonCheckedChange);
709 emit checkedChanged();
710}
711
712/*!
713 \qmlproperty bool QtQuick.Controls::AbstractButton::checkable
714
715 This property holds whether the button is checkable.
716
717 A checkable button toggles between checked (on) and unchecked (off) when
718 the user clicks on it or presses the space bar while the button has active
719 focus.
720
721 The default value is \c false.
722
723 \sa checked
724*/
725bool QQuickAbstractButton::isCheckable() const
726{
727 Q_D(const QQuickAbstractButton);
728 return d->checkable;
729}
730
731void QQuickAbstractButton::setCheckable(bool checkable)
732{
733 Q_D(QQuickAbstractButton);
734 if (d->checkable == checkable)
735 return;
736
737 d->checkable = checkable;
738 if (d->action)
739 d->action->setCheckable(checkable);
740 setAccessibleProperty("checkable", checkable);
741 buttonChange(ButtonCheckableChange);
742 emit checkableChanged();
743}
744
745/*!
746 \qmlproperty bool QtQuick.Controls::AbstractButton::autoExclusive
747
748 This property holds whether auto-exclusivity is enabled.
749
750 If auto-exclusivity is enabled, checkable buttons that belong to the same
751 parent item behave as if they were part of the same ButtonGroup. Only
752 one button can be checked at any time; checking another button automatically
753 unchecks the previously checked one.
754
755 \note The property has no effect on buttons that belong to a ButtonGroup.
756
757 RadioButton and TabButton are auto-exclusive by default.
758*/
759bool QQuickAbstractButton::autoExclusive() const
760{
761 Q_D(const QQuickAbstractButton);
762 return d->autoExclusive;
763}
764
765void QQuickAbstractButton::setAutoExclusive(bool exclusive)
766{
767 Q_D(QQuickAbstractButton);
768 if (d->autoExclusive == exclusive)
769 return;
770
771 d->autoExclusive = exclusive;
772 emit autoExclusiveChanged();
773}
774
775/*!
776 \qmlproperty bool QtQuick.Controls::AbstractButton::autoRepeat
777
778 This property holds whether the button repeats \l pressed(), \l released()
779 and \l clicked() signals while the button is pressed and held down.
780
781 If this property is set to \c true, the \l pressAndHold() signal will not
782 be emitted.
783
784 The default value is \c false.
785
786 The initial delay and the repetition interval are defined in milliseconds
787 by \l autoRepeatDelay and \l autoRepeatInterval.
788*/
789bool QQuickAbstractButton::autoRepeat() const
790{
791 Q_D(const QQuickAbstractButton);
792 return d->autoRepeat;
793}
794
795void QQuickAbstractButton::setAutoRepeat(bool repeat)
796{
797 Q_D(QQuickAbstractButton);
798 if (d->autoRepeat == repeat)
799 return;
800
801 d->stopPressRepeat();
802 d->autoRepeat = repeat;
803 emit autoRepeatChanged();
804}
805
806/*!
807 \qmlproperty Item QtQuick.Controls::AbstractButton::indicator
808
809 This property holds the indicator item.
810*/
811QQuickItem *QQuickAbstractButton::indicator() const
812{
813 QQuickAbstractButtonPrivate *d = const_cast<QQuickAbstractButtonPrivate *>(d_func());
814 if (!d->indicator)
815 d->executeIndicator();
816 return d->indicator;
817}
818
819void QQuickAbstractButton::setIndicator(QQuickItem *indicator)
820{
821 Q_D(QQuickAbstractButton);
822 if (d->indicator == indicator)
823 return;
824
825 QQuickControlPrivate::warnIfCustomizationNotSupported(this, indicator, QStringLiteral("indicator"));
826
827 if (!d->indicator.isExecuting())
828 d->cancelIndicator();
829
830 const qreal oldImplicitIndicatorWidth = implicitIndicatorWidth();
831 const qreal oldImplicitIndicatorHeight = implicitIndicatorHeight();
832
833 d->removeImplicitSizeListener(d->indicator);
834 QQuickControlPrivate::hideOldItem(d->indicator);
835 d->indicator = indicator;
836
837 if (indicator) {
838 if (!indicator->parentItem())
839 indicator->setParentItem(this);
840 indicator->setAcceptedMouseButtons(Qt::LeftButton);
841 d->addImplicitSizeListener(indicator);
842 }
843
844 if (!qFuzzyCompare(oldImplicitIndicatorWidth, implicitIndicatorWidth()))
845 emit implicitIndicatorWidthChanged();
846 if (!qFuzzyCompare(oldImplicitIndicatorHeight, implicitIndicatorHeight()))
847 emit implicitIndicatorHeightChanged();
848 if (!d->indicator.isExecuting())
849 emit indicatorChanged();
850}
851
852/*!
853 \qmlproperty string QtQuick.Controls::AbstractButton::icon.name
854 \qmlproperty url QtQuick.Controls::AbstractButton::icon.source
855 \qmlproperty int QtQuick.Controls::AbstractButton::icon.width
856 \qmlproperty int QtQuick.Controls::AbstractButton::icon.height
857 \qmlproperty color QtQuick.Controls::AbstractButton::icon.color
858 \qmlproperty bool QtQuick.Controls::AbstractButton::icon.cache
859
860 \since QtQuick.Controls 2.3
861
862 \include qquickicon.qdocinc grouped-properties
863
864 \sa text, display, {Icons in Qt Quick Controls}
865*/
866
867QQuickIcon QQuickAbstractButton::icon() const
868{
869 Q_D(const QQuickAbstractButton);
870 return d->effectiveIcon;
871}
872
873void QQuickAbstractButton::setIcon(const QQuickIcon &icon)
874{
875 Q_D(QQuickAbstractButton);
876 d->icon = icon;
877 d->icon.ensureRelativeSourceResolved(this);
878 d->updateEffectiveIcon();
879}
880
881/*!
882 \since QtQuick.Controls 2.3 (Qt 5.10)
883 \qmlproperty enumeration QtQuick.Controls::AbstractButton::display
884
885 This property determines how the \l icon and \l text are displayed within
886 the button.
887
888 \table
889 \header \li Display \li Result
890 \row \li \c AbstractButton.IconOnly
891 \li \image qtquickcontrols-button-icononly.png
892 {Button displaying only icon}
893 \row \li \c AbstractButton.TextOnly
894 \li \image qtquickcontrols-button-textonly.png
895 {Button displaying only text}
896 \row \li \c AbstractButton.TextBesideIcon (default)
897 \li \image qtquickcontrols-button-textbesideicon.png
898 {Button with text beside icon}
899 \row \li \c AbstractButton.TextUnderIcon
900 \li \image qtquickcontrols-button-textundericon.png
901 {Button with text under icon}
902 \endtable
903
904 \sa {Control::}{spacing}, {Control::}{padding}
905*/
906QQuickAbstractButton::Display QQuickAbstractButton::display() const
907{
908 Q_D(const QQuickAbstractButton);
909 return d->display;
910}
911
912void QQuickAbstractButton::setDisplay(Display display)
913{
914 Q_D(QQuickAbstractButton);
915 if (display == d->display)
916 return;
917
918 d->display = display;
919 emit displayChanged();
920}
921
922/*!
923 \since QtQuick.Controls 2.3 (Qt 5.10)
924 \qmlproperty Action QtQuick.Controls::AbstractButton::action
925
926 This property holds the button action.
927
928 \sa Action
929*/
930QQuickAction *QQuickAbstractButton::action() const
931{
932 Q_D(const QQuickAbstractButton);
933 return d->action;
934}
935
936void QQuickAbstractButton::setAction(QQuickAction *action)
937{
938 Q_D(QQuickAbstractButton);
939 qCDebug(lcAction) << this << "setAction called with" << action;
940 if (d->action == action)
941 return;
942
943 const QString oldText = text();
944
945 if (QQuickAction *oldAction = d->action.data()) {
946 QQuickActionPrivate::get(oldAction)->unregisterItem(this);
947 QObjectPrivate::disconnect(oldAction, &QQuickAction::triggered, d, &QQuickAbstractButtonPrivate::click);
948 QObjectPrivate::disconnect(oldAction, &QQuickAction::textChanged, d, &QQuickAbstractButtonPrivate::actionTextChange);
949
950 QObjectPrivate::disconnect(oldAction, &QQuickAction::iconChanged, d, &QQuickAbstractButtonPrivate::updateEffectiveIcon);
951 disconnect(oldAction, &QQuickAction::checkedChanged, this, &QQuickAbstractButton::setChecked);
952 disconnect(oldAction, &QQuickAction::checkableChanged, this, &QQuickAbstractButton::setCheckable);
953 disconnect(oldAction, &QQuickAction::enabledChanged, this, &QQuickItem::setEnabled);
954 }
955
956 if (action) {
957 QQuickActionPrivate::get(action)->registerItem(this);
958 QObjectPrivate::connect(action, &QQuickAction::triggered, d, &QQuickAbstractButtonPrivate::click);
959 QObjectPrivate::connect(action, &QQuickAction::textChanged, d, &QQuickAbstractButtonPrivate::actionTextChange);
960
961 QObjectPrivate::connect(action, &QQuickAction::iconChanged, d, &QQuickAbstractButtonPrivate::updateEffectiveIcon);
962 connect(action, &QQuickAction::checkedChanged, this, &QQuickAbstractButton::setChecked);
963 connect(action, &QQuickAction::checkableChanged, this, &QQuickAbstractButton::setCheckable);
964 connect(action, &QQuickAction::enabledChanged, this, &QQuickItem::setEnabled);
965
966 setChecked(action->isChecked());
967 setCheckable(action->isCheckable());
968 setEnabled(action->isEnabled());
969 }
970
971#if QT_CONFIG(accessibility)
972 auto attached = qobject_cast<QQuickAccessibleAttached*>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(this, true));
973 Q_ASSERT(attached);
974 attached->setProxying(qobject_cast<QQuickAccessibleAttached*>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(action, true)));
975#endif
976
977 d->action = action;
978
979 if (oldText != text())
980 buttonChange(ButtonTextChange);
981
982 d->updateEffectiveIcon();
983
984 emit actionChanged();
985}
986
987/*!
988 \since QtQuick.Controls 2.4 (Qt 5.11)
989 \qmlproperty int QtQuick.Controls::AbstractButton::autoRepeatDelay
990
991 This property holds the initial delay of auto-repetition in milliseconds.
992 The default value is \c 300 ms.
993
994 \sa autoRepeat, autoRepeatInterval
995*/
996int QQuickAbstractButton::autoRepeatDelay() const
997{
998 Q_D(const QQuickAbstractButton);
999 return d->repeatDelay;
1000}
1001
1002void QQuickAbstractButton::setAutoRepeatDelay(int delay)
1003{
1004 Q_D(QQuickAbstractButton);
1005 if (d->repeatDelay == delay)
1006 return;
1007
1008 d->repeatDelay = delay;
1009 emit autoRepeatDelayChanged();
1010}
1011
1012/*!
1013 \since QtQuick.Controls 2.4 (Qt 5.11)
1014 \qmlproperty int QtQuick.Controls::AbstractButton::autoRepeatInterval
1015
1016 This property holds the interval of auto-repetition in milliseconds.
1017 The default value is \c 100 ms.
1018
1019 \sa autoRepeat, autoRepeatDelay
1020*/
1021int QQuickAbstractButton::autoRepeatInterval() const
1022{
1023 Q_D(const QQuickAbstractButton);
1024 return d->repeatInterval;
1025}
1026
1027void QQuickAbstractButton::setAutoRepeatInterval(int interval)
1028{
1029 Q_D(QQuickAbstractButton);
1030 if (d->repeatInterval == interval)
1031 return;
1032
1033 d->repeatInterval = interval;
1034 emit autoRepeatIntervalChanged();
1035}
1036
1037#if QT_CONFIG(shortcut)
1038/*!
1039 \internal
1040
1041 This is the mnemonic shortcut that is derived from the text;
1042 see \c QQuickAbstractButton::buttonChange().
1043*/
1044QKeySequence QQuickAbstractButton::shortcut() const
1045{
1046 Q_D(const QQuickAbstractButton);
1047 return d->shortcut;
1048}
1049
1050void QQuickAbstractButton::setShortcut(const QKeySequence &shortcut)
1051{
1052 Q_D(QQuickAbstractButton);
1053 if (d->shortcut == shortcut)
1054 return;
1055
1056 d->ungrabShortcut();
1057 d->shortcut = shortcut;
1058 if (isVisible())
1059 d->grabShortcut();
1060}
1061#endif
1062
1063/*!
1064 \readonly
1065 \since QtQuick.Controls 2.4 (Qt 5.11)
1066 \qmlproperty real QtQuick.Controls::AbstractButton::pressX
1067
1068 This property holds the x-coordinate of the last press.
1069
1070 \note The value is updated on touch moves, but left intact after touch release.
1071
1072 \sa pressY
1073*/
1074qreal QQuickAbstractButton::pressX() const
1075{
1076 Q_D(const QQuickAbstractButton);
1077 return d->movePoint.x();
1078}
1079
1080/*!
1081 \readonly
1082 \since QtQuick.Controls 2.4 (Qt 5.11)
1083 \qmlproperty real QtQuick.Controls::AbstractButton::pressY
1084
1085 This property holds the y-coordinate of the last press.
1086
1087 \note The value is updated on touch moves, but left intact after touch release.
1088
1089 \sa pressX
1090*/
1091qreal QQuickAbstractButton::pressY() const
1092{
1093 Q_D(const QQuickAbstractButton);
1094 return d->movePoint.y();
1095}
1096
1097/*!
1098 \since QtQuick.Controls 2.5 (Qt 5.12)
1099 \qmlproperty real QtQuick.Controls::AbstractButton::implicitIndicatorWidth
1100 \readonly
1101
1102 This property holds the implicit indicator width.
1103
1104 The value is equal to \c {indicator ? indicator.implicitWidth : 0}.
1105
1106 This is typically used, together with \l {Control::}{implicitContentWidth} and
1107 \l {Control::}{implicitBackgroundWidth}, to calculate the \l {Item::}{implicitWidth}.
1108
1109 \sa implicitIndicatorHeight
1110*/
1111qreal QQuickAbstractButton::implicitIndicatorWidth() const
1112{
1113 Q_D(const QQuickAbstractButton);
1114 if (!d->indicator)
1115 return 0;
1116 return d->indicator->implicitWidth();
1117}
1118
1119/*!
1120 \since QtQuick.Controls 2.5 (Qt 5.12)
1121 \qmlproperty real QtQuick.Controls::AbstractButton::implicitIndicatorHeight
1122 \readonly
1123
1124 This property holds the implicit indicator height.
1125
1126 The value is equal to \c {indicator ? indicator.implicitHeight : 0}.
1127
1128 This is typically used, together with \l {Control::}{implicitContentHeight} and
1129 \l {Control::}{implicitBackgroundHeight}, to calculate the \l {Item::}{implicitHeight}.
1130
1131 \sa implicitIndicatorWidth
1132*/
1133qreal QQuickAbstractButton::implicitIndicatorHeight() const
1134{
1135 Q_D(const QQuickAbstractButton);
1136 if (!d->indicator)
1137 return 0;
1138 return d->indicator->implicitHeight();
1139}
1140
1141/*!
1142 \qmlmethod void QtQuick.Controls::AbstractButton::toggle()
1143
1144 Toggles the checked state of the button.
1145
1146 \sa click(), animateClick()
1147*/
1148void QQuickAbstractButton::toggle()
1149{
1150 Q_D(QQuickAbstractButton);
1151 setChecked(!d->checked);
1152}
1153
1154/*!
1155 \since Qt 6.8
1156 \qmlmethod void QtQuick.Controls::AbstractButton::click()
1157
1158 Simulates the button being clicked with no delay between press and release.
1159
1160 All signals associated with a click are emitted as appropriate.
1161
1162 If the \l [QML] {Item::} {focusPolicy} includes \c Qt.ClickFocus,
1163 \l [QML] {Item::} {activeFocus} will become \c true.
1164
1165 This function does nothing if the button is
1166 \l [QML] {Item::enabled} {disabled}.
1167
1168 Calling this function again before the button is released resets
1169 the release timer.
1170
1171 \sa animateClick(), pressed(), released(), clicked()
1172*/
1173void QQuickAbstractButton::click()
1174{
1175 Q_D(QQuickAbstractButton);
1176 if (!isEnabled())
1177 return;
1178
1179 // QQuickItemPrivate::deliverPointerEvent calls setFocusIfNeeded on real clicks,
1180 // so we need to do it ourselves.
1181 const bool setFocusOnPress = !QGuiApplication::styleHints()->setFocusOnTouchRelease();
1182 if (setFocusOnPress && focusPolicy() & Qt::ClickFocus)
1183 forceActiveFocus(Qt::MouseFocusReason);
1184
1185 const QPointF eventPos(d->width / 2, d->height / 2);
1186 d->handlePress(eventPos, 0);
1187 d->handleRelease(eventPos, 0);
1188}
1189
1190/*!
1191 \since Qt 6.8
1192 \qmlmethod void QtQuick.Controls::AbstractButton::animateClick()
1193
1194 Simulates the button being clicked, with a 100 millisecond delay
1195 between press and release, animating its visual state in the
1196 process.
1197
1198 All signals associated with a click are emitted as appropriate.
1199
1200 If the \l [QML] {Item::} {focusPolicy} includes \c Qt.ClickFocus,
1201 \l [QML] {Item::}{activeFocus} will become \c true.
1202
1203 This function does nothing if the button is
1204 \l [QML] {Item::enabled} {disabled}.
1205
1206 Calling this function again before the button is released resets
1207 the release timer.
1208
1209 \sa click(), pressed(), released(), clicked()
1210*/
1211void QQuickAbstractButton::animateClick()
1212{
1213 Q_D(QQuickAbstractButton);
1214 if (!isEnabled())
1215 return;
1216
1217 // See comment in click() for why we do this.
1218 const bool setFocusOnPress = !QGuiApplication::styleHints()->setFocusOnTouchRelease();
1219 if (setFocusOnPress && focusPolicy() & Qt::ClickFocus)
1220 forceActiveFocus(Qt::MouseFocusReason);
1221
1222 // If the timer was already running, kill it so we can restart it.
1223 if (d->animateTimer != 0) {
1224 killTimer(d->animateTimer);
1225 d->animateTimer = 0;
1226 } else {
1227 d->handlePress(QPointF(d->width / 2, d->height / 2), 0);
1228 }
1229
1230 d->animateTimer = startTimer(100);
1231}
1232
1233void QQuickAbstractButton::componentComplete()
1234{
1235 Q_D(QQuickAbstractButton);
1236 d->executeIndicator(true);
1237 QQuickControl::componentComplete();
1238}
1239
1240bool QQuickAbstractButton::event(QEvent *event)
1241{
1242#if QT_CONFIG(shortcut)
1243 Q_D(QQuickAbstractButton);
1244 if (event->type() == QEvent::Shortcut) {
1245 QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
1246 if (se->shortcutId() == d->shortcutId) {
1247 d->trigger();
1248 return true;
1249 }
1250 }
1251#endif
1252 return QQuickControl::event(event);
1253}
1254
1255void QQuickAbstractButton::focusOutEvent(QFocusEvent *event)
1256{
1257 Q_D(QQuickAbstractButton);
1258 QQuickControl::focusOutEvent(event);
1259 if (d->touchId == -1) // don't ungrab on multi-touch if another control gets focused
1260 d->handleUngrab();
1261}
1262
1263void QQuickAbstractButton::keyPressEvent(QKeyEvent *event)
1264{
1265 Q_D(QQuickAbstractButton);
1266 QQuickControl::keyPressEvent(event);
1267 if (d->acceptKeyClick(static_cast<Qt::Key>(event->key()))) {
1268 d->setPressPoint(d->centerPressPoint());
1269 setPressed(true);
1270
1271 if (d->autoRepeat)
1272 d->startRepeatDelay();
1273
1274 emit pressed();
1275 event->accept();
1276 }
1277}
1278
1279void QQuickAbstractButton::keyReleaseEvent(QKeyEvent *event)
1280{
1281 Q_D(QQuickAbstractButton);
1282 QQuickControl::keyReleaseEvent(event);
1283 if (d->pressed && d->acceptKeyClick(static_cast<Qt::Key>(event->key()))) {
1284 setPressed(false);
1285
1286 nextCheckState();
1287 emit released();
1288 d->trigger();
1289
1290 if (d->autoRepeat)
1291 d->stopPressRepeat();
1292 event->accept();
1293 }
1294}
1295
1296void QQuickAbstractButton::mousePressEvent(QMouseEvent *event)
1297{
1298 if (!(event->buttons() & Qt::LeftButton)) {
1299 event->ignore();
1300 return;
1301 }
1302
1303 Q_D(QQuickAbstractButton);
1304 d->pressButtons = event->buttons();
1305 QQuickControl::mousePressEvent(event);
1306}
1307
1308void QQuickAbstractButton::mouseDoubleClickEvent(QMouseEvent *event)
1309{
1310 Q_UNUSED(event);
1311 Q_D(QQuickAbstractButton);
1312 if (d->isDoubleClickConnected()) {
1313 // don't call QQuickItem::mouseDoubleClickEvent(): it would ignore()
1314 emit doubleClicked();
1315 d->wasDoubleClick = true;
1316 }
1317}
1318
1319void QQuickAbstractButton::timerEvent(QTimerEvent *event)
1320{
1321 Q_D(QQuickAbstractButton);
1322 QQuickControl::timerEvent(event);
1323 if (event->timerId() == d->holdTimer) {
1324 d->stopPressAndHold();
1325 d->wasHeld = true;
1326 emit pressAndHold();
1327 QQuickToolTipAttachedPrivate::maybeSetVisibleImplicitly(this, true);
1328 } else if (event->timerId() == d->delayTimer) {
1329 d->startPressRepeat();
1330 } else if (event->timerId() == d->repeatTimer) {
1331 emit released();
1332 d->trigger();
1333 emit pressed();
1334 } else if (event->timerId() == d->animateTimer) {
1335 const bool setFocusOnRelease = QGuiApplication::styleHints()->setFocusOnTouchRelease();
1336 if (setFocusOnRelease && focusPolicy() & Qt::ClickFocus)
1337 forceActiveFocus(Qt::MouseFocusReason);
1338 d->handleRelease(QPointF(d->width / 2, d->height / 2), 0);
1339 killTimer(d->animateTimer);
1340 d->animateTimer = 0;
1341 }
1342}
1343
1344void QQuickAbstractButton::itemChange(ItemChange change, const ItemChangeData &value)
1345{
1346 QQuickControl::itemChange(change, value);
1347#if QT_CONFIG(shortcut)
1348 Q_D(QQuickAbstractButton);
1349 if (change == ItemVisibleHasChanged) {
1350 if (value.boolValue)
1351 d->grabShortcut();
1352 else
1353 d->ungrabShortcut();
1354 }
1355#endif
1356}
1357
1358void QQuickAbstractButton::buttonChange(ButtonChange change)
1359{
1360 Q_D(QQuickAbstractButton);
1361 switch (change) {
1362 case ButtonCheckedChange:
1363 if (d->checked) {
1364 QQuickAbstractButton *button = d->findCheckedButton();
1365 if (button && button != this)
1366 button->setChecked(false);
1367 }
1368 break;
1369 case ButtonTextChange: {
1370 const QString txt = text();
1371#if QT_CONFIG(accessibility)
1372 maybeSetAccessibleName(qt_accStripAmp(txt));
1373#endif
1374#if QT_CONFIG(shortcut)
1375 setShortcut(QKeySequence::mnemonic(txt));
1376#endif
1377 emit textChanged();
1378 break;
1379 }
1380 default:
1381 break;
1382 }
1383}
1384
1385void QQuickAbstractButton::nextCheckState()
1386{
1387 Q_D(QQuickAbstractButton);
1388 if (!d->checkable)
1389 return;
1390
1391 if (d->checked) {
1392 if (d->findCheckedButton() == this)
1393 return;
1394 if (d->action) {
1395 // For non-exclusive groups checkedAction is null
1396 if (const auto group = QQuickActionPrivate::get(d->action)->group)
1397 if (group->checkedAction() == d->action)
1398 return;
1399 }
1400 }
1401
1402 d->toggle(!d->checked);
1403}
1404
1405#if QT_CONFIG(accessibility)
1406void QQuickAbstractButton::accessibilityActiveChanged(bool active)
1407{
1408 QQuickControl::accessibilityActiveChanged(active);
1409
1410 Q_D(QQuickAbstractButton);
1411 if (active) {
1412 maybeSetAccessibleName(qt_accStripAmp(text()));
1413 setAccessibleProperty("pressed", d->pressed);
1414 setAccessibleProperty("checked", d->checked);
1415 setAccessibleProperty("checkable", d->checkable);
1416 }
1417}
1418
1419QAccessible::Role QQuickAbstractButton::accessibleRole() const
1420{
1421 Q_D(const QQuickAbstractButton);
1422 if (d->checkable) {
1423 return QAccessible::CheckBox;
1424 }
1425 return QAccessible::Button;
1426}
1427
1428void QQuickAbstractButton::accessiblePressAction()
1429{
1430 Q_D(QQuickAbstractButton);
1431 d->accessiblePressAction();
1432}
1433#endif
1434
1435QT_END_NAMESPACE
1436
1437#include "moc_qquickabstractbutton_p.cpp"
Combined button and popup list for selecting options.