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(lcButtonAction, "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 our Action's trigger signal handler disables us (or the action, which causes us to be
431 // disabled), we still want clicked to be emitted so that e.g. menus close when a menu item is
432 // clicked. That's why we check wasEnabledBeforeTrigger here.
433 if (effectiveEnable || wasEnabledBeforeTrigger)
434 emit q->clicked();
435}
436
437void QQuickAbstractButtonPrivate::accessiblePressAction()
438{
439 Q_Q(QQuickAbstractButton);
440 q->click();
441}
442
443void QQuickAbstractButtonPrivate::accessibleToggleAction()
444{
445 accessiblePressAction();
446}
447
448void QQuickAbstractButtonPrivate::trigger(bool doubleClick)
449{
450 Q_Q(QQuickAbstractButton);
451 const QScopedValueRollback<bool> rollback(wasEnabledBeforeTrigger, effectiveEnable);
452
453 bool actionTriggered = false;
454 if (action && action->isEnabled())
455 actionTriggered = QQuickActionPrivate::get(action)->trigger(q, false);
456
457 // Don't emit the signals below if we were disabled or if our action already emitted its
458 // triggered signal (which we connect to click, which emits clicked, so would emit twice).
459 if (!wasEnabledBeforeTrigger || actionTriggered)
460 return;
461
462 if (!doubleClick)
463 emit q->clicked();
464 else
465 emit q->doubleClicked();
466}
467
468void QQuickAbstractButtonPrivate::toggle(bool value)
469{
470 Q_Q(QQuickAbstractButton);
471 const bool wasChecked = checked;
472 q->setChecked(value);
473 if (wasChecked != checked)
474 emit q->toggled();
475}
476
477void QQuickAbstractButtonPrivate::cancelIndicator()
478{
479 Q_Q(QQuickAbstractButton);
480 quickCancelDeferred(q, indicatorName());
481}
482
483void QQuickAbstractButtonPrivate::executeIndicator(bool complete)
484{
485 Q_Q(QQuickAbstractButton);
486 if (indicator.wasExecuted())
487 return;
488
489 if (!indicator || complete)
490 quickBeginDeferred(q, indicatorName(), indicator);
491 if (complete)
492 quickCompleteDeferred(q, indicatorName(), indicator);
493}
494
495void QQuickAbstractButtonPrivate::itemImplicitWidthChanged(QQuickItem *item)
496{
497 Q_Q(QQuickAbstractButton);
498 QQuickControlPrivate::itemImplicitWidthChanged(item);
499 if (item == indicator)
500 emit q->implicitIndicatorWidthChanged();
501}
502
503void QQuickAbstractButtonPrivate::itemImplicitHeightChanged(QQuickItem *item)
504{
505 Q_Q(QQuickAbstractButton);
506 QQuickControlPrivate::itemImplicitHeightChanged(item);
507 if (item == indicator)
508 emit q->implicitIndicatorHeightChanged();
509}
510
511void QQuickAbstractButtonPrivate::itemDestroyed(QQuickItem *item)
512{
513 Q_Q(QQuickAbstractButton);
514 QQuickControlPrivate::itemDestroyed(item);
515 if (item == indicator) {
516 indicator = nullptr;
517 emit q->implicitIndicatorWidthChanged();
518 emit q->implicitIndicatorHeightChanged();
519 }
520}
521
522QQuickAbstractButton *QQuickAbstractButtonPrivate::findCheckedButton() const
523{
524 Q_Q(const QQuickAbstractButton);
525 if (group)
526 return group->checkedButton();
527
528 const QList<QQuickAbstractButton *> buttons = findExclusiveButtons();
529 // TODO: A singular QRadioButton can be unchecked, which seems logical,
530 // because there's nothing to be exclusive with. However, a RadioButton
531 // from QtQuick.Controls 1.x can never be unchecked, which is the behavior
532 // that QQuickRadioButton adopted. Uncommenting the following count check
533 // gives the QRadioButton behavior. Notice that tst_radiobutton.qml needs
534 // to be updated.
535 if (!autoExclusive /*|| buttons.count() == 1*/)
536 return nullptr;
537
538 for (QQuickAbstractButton *button : buttons) {
539 if (button->isChecked() && button != q)
540 return button;
541 }
542 return checked ? const_cast<QQuickAbstractButton *>(q) : nullptr;
543}
544
545QList<QQuickAbstractButton *> QQuickAbstractButtonPrivate::findExclusiveButtons() const
546{
547 QList<QQuickAbstractButton *> buttons;
548 if (group) {
549 QQmlListProperty<QQuickAbstractButton> groupButtons = group->buttons();
550 int count = groupButtons.count(&groupButtons);
551 for (int i = 0; i < count; ++i) {
552 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(groupButtons.at(&groupButtons, i));
553 if (button)
554 buttons += button;
555 }
556 } else if (parentItem) {
557 const auto childItems = parentItem->childItems();
558 for (QQuickItem *child : childItems) {
559 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(child);
560 if (button && button->autoExclusive() && !QQuickAbstractButtonPrivate::get(button)->group)
561 buttons += button;
562 }
563 }
564 return buttons;
565}
566
567QQuickAbstractButton::QQuickAbstractButton(QQuickItem *parent)
568 : QQuickControl(*(new QQuickAbstractButtonPrivate), parent)
569{
570 Q_D(QQuickAbstractButton);
571 d->init();
572}
573
574QQuickAbstractButton::QQuickAbstractButton(QQuickAbstractButtonPrivate &dd, QQuickItem *parent)
575 : QQuickControl(dd, parent)
576{
577 Q_D(QQuickAbstractButton);
578 d->init();
579}
580
581QQuickAbstractButton::~QQuickAbstractButton()
582{
583 Q_D(QQuickAbstractButton);
584 d->removeImplicitSizeListener(d->indicator);
585 if (d->group) {
586 auto *attached = qobject_cast<QQuickButtonGroupAttached *>(
587 qmlAttachedPropertiesObject<QQuickButtonGroup>(this, false));
588 if (attached)
589 attached->setGroup(nullptr);
590 else
591 d->group->removeButton(this);
592 }
593#if QT_CONFIG(shortcut)
594 d->ungrabShortcut();
595#endif
596}
597
598/*!
599 \qmlproperty string QtQuick.Controls::AbstractButton::text
600
601 This property holds a textual description of the button.
602
603 \note The text is used for accessibility purposes, so it makes sense to
604 set a textual description even if the content item is an image.
605
606 \sa icon, display, {Control::contentItem}{contentItem}
607*/
608QString QQuickAbstractButton::text() const
609{
610 Q_D(const QQuickAbstractButton);
611 return d->explicitText || !d->action ? d->text : d->action->text();
612}
613
614void QQuickAbstractButton::setText(const QString &text)
615{
616 Q_D(QQuickAbstractButton);
617 d->setText(text, QQml::PropertyUtils::State::ExplicitlySet);
618}
619
620void QQuickAbstractButton::resetText()
621{
622 Q_D(QQuickAbstractButton);
623 d->setText(QString(), QQml::PropertyUtils::State::ImplicitlySet);
624}
625
626/*!
627 \qmlproperty bool QtQuick.Controls::AbstractButton::down
628
629 This property holds whether the button is visually down.
630
631 Unless explicitly set, this property follows the value of \l pressed. To
632 return to the default value, set this property to \c undefined.
633
634 \sa pressed
635*/
636bool QQuickAbstractButton::isDown() const
637{
638 Q_D(const QQuickAbstractButton);
639 return d->down;
640}
641
642void QQuickAbstractButton::setDown(bool down)
643{
644 Q_D(QQuickAbstractButton);
645 d->explicitDown = true;
646
647 if (d->down == down)
648 return;
649
650 d->down = down;
651 emit downChanged();
652}
653
654void QQuickAbstractButton::resetDown()
655{
656 Q_D(QQuickAbstractButton);
657 if (!d->explicitDown)
658 return;
659
660 setDown(d->pressed);
661 d->explicitDown = false;
662}
663
664/*!
665 \qmlproperty bool QtQuick.Controls::AbstractButton::pressed
666 \readonly
667
668 This property holds whether the button is physically pressed. A button can
669 be pressed by either touch or key events.
670
671 \sa down
672*/
673bool QQuickAbstractButton::isPressed() const
674{
675 Q_D(const QQuickAbstractButton);
676 return d->pressed;
677}
678
679void QQuickAbstractButton::setPressed(bool isPressed)
680{
681 Q_D(QQuickAbstractButton);
682 if (d->pressed == isPressed)
683 return;
684
685 d->pressed = isPressed;
686 setAccessibleProperty("pressed", isPressed);
687 emit pressedChanged();
688 buttonChange(ButtonPressedChanged);
689
690 if (!d->explicitDown) {
691 setDown(d->pressed);
692 d->explicitDown = false;
693 }
694}
695
696/*!
697 \qmlproperty bool QtQuick.Controls::AbstractButton::checked
698
699 This property holds whether the button is checked.
700
701 Since Qt 6.2, setting this property no longer affects the
702 \l {AbstractButton::}{checkable} property. Explicitly set the
703 \c checkable property if needed.
704
705 \sa checkable
706*/
707bool QQuickAbstractButton::isChecked() const
708{
709 Q_D(const QQuickAbstractButton);
710 return d->checked;
711}
712
713void QQuickAbstractButton::setChecked(bool checked)
714{
715 Q_D(QQuickAbstractButton);
716 if (d->checked == checked)
717 return;
718
719 d->checked = checked;
720 if (d->action)
721 d->action->setChecked(checked);
722 setAccessibleProperty("checked", checked);
723 buttonChange(ButtonCheckedChange);
724 emit checkedChanged();
725}
726
727/*!
728 \qmlproperty bool QtQuick.Controls::AbstractButton::checkable
729
730 This property holds whether the button is checkable.
731
732 A checkable button toggles between checked (on) and unchecked (off) when
733 the user clicks on it or presses the space bar while the button has active
734 focus.
735
736 The default value is \c false.
737
738 \sa checked
739*/
740bool QQuickAbstractButton::isCheckable() const
741{
742 Q_D(const QQuickAbstractButton);
743 return d->checkable;
744}
745
746void QQuickAbstractButton::setCheckable(bool checkable)
747{
748 Q_D(QQuickAbstractButton);
749 if (d->checkable == checkable)
750 return;
751
752 d->checkable = checkable;
753 if (d->action)
754 d->action->setCheckable(checkable);
755 setAccessibleProperty("checkable", checkable);
756 buttonChange(ButtonCheckableChange);
757 emit checkableChanged();
758}
759
760/*!
761 \qmlproperty bool QtQuick.Controls::AbstractButton::autoExclusive
762
763 This property holds whether auto-exclusivity is enabled.
764
765 If auto-exclusivity is enabled, checkable buttons that belong to the same
766 parent item behave as if they were part of the same ButtonGroup. Only
767 one button can be checked at any time; checking another button automatically
768 unchecks the previously checked one.
769
770 \note The property has no effect on buttons that belong to a ButtonGroup.
771
772 RadioButton and TabButton are auto-exclusive by default.
773*/
774bool QQuickAbstractButton::autoExclusive() const
775{
776 Q_D(const QQuickAbstractButton);
777 return d->autoExclusive;
778}
779
780void QQuickAbstractButton::setAutoExclusive(bool exclusive)
781{
782 Q_D(QQuickAbstractButton);
783 if (d->autoExclusive == exclusive)
784 return;
785
786 d->autoExclusive = exclusive;
787 emit autoExclusiveChanged();
788}
789
790/*!
791 \qmlproperty bool QtQuick.Controls::AbstractButton::autoRepeat
792
793 This property holds whether the button repeats \l pressed(), \l released()
794 and \l clicked() signals while the button is pressed and held down.
795
796 If this property is set to \c true, the \l pressAndHold() signal will not
797 be emitted.
798
799 The default value is \c false.
800
801 The initial delay and the repetition interval are defined in milliseconds
802 by \l autoRepeatDelay and \l autoRepeatInterval.
803*/
804bool QQuickAbstractButton::autoRepeat() const
805{
806 Q_D(const QQuickAbstractButton);
807 return d->autoRepeat;
808}
809
810void QQuickAbstractButton::setAutoRepeat(bool repeat)
811{
812 Q_D(QQuickAbstractButton);
813 if (d->autoRepeat == repeat)
814 return;
815
816 d->stopPressRepeat();
817 d->autoRepeat = repeat;
818 emit autoRepeatChanged();
819}
820
821/*!
822 \qmlproperty Item QtQuick.Controls::AbstractButton::indicator
823
824 This property holds the indicator item.
825*/
826QQuickItem *QQuickAbstractButton::indicator() const
827{
828 QQuickAbstractButtonPrivate *d = const_cast<QQuickAbstractButtonPrivate *>(d_func());
829 if (!d->indicator)
830 d->executeIndicator();
831 return d->indicator;
832}
833
834void QQuickAbstractButton::setIndicator(QQuickItem *indicator)
835{
836 Q_D(QQuickAbstractButton);
837 if (d->indicator == indicator)
838 return;
839
840 QQuickControlPrivate::warnIfCustomizationNotSupported(this, indicator, QStringLiteral("indicator"));
841
842 if (!d->indicator.isExecuting())
843 d->cancelIndicator();
844
845 const qreal oldImplicitIndicatorWidth = implicitIndicatorWidth();
846 const qreal oldImplicitIndicatorHeight = implicitIndicatorHeight();
847
848 d->removeImplicitSizeListener(d->indicator);
849 QQuickControlPrivate::hideOldItem(d->indicator);
850 d->indicator = indicator;
851
852 if (indicator) {
853 if (!indicator->parentItem())
854 indicator->setParentItem(this);
855 indicator->setAcceptedMouseButtons(Qt::LeftButton);
856 d->addImplicitSizeListener(indicator);
857 }
858
859 if (!qFuzzyCompare(oldImplicitIndicatorWidth, implicitIndicatorWidth()))
860 emit implicitIndicatorWidthChanged();
861 if (!qFuzzyCompare(oldImplicitIndicatorHeight, implicitIndicatorHeight()))
862 emit implicitIndicatorHeightChanged();
863 if (!d->indicator.isExecuting())
864 emit indicatorChanged();
865}
866
867/*!
868 \qmlproperty string QtQuick.Controls::AbstractButton::icon.name
869 \qmlproperty url QtQuick.Controls::AbstractButton::icon.source
870 \qmlproperty int QtQuick.Controls::AbstractButton::icon.width
871 \qmlproperty int QtQuick.Controls::AbstractButton::icon.height
872 \qmlproperty color QtQuick.Controls::AbstractButton::icon.color
873 \qmlproperty bool QtQuick.Controls::AbstractButton::icon.cache
874
875 \since QtQuick.Controls 2.3
876
877 \include qquickicon.qdocinc grouped-properties
878
879 \sa text, display, {Icons in Qt Quick Controls}
880*/
881
882QQuickIcon QQuickAbstractButton::icon() const
883{
884 Q_D(const QQuickAbstractButton);
885 return d->effectiveIcon;
886}
887
888void QQuickAbstractButton::setIcon(const QQuickIcon &icon)
889{
890 Q_D(QQuickAbstractButton);
891 d->icon = icon;
892 d->icon.ensureRelativeSourceResolved(this);
893 d->updateEffectiveIcon();
894}
895
896/*!
897 \since QtQuick.Controls 2.3 (Qt 5.10)
898 \qmlproperty enumeration QtQuick.Controls::AbstractButton::display
899
900 This property determines how the \l icon and \l text are displayed within
901 the button.
902
903 \table
904 \header \li Display \li Result
905 \row \li \c AbstractButton.IconOnly
906 \li \image qtquickcontrols-button-icononly.png
907 {Button displaying only icon}
908 \row \li \c AbstractButton.TextOnly
909 \li \image qtquickcontrols-button-textonly.png
910 {Button displaying only text}
911 \row \li \c AbstractButton.TextBesideIcon (default)
912 \li \image qtquickcontrols-button-textbesideicon.png
913 {Button with text beside icon}
914 \row \li \c AbstractButton.TextUnderIcon
915 \li \image qtquickcontrols-button-textundericon.png
916 {Button with text under icon}
917 \endtable
918
919 \sa {Control::}{spacing}, {Control::}{padding}
920*/
921QQuickAbstractButton::Display QQuickAbstractButton::display() const
922{
923 Q_D(const QQuickAbstractButton);
924 return d->display;
925}
926
927void QQuickAbstractButton::setDisplay(Display display)
928{
929 Q_D(QQuickAbstractButton);
930 if (display == d->display)
931 return;
932
933 d->display = display;
934 emit displayChanged();
935}
936
937/*!
938 \since QtQuick.Controls 2.3 (Qt 5.10)
939 \qmlproperty Action QtQuick.Controls::AbstractButton::action
940
941 This property holds the button action.
942
943 \sa Action
944*/
945QQuickAction *QQuickAbstractButton::action() const
946{
947 Q_D(const QQuickAbstractButton);
948 return d->action;
949}
950
951void QQuickAbstractButton::setAction(QQuickAction *action)
952{
953 Q_D(QQuickAbstractButton);
954 qCDebug(lcButtonAction) << this << "setAction called with" << action;
955 if (d->action == action)
956 return;
957
958 const QString oldText = text();
959
960 if (QQuickAction *oldAction = d->action.data()) {
961 QQuickActionPrivate::get(oldAction)->unregisterItem(this);
962 QObjectPrivate::disconnect(oldAction, &QQuickAction::triggered, d, &QQuickAbstractButtonPrivate::click);
963 QObjectPrivate::disconnect(oldAction, &QQuickAction::textChanged, d, &QQuickAbstractButtonPrivate::actionTextChange);
964
965 QObjectPrivate::disconnect(oldAction, &QQuickAction::iconChanged, d, &QQuickAbstractButtonPrivate::updateEffectiveIcon);
966 disconnect(oldAction, &QQuickAction::checkedChanged, this, &QQuickAbstractButton::setChecked);
967 disconnect(oldAction, &QQuickAction::checkableChanged, this, &QQuickAbstractButton::setCheckable);
968 disconnect(oldAction, &QQuickAction::enabledChanged, this, &QQuickItem::setEnabled);
969 }
970
971 if (action) {
972 QQuickActionPrivate::get(action)->registerItem(this);
973 QObjectPrivate::connect(action, &QQuickAction::triggered, d, &QQuickAbstractButtonPrivate::click);
974 QObjectPrivate::connect(action, &QQuickAction::textChanged, d, &QQuickAbstractButtonPrivate::actionTextChange);
975
976 QObjectPrivate::connect(action, &QQuickAction::iconChanged, d, &QQuickAbstractButtonPrivate::updateEffectiveIcon);
977 connect(action, &QQuickAction::checkedChanged, this, &QQuickAbstractButton::setChecked);
978 connect(action, &QQuickAction::checkableChanged, this, &QQuickAbstractButton::setCheckable);
979 connect(action, &QQuickAction::enabledChanged, this, &QQuickItem::setEnabled);
980
981 setChecked(action->isChecked());
982 setCheckable(action->isCheckable());
983 setEnabled(action->isEnabled());
984 }
985
986#if QT_CONFIG(accessibility)
987 auto attached = qobject_cast<QQuickAccessibleAttached*>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(this, true));
988 Q_ASSERT(attached);
989 attached->setProxying(qobject_cast<QQuickAccessibleAttached*>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(action, true)));
990#endif
991
992 d->action = action;
993
994 if (oldText != text())
995 buttonChange(ButtonTextChange);
996
997 d->updateEffectiveIcon();
998
999 emit actionChanged();
1000}
1001
1002/*!
1003 \since QtQuick.Controls 2.4 (Qt 5.11)
1004 \qmlproperty int QtQuick.Controls::AbstractButton::autoRepeatDelay
1005
1006 This property holds the initial delay of auto-repetition in milliseconds.
1007 The default value is \c 300 ms.
1008
1009 \sa autoRepeat, autoRepeatInterval
1010*/
1011int QQuickAbstractButton::autoRepeatDelay() const
1012{
1013 Q_D(const QQuickAbstractButton);
1014 return d->repeatDelay;
1015}
1016
1017void QQuickAbstractButton::setAutoRepeatDelay(int delay)
1018{
1019 Q_D(QQuickAbstractButton);
1020 if (d->repeatDelay == delay)
1021 return;
1022
1023 d->repeatDelay = delay;
1024 emit autoRepeatDelayChanged();
1025}
1026
1027/*!
1028 \since QtQuick.Controls 2.4 (Qt 5.11)
1029 \qmlproperty int QtQuick.Controls::AbstractButton::autoRepeatInterval
1030
1031 This property holds the interval of auto-repetition in milliseconds.
1032 The default value is \c 100 ms.
1033
1034 \sa autoRepeat, autoRepeatDelay
1035*/
1036int QQuickAbstractButton::autoRepeatInterval() const
1037{
1038 Q_D(const QQuickAbstractButton);
1039 return d->repeatInterval;
1040}
1041
1042void QQuickAbstractButton::setAutoRepeatInterval(int interval)
1043{
1044 Q_D(QQuickAbstractButton);
1045 if (d->repeatInterval == interval)
1046 return;
1047
1048 d->repeatInterval = interval;
1049 emit autoRepeatIntervalChanged();
1050}
1051
1052#if QT_CONFIG(shortcut)
1053/*!
1054 \internal
1055
1056 This is the mnemonic shortcut that is derived from the text;
1057 see \c QQuickAbstractButton::buttonChange().
1058*/
1059QKeySequence QQuickAbstractButton::shortcut() const
1060{
1061 Q_D(const QQuickAbstractButton);
1062 return d->shortcut;
1063}
1064
1065void QQuickAbstractButton::setShortcut(const QKeySequence &shortcut)
1066{
1067 Q_D(QQuickAbstractButton);
1068 if (d->shortcut == shortcut)
1069 return;
1070
1071 d->ungrabShortcut();
1072 d->shortcut = shortcut;
1073 if (isVisible())
1074 d->grabShortcut();
1075}
1076#endif
1077
1078/*!
1079 \readonly
1080 \since QtQuick.Controls 2.4 (Qt 5.11)
1081 \qmlproperty real QtQuick.Controls::AbstractButton::pressX
1082
1083 This property holds the x-coordinate of the last press.
1084
1085 \note The value is updated on touch moves, but left intact after touch release.
1086
1087 \sa pressY
1088*/
1089qreal QQuickAbstractButton::pressX() const
1090{
1091 Q_D(const QQuickAbstractButton);
1092 return d->movePoint.x();
1093}
1094
1095/*!
1096 \readonly
1097 \since QtQuick.Controls 2.4 (Qt 5.11)
1098 \qmlproperty real QtQuick.Controls::AbstractButton::pressY
1099
1100 This property holds the y-coordinate of the last press.
1101
1102 \note The value is updated on touch moves, but left intact after touch release.
1103
1104 \sa pressX
1105*/
1106qreal QQuickAbstractButton::pressY() const
1107{
1108 Q_D(const QQuickAbstractButton);
1109 return d->movePoint.y();
1110}
1111
1112/*!
1113 \since QtQuick.Controls 2.5 (Qt 5.12)
1114 \qmlproperty real QtQuick.Controls::AbstractButton::implicitIndicatorWidth
1115 \readonly
1116
1117 This property holds the implicit indicator width.
1118
1119 The value is equal to \c {indicator ? indicator.implicitWidth : 0}.
1120
1121 This is typically used, together with \l {Control::}{implicitContentWidth} and
1122 \l {Control::}{implicitBackgroundWidth}, to calculate the \l {Item::}{implicitWidth}.
1123
1124 \sa implicitIndicatorHeight
1125*/
1126qreal QQuickAbstractButton::implicitIndicatorWidth() const
1127{
1128 Q_D(const QQuickAbstractButton);
1129 if (!d->indicator)
1130 return 0;
1131 return d->indicator->implicitWidth();
1132}
1133
1134/*!
1135 \since QtQuick.Controls 2.5 (Qt 5.12)
1136 \qmlproperty real QtQuick.Controls::AbstractButton::implicitIndicatorHeight
1137 \readonly
1138
1139 This property holds the implicit indicator height.
1140
1141 The value is equal to \c {indicator ? indicator.implicitHeight : 0}.
1142
1143 This is typically used, together with \l {Control::}{implicitContentHeight} and
1144 \l {Control::}{implicitBackgroundHeight}, to calculate the \l {Item::}{implicitHeight}.
1145
1146 \sa implicitIndicatorWidth
1147*/
1148qreal QQuickAbstractButton::implicitIndicatorHeight() const
1149{
1150 Q_D(const QQuickAbstractButton);
1151 if (!d->indicator)
1152 return 0;
1153 return d->indicator->implicitHeight();
1154}
1155
1156/*!
1157 \qmlmethod void QtQuick.Controls::AbstractButton::toggle()
1158
1159 Toggles the checked state of the button.
1160
1161 \sa click(), animateClick()
1162*/
1163void QQuickAbstractButton::toggle()
1164{
1165 Q_D(QQuickAbstractButton);
1166 setChecked(!d->checked);
1167}
1168
1169/*!
1170 \since Qt 6.8
1171 \qmlmethod void QtQuick.Controls::AbstractButton::click()
1172
1173 Simulates the button being clicked with no delay between press and release.
1174
1175 All signals associated with a click are emitted as appropriate.
1176
1177 If the \l [QML] {Item::} {focusPolicy} includes \c Qt.ClickFocus,
1178 \l [QML] {Item::} {activeFocus} will become \c true.
1179
1180 This function does nothing if the button is
1181 \l [QML] {Item::enabled} {disabled}.
1182
1183 Calling this function again before the button is released resets
1184 the release timer.
1185
1186 \sa animateClick(), pressed(), released(), clicked()
1187*/
1188void QQuickAbstractButton::click()
1189{
1190 Q_D(QQuickAbstractButton);
1191 if (!isEnabled())
1192 return;
1193
1194 // QQuickItemPrivate::deliverPointerEvent calls setFocusIfNeeded on real clicks,
1195 // so we need to do it ourselves.
1196 const bool setFocusOnPress = !QGuiApplication::styleHints()->setFocusOnTouchRelease();
1197 if (setFocusOnPress && focusPolicy() & Qt::ClickFocus)
1198 forceActiveFocus(Qt::MouseFocusReason);
1199
1200 const QPointF eventPos(d->width / 2, d->height / 2);
1201 d->handlePress(eventPos, 0);
1202 d->handleRelease(eventPos, 0);
1203}
1204
1205/*!
1206 \since Qt 6.8
1207 \qmlmethod void QtQuick.Controls::AbstractButton::animateClick()
1208
1209 Simulates the button being clicked, with a 100 millisecond delay
1210 between press and release, animating its visual state in the
1211 process.
1212
1213 All signals associated with a click are emitted as appropriate.
1214
1215 If the \l [QML] {Item::} {focusPolicy} includes \c Qt.ClickFocus,
1216 \l [QML] {Item::}{activeFocus} will become \c true.
1217
1218 This function does nothing if the button is
1219 \l [QML] {Item::enabled} {disabled}.
1220
1221 Calling this function again before the button is released resets
1222 the release timer.
1223
1224 \sa click(), pressed(), released(), clicked()
1225*/
1226void QQuickAbstractButton::animateClick()
1227{
1228 Q_D(QQuickAbstractButton);
1229 if (!isEnabled())
1230 return;
1231
1232 // See comment in click() for why we do this.
1233 const bool setFocusOnPress = !QGuiApplication::styleHints()->setFocusOnTouchRelease();
1234 if (setFocusOnPress && focusPolicy() & Qt::ClickFocus)
1235 forceActiveFocus(Qt::MouseFocusReason);
1236
1237 // If the timer was already running, kill it so we can restart it.
1238 if (d->animateTimer != 0) {
1239 killTimer(d->animateTimer);
1240 d->animateTimer = 0;
1241 } else {
1242 d->handlePress(QPointF(d->width / 2, d->height / 2), 0);
1243 }
1244
1245 d->animateTimer = startTimer(100);
1246}
1247
1248void QQuickAbstractButton::componentComplete()
1249{
1250 Q_D(QQuickAbstractButton);
1251 d->executeIndicator(true);
1252 QQuickControl::componentComplete();
1253}
1254
1255bool QQuickAbstractButton::event(QEvent *event)
1256{
1257#if QT_CONFIG(shortcut)
1258 Q_D(QQuickAbstractButton);
1259 if (event->type() == QEvent::Shortcut) {
1260 QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
1261 if (se->shortcutId() == d->shortcutId) {
1262 d->trigger();
1263 return true;
1264 }
1265 }
1266#endif
1267 return QQuickControl::event(event);
1268}
1269
1270void QQuickAbstractButton::focusOutEvent(QFocusEvent *event)
1271{
1272 Q_D(QQuickAbstractButton);
1273 QQuickControl::focusOutEvent(event);
1274 if (d->touchId == -1) // don't ungrab on multi-touch if another control gets focused
1275 d->handleUngrab();
1276}
1277
1278void QQuickAbstractButton::keyPressEvent(QKeyEvent *event)
1279{
1280 Q_D(QQuickAbstractButton);
1281 QQuickControl::keyPressEvent(event);
1282 if (d->acceptKeyClick(static_cast<Qt::Key>(event->key()))) {
1283 d->setPressPoint(d->centerPressPoint());
1284 setPressed(true);
1285
1286 if (d->autoRepeat)
1287 d->startRepeatDelay();
1288
1289 emit pressed();
1290 event->accept();
1291 }
1292}
1293
1294void QQuickAbstractButton::keyReleaseEvent(QKeyEvent *event)
1295{
1296 Q_D(QQuickAbstractButton);
1297 QQuickControl::keyReleaseEvent(event);
1298 if (d->pressed && d->acceptKeyClick(static_cast<Qt::Key>(event->key()))) {
1299 setPressed(false);
1300
1301 nextCheckState();
1302 emit released();
1303 d->trigger();
1304
1305 if (d->autoRepeat)
1306 d->stopPressRepeat();
1307 event->accept();
1308 }
1309}
1310
1311void QQuickAbstractButton::mousePressEvent(QMouseEvent *event)
1312{
1313 if (!(event->buttons() & Qt::LeftButton)) {
1314 event->ignore();
1315 return;
1316 }
1317
1318 Q_D(QQuickAbstractButton);
1319 d->pressButtons = event->buttons();
1320 QQuickControl::mousePressEvent(event);
1321}
1322
1323void QQuickAbstractButton::mouseDoubleClickEvent(QMouseEvent *event)
1324{
1325 Q_UNUSED(event);
1326 Q_D(QQuickAbstractButton);
1327 if (d->isDoubleClickConnected()) {
1328 // don't call QQuickItem::mouseDoubleClickEvent(): it would ignore()
1329 emit doubleClicked();
1330 d->wasDoubleClick = true;
1331 }
1332}
1333
1334void QQuickAbstractButton::timerEvent(QTimerEvent *event)
1335{
1336 Q_D(QQuickAbstractButton);
1337 QQuickControl::timerEvent(event);
1338 if (event->timerId() == d->holdTimer) {
1339 d->stopPressAndHold();
1340 d->wasHeld = true;
1341 emit pressAndHold();
1342 QQuickToolTipAttachedPrivate::maybeSetVisibleImplicitly(this, true);
1343 } else if (event->timerId() == d->delayTimer) {
1344 d->startPressRepeat();
1345 } else if (event->timerId() == d->repeatTimer) {
1346 emit released();
1347 d->trigger();
1348 emit pressed();
1349 } else if (event->timerId() == d->animateTimer) {
1350 const bool setFocusOnRelease = QGuiApplication::styleHints()->setFocusOnTouchRelease();
1351 if (setFocusOnRelease && focusPolicy() & Qt::ClickFocus)
1352 forceActiveFocus(Qt::MouseFocusReason);
1353 d->handleRelease(QPointF(d->width / 2, d->height / 2), 0);
1354 killTimer(d->animateTimer);
1355 d->animateTimer = 0;
1356 }
1357}
1358
1359void QQuickAbstractButton::itemChange(ItemChange change, const ItemChangeData &value)
1360{
1361 QQuickControl::itemChange(change, value);
1362#if QT_CONFIG(shortcut)
1363 Q_D(QQuickAbstractButton);
1364 if (change == ItemVisibleHasChanged) {
1365 if (value.boolValue)
1366 d->grabShortcut();
1367 else
1368 d->ungrabShortcut();
1369 }
1370#endif
1371}
1372
1373void QQuickAbstractButton::buttonChange(ButtonChange change)
1374{
1375 Q_D(QQuickAbstractButton);
1376 switch (change) {
1377 case ButtonCheckedChange:
1378 if (d->checked) {
1379 QQuickAbstractButton *button = d->findCheckedButton();
1380 if (button && button != this)
1381 button->setChecked(false);
1382 }
1383 break;
1384 case ButtonTextChange: {
1385 const QString txt = text();
1386#if QT_CONFIG(accessibility)
1387 maybeSetAccessibleName(qt_accStripAmp(txt));
1388#endif
1389#if QT_CONFIG(shortcut)
1390 setShortcut(QKeySequence::mnemonic(txt));
1391#endif
1392 emit textChanged();
1393 break;
1394 }
1395 default:
1396 break;
1397 }
1398}
1399
1400void QQuickAbstractButton::nextCheckState()
1401{
1402 Q_D(QQuickAbstractButton);
1403 if (!d->checkable)
1404 return;
1405
1406 if (d->checked) {
1407 if (d->findCheckedButton() == this)
1408 return;
1409 if (d->action) {
1410 // For non-exclusive groups checkedAction is null
1411 if (const auto group = QQuickActionPrivate::get(d->action)->group)
1412 if (group->checkedAction() == d->action)
1413 return;
1414 }
1415 }
1416
1417 d->toggle(!d->checked);
1418}
1419
1420#if QT_CONFIG(accessibility)
1421void QQuickAbstractButton::accessibilityActiveChanged(bool active)
1422{
1423 QQuickControl::accessibilityActiveChanged(active);
1424
1425 Q_D(QQuickAbstractButton);
1426 if (active) {
1427 maybeSetAccessibleName(qt_accStripAmp(text()));
1428 setAccessibleProperty("pressed", d->pressed);
1429 setAccessibleProperty("checked", d->checked);
1430 setAccessibleProperty("checkable", d->checkable);
1431 }
1432}
1433
1434QAccessible::Role QQuickAbstractButton::accessibleRole() const
1435{
1436 Q_D(const QQuickAbstractButton);
1437 if (d->checkable) {
1438 return QAccessible::CheckBox;
1439 }
1440 return QAccessible::Button;
1441}
1442
1443void QQuickAbstractButton::accessiblePressAction()
1444{
1445 Q_D(QQuickAbstractButton);
1446 d->accessiblePressAction();
1447}
1448
1449void QQuickAbstractButton::accessibleToggleAction()
1450{
1451 Q_D(QQuickAbstractButton);
1452 d->accessibleToggleAction();
1453}
1454#endif
1455
1456QT_END_NAMESPACE
1457
1458#include "moc_qquickabstractbutton_p.cpp"
Combined button and popup list for selecting options.