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