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