1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "simplewidgets_p.h"
5
6#if QT_CONFIG(abstractbutton)
7#include <qabstractbutton.h>
8#endif
9#if QT_CONFIG(checkbox)
10#include <qcheckbox.h>
11#endif
12#if QT_CONFIG(pushbutton)
13#include <qpushbutton.h>
14#endif
15#if QT_CONFIG(progressbar)
16#include <qprogressbar.h>
17#endif
18#if QT_CONFIG(statusbar)
19#include <qstatusbar.h>
20#endif
21#if QT_CONFIG(radiobutton)
22#include <qradiobutton.h>
23#endif
24#if QT_CONFIG(toolbutton)
25#include <qtoolbutton.h>
26#endif
27#if QT_CONFIG(menu)
28#include <qmenu.h>
29#endif
30#if QT_CONFIG(label)
31#include <qlabel.h>
32#endif
33#if QT_CONFIG(groupbox)
34#include <qgroupbox.h>
35#endif
36#if QT_CONFIG(lcdnumber)
37#include <qlcdnumber.h>
38#endif
39#if QT_CONFIG(lineedit)
40#include <qlineedit.h>
41#include <private/qlineedit_p.h>
42#endif
43#ifndef QT_NO_PICTURE
44#include <QtGui/qpicture.h>
45#endif
46#if QT_CONFIG(messagebox)
47#include <qmessagebox.h>
48#endif
49#include <qstyle.h>
50#include <qstyleoption.h>
51#include <qtextdocument.h>
52#include <qwindow.h>
53#include <private/qwindowcontainer_p.h>
54#include <QtCore/qvarlengtharray.h>
55#include <QtGui/qvalidator.h>
56
57#ifdef Q_OS_MAC
58#include <qfocusframe.h>
59#endif
60
61QT_BEGIN_NAMESPACE
62
63using namespace Qt::StringLiterals;
64
65#if QT_CONFIG(accessibility)
66
67QWidgetList _q_ac_childWidgets(const QWidget *widget);
68
69QString qt_accStripAmp(const QString &text);
70QString qt_accHotKey(const QString &text);
71
72#if QT_CONFIG(abstractbutton)
73/*!
74 \class QAccessibleButton
75 \brief The QAccessibleButton class implements the QAccessibleInterface for button type widgets.
76 \internal
77
78 \ingroup accessibility
79*/
80
81/*!
82 Creates a QAccessibleButton object for \a w.
83*/
84QAccessibleButton::QAccessibleButton(QWidget *w)
85: QAccessibleWidget(w)
86{
87 Q_ASSERT(button());
88
89 // FIXME: The checkable state of the button is dynamic,
90 // while we only update the controlling signal once :(
91 if (button()->isCheckable())
92 addControllingSignal(signal: "toggled(bool)"_L1);
93 else
94 addControllingSignal(signal: "clicked()"_L1);
95}
96
97/*! Returns the button. */
98QAbstractButton *QAccessibleButton::button() const
99{
100 return qobject_cast<QAbstractButton*>(object: object());
101}
102
103/*! \reimp */
104QString QAccessibleButton::text(QAccessible::Text t) const
105{
106 QString str;
107 switch (t) {
108 case QAccessible::Accelerator:
109 {
110#if QT_CONFIG(shortcut) && QT_CONFIG(pushbutton)
111 QPushButton *pb = qobject_cast<QPushButton*>(object: object());
112 if (pb && pb->isDefault())
113 str = QKeySequence(Qt::Key_Enter).toString(format: QKeySequence::NativeText);
114#endif
115 if (str.isEmpty())
116 str = qt_accHotKey(text: button()->text());
117 }
118 break;
119 case QAccessible::Name:
120 str = widget()->accessibleName();
121 if (str.isEmpty())
122 str = qt_accStripAmp(text: button()->text());
123 break;
124 default:
125 break;
126 }
127 if (str.isEmpty())
128 str = QAccessibleWidget::text(t);
129 return str;
130}
131
132QAccessible::State QAccessibleButton::state() const
133{
134 QAccessible::State state = QAccessibleWidget::state();
135
136 QAbstractButton *b = button();
137#if QT_CONFIG(checkbox)
138 QCheckBox *cb = qobject_cast<QCheckBox *>(object: b);
139#endif
140 if (b->isCheckable())
141 state.checkable = true;
142 if (b->isChecked())
143 state.checked = true;
144#if QT_CONFIG(checkbox)
145 if (cb && cb->checkState() == Qt::PartiallyChecked)
146 state.checkStateMixed = true;
147#endif
148 if (b->isDown())
149 state.pressed = true;
150#if QT_CONFIG(pushbutton)
151 QPushButton *pb = qobject_cast<QPushButton*>(object: b);
152 if (pb) {
153 if (pb->isDefault())
154 state.defaultButton = true;
155#if QT_CONFIG(menu)
156 if (pb->menu())
157 state.hasPopup = true;
158#endif
159 }
160#endif
161
162 return state;
163}
164
165QRect QAccessibleButton::rect() const
166{
167 QAbstractButton *ab = button();
168 if (!ab->isVisible())
169 return QRect();
170
171#if QT_CONFIG(checkbox)
172 if (QCheckBox *cb = qobject_cast<QCheckBox *>(object: ab)) {
173 QPoint wpos = cb->mapToGlobal(QPoint(0, 0));
174 QStyleOptionButton opt;
175 cb->initStyleOption(option: &opt);
176 return cb->style()->subElementRect(subElement: QStyle::SE_CheckBoxClickRect, option: &opt, widget: cb).translated(p: wpos);
177 }
178#endif
179#if QT_CONFIG(radiobutton)
180 else if (QRadioButton *rb = qobject_cast<QRadioButton *>(object: ab)) {
181 QPoint wpos = rb->mapToGlobal(QPoint(0, 0));
182 QStyleOptionButton opt;
183 rb->initStyleOption(button: &opt);
184 return rb->style()->subElementRect(subElement: QStyle::SE_RadioButtonClickRect, option: &opt, widget: rb).translated(p: wpos);
185 }
186#endif
187 return QAccessibleWidget::rect();
188}
189
190QAccessible::Role QAccessibleButton::role() const
191{
192 QAbstractButton *ab = button();
193
194#if QT_CONFIG(menu)
195 if (QPushButton *pb = qobject_cast<QPushButton*>(object: ab)) {
196 if (pb->menu())
197 return QAccessible::ButtonMenu;
198 }
199#endif
200
201 if (ab->isCheckable())
202 return ab->autoExclusive() ? QAccessible::RadioButton : QAccessible::CheckBox;
203
204 return QAccessible::Button;
205}
206
207QStringList QAccessibleButton::actionNames() const
208{
209 QStringList names;
210 if (widget()->isEnabled()) {
211 switch (role()) {
212 case QAccessible::ButtonMenu:
213 names << showMenuAction();
214 break;
215 case QAccessible::RadioButton:
216 names << toggleAction();
217 break;
218 default:
219 if (button()->isCheckable())
220 names << toggleAction();
221 names << pressAction();
222 break;
223 }
224 }
225 names << QAccessibleWidget::actionNames();
226 return names;
227}
228
229void QAccessibleButton::doAction(const QString &actionName)
230{
231 if (!widget()->isEnabled())
232 return;
233 if (actionName == pressAction() ||
234 actionName == showMenuAction()) {
235#if QT_CONFIG(menu)
236 QPushButton *pb = qobject_cast<QPushButton*>(object: object());
237 if (pb && pb->menu())
238 pb->showMenu();
239 else
240#endif
241 button()->animateClick();
242 } else if (actionName == toggleAction()) {
243 button()->toggle();
244 } else {
245 QAccessibleWidget::doAction(actionName);
246 }
247}
248
249QStringList QAccessibleButton::keyBindingsForAction(const QString &actionName) const
250{
251 if (actionName == pressAction()) {
252#ifndef QT_NO_SHORTCUT
253 return QStringList() << button()->shortcut().toString();
254#endif
255 }
256 return QStringList();
257}
258#endif // QT_CONFIG(abstractbutton)
259
260#if QT_CONFIG(toolbutton)
261/*!
262 \class QAccessibleToolButton
263 \brief The QAccessibleToolButton class implements the QAccessibleInterface for tool buttons.
264 \internal
265
266 \ingroup accessibility
267*/
268
269/*!
270 Creates a QAccessibleToolButton object for \a w.
271*/
272QAccessibleToolButton::QAccessibleToolButton(QWidget *w)
273: QAccessibleButton(w)
274{
275 Q_ASSERT(toolButton());
276}
277
278/*! Returns the button. */
279QToolButton *QAccessibleToolButton::toolButton() const
280{
281 return qobject_cast<QToolButton*>(object: object());
282}
283
284/*!
285 Returns \c true if this tool button is a split button.
286*/
287bool QAccessibleToolButton::isSplitButton() const
288{
289#if QT_CONFIG(menu)
290 return toolButton()->menu() && toolButton()->popupMode() == QToolButton::MenuButtonPopup;
291#else
292 return false;
293#endif
294}
295
296QAccessible::State QAccessibleToolButton::state() const
297{
298 QAccessible::State st = QAccessibleButton::state();
299 if (toolButton()->autoRaise())
300 st.hotTracked = true;
301#if QT_CONFIG(menu)
302 if (toolButton()->menu())
303 st.hasPopup = true;
304#endif
305 return st;
306}
307
308int QAccessibleToolButton::childCount() const
309{
310 return isSplitButton() ? 1 : 0;
311}
312
313QAccessible::Role QAccessibleToolButton::role() const
314{
315#if QT_CONFIG(menu)
316 QAbstractButton *ab = button();
317 QToolButton *tb = qobject_cast<QToolButton*>(object: ab);
318 if (!tb->menu())
319 return tb->isCheckable() ? QAccessible::CheckBox : QAccessible::PushButton;
320 else if (tb->popupMode() == QToolButton::DelayedPopup)
321 return QAccessible::ButtonDropDown;
322#endif
323
324 return QAccessible::ButtonMenu;
325}
326
327QAccessibleInterface *QAccessibleToolButton::child(int index) const
328{
329#if QT_CONFIG(menu)
330 if (index == 0 && toolButton()->menu())
331 {
332 return QAccessible::queryAccessibleInterface(toolButton()->menu());
333 }
334#else
335 Q_UNUSED(index);
336#endif
337 return nullptr;
338}
339
340/*
341 The three different tool button types can have the following actions:
342| DelayedPopup | ShowMenuAction + (PressedAction || CheckedAction) |
343| MenuButtonPopup | ShowMenuAction + (PressedAction || CheckedAction) |
344| InstantPopup | ShowMenuAction |
345*/
346QStringList QAccessibleToolButton::actionNames() const
347{
348 QStringList names;
349 if (widget()->isEnabled()) {
350#if QT_CONFIG(menu)
351 if (toolButton()->menu())
352 names << showMenuAction();
353 if (toolButton()->popupMode() != QToolButton::InstantPopup)
354 names << QAccessibleButton::actionNames();
355#endif
356 }
357 return names;
358}
359
360void QAccessibleToolButton::doAction(const QString &actionName)
361{
362 if (!widget()->isEnabled())
363 return;
364
365 if (actionName == pressAction()) {
366 button()->click();
367 } else if (actionName == showMenuAction()) {
368#if QT_CONFIG(menu)
369 if (toolButton()->popupMode() != QToolButton::InstantPopup) {
370 toolButton()->setDown(true);
371 toolButton()->showMenu();
372 }
373#endif
374 } else {
375 QAccessibleButton::doAction(actionName);
376 }
377
378}
379
380#endif // QT_CONFIG(toolbutton)
381
382/*!
383 \class QAccessibleDisplay
384 \brief The QAccessibleDisplay class implements the QAccessibleInterface for widgets that display information.
385 \internal
386
387 \ingroup accessibility
388*/
389
390/*!
391 Constructs a QAccessibleDisplay object for \a w.
392 \a role is propagated to the QAccessibleWidget constructor.
393*/
394QAccessibleDisplay::QAccessibleDisplay(QWidget *w, QAccessible::Role role)
395: QAccessibleWidget(w, role)
396{
397}
398
399QAccessible::Role QAccessibleDisplay::role() const
400{
401#if QT_CONFIG(label)
402 QLabel *l = qobject_cast<QLabel*>(object: object());
403 if (l) {
404 if (!l->pixmap().isNull())
405 return QAccessible::Graphic;
406#ifndef QT_NO_PICTURE
407 if (!l->picture().isNull())
408 return QAccessible::Graphic;
409#endif
410#if QT_CONFIG(movie)
411 if (l->movie())
412 return QAccessible::Animation;
413#endif
414#if QT_CONFIG(progressbar)
415 } else if (qobject_cast<QProgressBar*>(object: object())) {
416 return QAccessible::ProgressBar;
417#endif
418#if QT_CONFIG(statusbar)
419 } else if (qobject_cast<QStatusBar*>(object: object())) {
420 return QAccessible::StatusBar;
421#endif
422 }
423#endif
424 return QAccessibleWidget::role();
425}
426
427QAccessible::State QAccessibleDisplay::state() const
428{
429 QAccessible::State s = QAccessibleWidget::state();
430 s.readOnly = true;
431 return s;
432}
433
434QString QAccessibleDisplay::text(QAccessible::Text t) const
435{
436 QString str;
437 switch (t) {
438 case QAccessible::Name:
439 str = widget()->accessibleName();
440 if (str.isEmpty()) {
441 if (false) {
442#if QT_CONFIG(label)
443 } else if (qobject_cast<QLabel*>(object: object())) {
444 QLabel *label = qobject_cast<QLabel*>(object: object());
445 str = label->text();
446#ifndef QT_NO_TEXTHTMLPARSER
447 if (label->textFormat() == Qt::RichText
448 || (label->textFormat() == Qt::AutoText && Qt::mightBeRichText(str))) {
449 QTextDocument doc;
450 doc.setHtml(str);
451 str = doc.toPlainText();
452 }
453#endif
454#ifndef QT_NO_SHORTCUT
455 if (label->buddy())
456 str = qt_accStripAmp(text: str);
457#endif
458#endif // QT_CONFIG(label)
459#if QT_CONFIG(lcdnumber)
460 } else if (qobject_cast<QLCDNumber*>(object: object())) {
461 QLCDNumber *l = qobject_cast<QLCDNumber*>(object: object());
462 if (l->digitCount())
463 str = QString::number(l->value());
464 else
465 str = QString::number(l->intValue());
466#endif
467#if QT_CONFIG(statusbar)
468 } else if (qobject_cast<QStatusBar*>(object: object())) {
469 return qobject_cast<QStatusBar*>(object: object())->currentMessage();
470#endif
471 }
472 }
473 break;
474 case QAccessible::Value:
475#if QT_CONFIG(progressbar)
476 if (qobject_cast<QProgressBar*>(object: object()))
477 str = QString::number(qobject_cast<QProgressBar*>(object: object())->value());
478#endif
479 break;
480 default:
481 break;
482 }
483 if (str.isEmpty())
484 str = QAccessibleWidget::text(t);
485 return str;
486}
487
488/*! \reimp */
489QList<QPair<QAccessibleInterface *, QAccessible::Relation>>
490QAccessibleDisplay::relations(QAccessible::Relation match /* = QAccessible::AllRelations */) const
491{
492 QList<QPair<QAccessibleInterface *, QAccessible::Relation>> rels =
493 QAccessibleWidget::relations(match);
494# if QT_CONFIG(shortcut) && QT_CONFIG(label)
495 if (match & QAccessible::Labelled) {
496 if (QLabel *label = qobject_cast<QLabel*>(object: object())) {
497 const QAccessible::Relation rel = QAccessible::Labelled;
498 if (QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(label->buddy()))
499 rels.append(t: qMakePair(value1&: iface, value2: rel));
500 }
501 }
502#endif
503 return rels;
504}
505
506void *QAccessibleDisplay::interface_cast(QAccessible::InterfaceType t)
507{
508 if (t == QAccessible::ImageInterface)
509 return static_cast<QAccessibleImageInterface*>(this);
510 return QAccessibleWidget::interface_cast(t);
511}
512
513/*! \internal */
514QString QAccessibleDisplay::imageDescription() const
515{
516#if QT_CONFIG(tooltip)
517 return widget()->toolTip();
518#else
519 return QString();
520#endif
521}
522
523/*! \internal */
524QSize QAccessibleDisplay::imageSize() const
525{
526#if QT_CONFIG(label)
527 QLabel *label = qobject_cast<QLabel *>(object: widget());
528 if (!label)
529#endif
530 return QSize();
531#if QT_CONFIG(label)
532 return label->pixmap().size();
533#endif
534}
535
536/*! \internal */
537QPoint QAccessibleDisplay::imagePosition() const
538{
539#if QT_CONFIG(label)
540 QLabel *label = qobject_cast<QLabel *>(object: widget());
541 if (!label)
542#endif
543 return QPoint();
544#if QT_CONFIG(label)
545 if (label->pixmap().isNull())
546 return QPoint();
547
548 return QPoint(label->mapToGlobal(label->pos()));
549#endif
550}
551
552#if QT_CONFIG(groupbox)
553QAccessibleGroupBox::QAccessibleGroupBox(QWidget *w)
554: QAccessibleWidget(w)
555{
556}
557
558QGroupBox* QAccessibleGroupBox::groupBox() const
559{
560 return static_cast<QGroupBox *>(widget());
561}
562
563QString QAccessibleGroupBox::text(QAccessible::Text t) const
564{
565 QString txt = QAccessibleWidget::text(t);
566
567 if (txt.isEmpty()) {
568 switch (t) {
569 case QAccessible::Name:
570 txt = qt_accStripAmp(text: groupBox()->title());
571 break;
572#if QT_CONFIG(tooltip)
573 case QAccessible::Description:
574 txt = groupBox()->toolTip();
575 break;
576#endif
577 case QAccessible::Accelerator:
578 txt = qt_accHotKey(text: groupBox()->title());
579 break;
580 default:
581 break;
582 }
583 }
584
585 return txt;
586}
587
588QAccessible::State QAccessibleGroupBox::state() const
589{
590 QAccessible::State st = QAccessibleWidget::state();
591 st.checkable = groupBox()->isCheckable();
592 st.checked = groupBox()->isChecked();
593 return st;
594}
595
596QAccessible::Role QAccessibleGroupBox::role() const
597{
598 return groupBox()->isCheckable() ? QAccessible::CheckBox : QAccessible::Grouping;
599}
600
601QList<QPair<QAccessibleInterface *, QAccessible::Relation>>
602QAccessibleGroupBox::relations(QAccessible::Relation match /* = QAccessible::AllRelations */) const
603{
604 QList<QPair<QAccessibleInterface *, QAccessible::Relation>> rels =
605 QAccessibleWidget::relations(match);
606
607 if ((match & QAccessible::Labelled) && (!groupBox()->title().isEmpty())) {
608 const QList<QWidget*> kids = _q_ac_childWidgets(widget: widget());
609 for (QWidget *kid : kids) {
610 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(kid);
611 if (iface)
612 rels.append(t: qMakePair(value1&: iface, value2: QAccessible::Relation(QAccessible::Labelled)));
613 }
614 }
615 return rels;
616}
617
618QStringList QAccessibleGroupBox::actionNames() const
619{
620 QStringList actions = QAccessibleWidget::actionNames();
621
622 if (groupBox()->isCheckable()) {
623 actions.prepend(t: QAccessibleActionInterface::toggleAction());
624 }
625 return actions;
626}
627
628void QAccessibleGroupBox::doAction(const QString &actionName)
629{
630 if (actionName == QAccessibleActionInterface::toggleAction())
631 groupBox()->setChecked(!groupBox()->isChecked());
632}
633
634QStringList QAccessibleGroupBox::keyBindingsForAction(const QString &) const
635{
636 return QStringList();
637}
638
639#endif
640
641#if QT_CONFIG(lineedit)
642/*!
643 \class QAccessibleLineEdit
644 \brief The QAccessibleLineEdit class implements the QAccessibleInterface for widgets with editable text
645 \internal
646
647 \ingroup accessibility
648*/
649
650/*!
651 Constructs a QAccessibleLineEdit object for \a w.
652 \a name is propagated to the QAccessibleWidget constructor.
653*/
654QAccessibleLineEdit::QAccessibleLineEdit(QWidget *w, const QString &name)
655: QAccessibleWidget(w, QAccessible::EditableText, name)
656{
657 addControllingSignal(signal: "textChanged(const QString&)"_L1);
658 addControllingSignal(signal: "returnPressed()"_L1);
659}
660
661/*! Returns the line edit. */
662QLineEdit *QAccessibleLineEdit::lineEdit() const
663{
664 return qobject_cast<QLineEdit*>(object: object());
665}
666
667QString QAccessibleLineEdit::text(QAccessible::Text t) const
668{
669 QString str;
670 switch (t) {
671 case QAccessible::Value:
672 if (lineEdit()->echoMode() == QLineEdit::Normal)
673 str = lineEdit()->text();
674 else if (lineEdit()->echoMode() != QLineEdit::NoEcho)
675 str = QString(lineEdit()->text().size(), QChar::fromLatin1(c: '*'));
676 break;
677 default:
678 break;
679 }
680 if (str.isEmpty())
681 str = QAccessibleWidget::text(t);
682 if (str.isEmpty() && t == QAccessible::Description)
683 str = lineEdit()->placeholderText();
684 return str;
685}
686
687void QAccessibleLineEdit::setText(QAccessible::Text t, const QString &text)
688{
689 if (t != QAccessible::Value) {
690 QAccessibleWidget::setText(t, text);
691 return;
692 }
693
694 QString newText = text;
695#if QT_CONFIG(validator)
696 if (lineEdit()->validator()) {
697 int pos = 0;
698 if (lineEdit()->validator()->validate(newText, pos) != QValidator::Acceptable)
699 return;
700 }
701#endif
702 lineEdit()->setText(newText);
703}
704
705QAccessible::State QAccessibleLineEdit::state() const
706{
707 QAccessible::State state = QAccessibleWidget::state();
708
709 QLineEdit *l = lineEdit();
710 state.editable = true;
711 if (l->isReadOnly())
712 state.readOnly = true;
713
714 if (l->echoMode() != QLineEdit::Normal)
715 state.passwordEdit = true;
716
717 state.selectableText = true;
718 return state;
719}
720
721void *QAccessibleLineEdit::interface_cast(QAccessible::InterfaceType t)
722{
723 if (t == QAccessible::TextInterface)
724 return static_cast<QAccessibleTextInterface*>(this);
725 if (t == QAccessible::EditableTextInterface)
726 return static_cast<QAccessibleEditableTextInterface*>(this);
727 return QAccessibleWidget::interface_cast(t);
728}
729
730void QAccessibleLineEdit::addSelection(int startOffset, int endOffset)
731{
732 setSelection(selectionIndex: 0, startOffset, endOffset);
733}
734
735QString QAccessibleLineEdit::attributes(int offset, int *startOffset, int *endOffset) const
736{
737 // QLineEdit doesn't have text attributes
738 *startOffset = *endOffset = offset;
739 return QString();
740}
741
742int QAccessibleLineEdit::cursorPosition() const
743{
744 return lineEdit()->cursorPosition();
745}
746
747QRect QAccessibleLineEdit::characterRect(int offset) const
748{
749 int x = lineEdit()->d_func()->control->cursorToX(cursor: offset);
750 int y = lineEdit()->textMargins().top();
751 QFontMetrics fm(lineEdit()->font());
752 const QString ch = text(startOffset: offset, endOffset: offset + 1);
753 if (ch.isEmpty())
754 return QRect();
755 int w = fm.horizontalAdvance(ch);
756 int h = fm.height();
757 QRect r(x, y, w, h);
758 r.moveTo(p: lineEdit()->mapToGlobal(r.topLeft()));
759 return r;
760}
761
762int QAccessibleLineEdit::selectionCount() const
763{
764 return lineEdit()->hasSelectedText() ? 1 : 0;
765}
766
767int QAccessibleLineEdit::offsetAtPoint(const QPoint &point) const
768{
769 QPoint p = lineEdit()->mapFromGlobal(point);
770
771 return lineEdit()->cursorPositionAt(pos: p);
772}
773
774void QAccessibleLineEdit::selection(int selectionIndex, int *startOffset, int *endOffset) const
775{
776 *startOffset = *endOffset = 0;
777 if (selectionIndex != 0)
778 return;
779
780 *startOffset = lineEdit()->selectionStart();
781 *endOffset = *startOffset + lineEdit()->selectedText().size();
782}
783
784QString QAccessibleLineEdit::text(int startOffset, int endOffset) const
785{
786 if (startOffset > endOffset)
787 return QString();
788
789 if (lineEdit()->echoMode() != QLineEdit::Normal)
790 return QString();
791
792 return lineEdit()->text().mid(position: startOffset, n: endOffset - startOffset);
793}
794
795QString QAccessibleLineEdit::textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType,
796 int *startOffset, int *endOffset) const
797{
798 if (lineEdit()->echoMode() != QLineEdit::Normal) {
799 *startOffset = *endOffset = -1;
800 return QString();
801 }
802 if (offset == -2)
803 offset = cursorPosition();
804 return QAccessibleTextInterface::textBeforeOffset(offset, boundaryType, startOffset, endOffset);
805}
806
807QString QAccessibleLineEdit::textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType,
808 int *startOffset, int *endOffset) const
809{
810 if (lineEdit()->echoMode() != QLineEdit::Normal) {
811 *startOffset = *endOffset = -1;
812 return QString();
813 }
814 if (offset == -2)
815 offset = cursorPosition();
816 return QAccessibleTextInterface::textAfterOffset(offset, boundaryType, startOffset, endOffset);
817}
818
819QString QAccessibleLineEdit::textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType,
820 int *startOffset, int *endOffset) const
821{
822 if (lineEdit()->echoMode() != QLineEdit::Normal) {
823 *startOffset = *endOffset = -1;
824 return QString();
825 }
826 if (offset == -2)
827 offset = cursorPosition();
828 return QAccessibleTextInterface::textAtOffset(offset, boundaryType, startOffset, endOffset);
829}
830
831void QAccessibleLineEdit::removeSelection(int selectionIndex)
832{
833 if (selectionIndex != 0)
834 return;
835
836 lineEdit()->deselect();
837}
838
839void QAccessibleLineEdit::setCursorPosition(int position)
840{
841 lineEdit()->setCursorPosition(position);
842}
843
844void QAccessibleLineEdit::setSelection(int selectionIndex, int startOffset, int endOffset)
845{
846 if (selectionIndex != 0)
847 return;
848
849 lineEdit()->setSelection(startOffset, endOffset - startOffset);
850}
851
852int QAccessibleLineEdit::characterCount() const
853{
854 return lineEdit()->text().size();
855}
856
857void QAccessibleLineEdit::scrollToSubstring(int startIndex, int endIndex)
858{
859 lineEdit()->setCursorPosition(endIndex);
860 lineEdit()->setCursorPosition(startIndex);
861}
862
863void QAccessibleLineEdit::deleteText(int startOffset, int endOffset)
864{
865 lineEdit()->setText(lineEdit()->text().remove(i: startOffset, len: endOffset - startOffset));
866}
867
868void QAccessibleLineEdit::insertText(int offset, const QString &text)
869{
870 lineEdit()->setText(lineEdit()->text().insert(i: offset, s: text));
871}
872
873void QAccessibleLineEdit::replaceText(int startOffset, int endOffset, const QString &text)
874{
875 lineEdit()->setText(lineEdit()->text().replace(i: startOffset, len: endOffset - startOffset, after: text));
876}
877
878#endif // QT_CONFIG(lineedit)
879
880#if QT_CONFIG(progressbar)
881QAccessibleProgressBar::QAccessibleProgressBar(QWidget *o)
882 : QAccessibleDisplay(o)
883{
884 Q_ASSERT(progressBar());
885}
886
887void *QAccessibleProgressBar::interface_cast(QAccessible::InterfaceType t)
888{
889 if (t == QAccessible::ValueInterface)
890 return static_cast<QAccessibleValueInterface*>(this);
891 return QAccessibleDisplay::interface_cast(t);
892}
893
894QVariant QAccessibleProgressBar::currentValue() const
895{
896 return progressBar()->value();
897}
898
899QVariant QAccessibleProgressBar::maximumValue() const
900{
901 return progressBar()->maximum();
902}
903
904QVariant QAccessibleProgressBar::minimumValue() const
905{
906 return progressBar()->minimum();
907}
908
909QVariant QAccessibleProgressBar::minimumStepSize() const
910{
911 // This is arbitrary since any value between min and max is valid.
912 // Some screen readers (orca use it to calculate how many digits to display though,
913 // so it makes sense to return a "sensible" value. Providing 100 increments seems ok.
914 return (progressBar()->maximum() - progressBar()->minimum()) / 100.0;
915}
916
917QProgressBar *QAccessibleProgressBar::progressBar() const
918{
919 return qobject_cast<QProgressBar *>(object: object());
920}
921#endif
922
923
924QAccessibleWindowContainer::QAccessibleWindowContainer(QWidget *w)
925 : QAccessibleWidget(w)
926{
927}
928
929int QAccessibleWindowContainer::childCount() const
930{
931 if (container()->containedWindow() && QAccessible::queryAccessibleInterface(container()->containedWindow()))
932 return 1;
933 return 0;
934}
935
936int QAccessibleWindowContainer::indexOfChild(const QAccessibleInterface *child) const
937{
938 if (child->object() == container()->containedWindow())
939 return 0;
940 return -1;
941}
942
943QAccessibleInterface *QAccessibleWindowContainer::child(int i) const
944{
945 if (i == 0)
946 return QAccessible::queryAccessibleInterface(container()->containedWindow());
947 return nullptr;
948}
949
950QWindowContainer *QAccessibleWindowContainer::container() const
951{
952 return static_cast<QWindowContainer *>(widget());
953}
954
955#if QT_CONFIG(messagebox)
956/*!
957 \internal
958 Implements QAccessibleWidget for QMessageBox
959*/
960QAccessibleMessageBox::QAccessibleMessageBox(QWidget *widget)
961 : QAccessibleWidget(widget, QAccessible::AlertMessage)
962{
963 Q_ASSERT(qobject_cast<QMessageBox *>(widget));
964}
965
966QMessageBox *QAccessibleMessageBox::messageBox() const
967{
968 return static_cast<QMessageBox *>(widget());
969}
970
971QString QAccessibleMessageBox::text(QAccessible::Text t) const
972{
973 QString str;
974
975 switch (t) {
976 case QAccessible::Name:
977 str = QAccessibleWidget::text(t);
978 if (str.isEmpty()) // implies no title text is set
979 str = messageBox()->text();
980 break;
981 case QAccessible::Description:
982 str = widget()->accessibleDescription();
983 break;
984 case QAccessible::Value:
985 str = messageBox()->text();
986 break;
987 case QAccessible::Help:
988 str = messageBox()->informativeText();
989 break;
990 default:
991 break;
992 }
993
994 return str;
995}
996#endif
997
998#endif // QT_CONFIG(accessibility)
999
1000QT_END_NAMESPACE
1001

source code of qtbase/src/widgets/accessible/simplewidgets.cpp