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