source: trunk/src/plugins/accessible/widgets/qaccessiblewidgets.cpp@ 603

Last change on this file since 603 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 47.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the plugins of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qaccessiblewidgets.h"
43#include "qabstracttextdocumentlayout.h"
44#include "qapplication.h"
45#include "qclipboard.h"
46#include "qtextedit.h"
47#include "private/qtextedit_p.h"
48#include "qtextdocument.h"
49#include "qtextobject.h"
50#include "qscrollbar.h"
51#include "qdebug.h"
52#include <QApplication>
53#include <QStackedWidget>
54#include <QToolBox>
55#include <QMdiArea>
56#include <QMdiSubWindow>
57#include <QWorkspace>
58#include <QDialogButtonBox>
59#include <limits.h>
60#include <QRubberBand>
61#include <QTextBrowser>
62#include <QCalendarWidget>
63#include <QAbstractItemView>
64#include <QDockWidget>
65#include <QMainWindow>
66#include <QAbstractButton>
67#include <private/qdockwidget_p.h>
68#include <QtGui/QFocusFrame>
69
70#ifndef QT_NO_ACCESSIBILITY
71
72QT_BEGIN_NAMESPACE
73
74using namespace QAccessible2;
75
76QList<QWidget*> childWidgets(const QWidget *widget, bool includeTopLevel)
77{
78 if (widget == 0)
79 return QList<QWidget*>();
80 QList<QObject*> list = widget->children();
81 QList<QWidget*> widgets;
82 for (int i = 0; i < list.size(); ++i) {
83 QWidget *w = qobject_cast<QWidget *>(list.at(i));
84 if (!w)
85 continue;
86 QString objectName = w->objectName();
87 if ((includeTopLevel || !w->isWindow())
88 && !qobject_cast<QFocusFrame*>(w)
89 && !qobject_cast<QMenu*>(w)
90 && objectName != QLatin1String("qt_rubberband")
91 && objectName != QLatin1String("qt_qmainwindow_extended_splitter")) {
92 widgets.append(w);
93 }
94 }
95 return widgets;
96}
97
98static inline int distance(QWidget *source, QWidget *target,
99 QAccessible::RelationFlag relation)
100{
101 if (!source || !target)
102 return -1;
103
104 int returnValue = -1;
105 switch (relation) {
106 case QAccessible::Up:
107 if (target->y() <= source->y())
108 returnValue = source->y() - target->y();
109 break;
110 case QAccessible::Down:
111 if (target->y() >= source->y() + source->height())
112 returnValue = target->y() - (source->y() + source->height());
113 break;
114 case QAccessible::Right:
115 if (target->x() >= source->x() + source->width())
116 returnValue = target->x() - (source->x() + source->width());
117 break;
118 case QAccessible::Left:
119 if (target->x() <= source->x())
120 returnValue = source->x() - target->x();
121 break;
122 default:
123 break;
124 }
125 return returnValue;
126}
127
128static inline QWidget *mdiAreaNavigate(QWidget *area,
129 QAccessible::RelationFlag relation, int entry)
130{
131#if defined(QT_NO_MDIAREA) && defined(QT_NO_WORKSPACE)
132 Q_UNUSED(area);
133#endif
134#ifndef QT_NO_MDIAREA
135 const QMdiArea *mdiArea = qobject_cast<QMdiArea *>(area);
136#endif
137#ifndef QT_NO_WORKSPACE
138 const QWorkspace *workspace = qobject_cast<QWorkspace *>(area);
139#endif
140 if (true
141#ifndef QT_NO_MDIAREA
142 && !mdiArea
143#endif
144#ifndef QT_NO_WORKSPACE
145 && !workspace
146#endif
147 )
148 return 0;
149
150 QWidgetList windows;
151#ifndef QT_NO_MDIAREA
152 if (mdiArea) {
153 foreach (QMdiSubWindow *window, mdiArea->subWindowList())
154 windows.append(window);
155 } else
156#endif
157 {
158#ifndef QT_NO_WORKSPACE
159 foreach (QWidget *window, workspace->windowList())
160 windows.append(window->parentWidget());
161#endif
162 }
163
164 if (windows.isEmpty() || entry < 1 || entry > windows.count())
165 return 0;
166
167 QWidget *source = windows.at(entry - 1);
168 QMap<int, QWidget *> candidates;
169 foreach (QWidget *window, windows) {
170 if (source == window)
171 continue;
172 int candidateDistance = distance(source, window, relation);
173 if (candidateDistance >= 0)
174 candidates.insert(candidateDistance, window);
175 }
176
177 int minimumDistance = INT_MAX;
178 QWidget *target = 0;
179 foreach (QWidget *candidate, candidates.values()) {
180 switch (relation) {
181 case QAccessible::Up:
182 case QAccessible::Down:
183 if (qAbs(candidate->x() - source->x()) < minimumDistance) {
184 target = candidate;
185 minimumDistance = qAbs(candidate->x() - source->x());
186 }
187 break;
188 case QAccessible::Left:
189 case QAccessible::Right:
190 if (qAbs(candidate->y() - source->y()) < minimumDistance) {
191 target = candidate;
192 minimumDistance = qAbs(candidate->y() - source->y());
193 }
194 break;
195 default:
196 break;
197 }
198 if (minimumDistance == 0)
199 break;
200 }
201
202#ifndef QT_NO_WORKSPACE
203 if (workspace) {
204 foreach (QWidget *widget, workspace->windowList()) {
205 if (widget->parentWidget() == target)
206 target = widget;
207 }
208 }
209#endif
210 return target;
211}
212
213#ifndef QT_NO_TEXTEDIT
214
215/*!
216 \class QAccessibleTextEdit
217 \brief The QAccessibleTextEdit class implements the QAccessibleInterface for richtext editors.
218 \internal
219*/
220
221static QTextBlock qTextBlockAt(const QTextDocument *doc, int pos)
222{
223 Q_ASSERT(pos >= 0);
224
225 QTextBlock block = doc->begin();
226 int i = 0;
227 while (block.isValid() && i < pos) {
228 block = block.next();
229 ++i;
230 }
231 return block;
232}
233
234static int qTextBlockPosition(QTextBlock block)
235{
236 int child = 0;
237 while (block.isValid()) {
238 block = block.previous();
239 ++child;
240 }
241
242 return child;
243}
244
245/*!
246 \fn QAccessibleTextEdit::QAccessibleTextEdit(QWidget* widget)
247
248 Constructs a QAccessibleTextEdit object for a \a widget.
249*/
250QAccessibleTextEdit::QAccessibleTextEdit(QWidget *o)
251: QAccessibleWidgetEx(o, EditableText)
252{
253 Q_ASSERT(widget()->inherits("QTextEdit"));
254 childOffset = QAccessibleWidgetEx::childCount();
255}
256
257/*! Returns the text edit. */
258QTextEdit *QAccessibleTextEdit::textEdit() const
259{
260 return static_cast<QTextEdit *>(widget());
261}
262
263QRect QAccessibleTextEdit::rect(int child) const
264{
265 if (child <= childOffset)
266 return QAccessibleWidgetEx::rect(child);
267
268 QTextEdit *edit = textEdit();
269 QTextBlock block = qTextBlockAt(edit->document(), child - childOffset - 1);
270 if (!block.isValid())
271 return QRect();
272
273 QRect rect = edit->document()->documentLayout()->blockBoundingRect(block).toRect();
274 rect.translate(-edit->horizontalScrollBar()->value(), -edit->verticalScrollBar()->value());
275
276 rect = edit->viewport()->rect().intersect(rect);
277 if (rect.isEmpty())
278 return QRect();
279
280 return rect.translated(edit->viewport()->mapToGlobal(QPoint(0, 0)));
281}
282
283int QAccessibleTextEdit::childAt(int x, int y) const
284{
285 QTextEdit *edit = textEdit();
286 if (!edit->isVisible())
287 return -1;
288
289 QPoint point = edit->viewport()->mapFromGlobal(QPoint(x, y));
290 QTextBlock block = edit->cursorForPosition(point).block();
291 if (block.isValid())
292 return qTextBlockPosition(block) + childOffset;
293
294 return QAccessibleWidgetEx::childAt(x, y);
295}
296
297/*! \reimp */
298QString QAccessibleTextEdit::text(Text t, int child) const
299{
300 if (t == Value) {
301 if (child > childOffset)
302 return qTextBlockAt(textEdit()->document(), child - childOffset - 1).text();
303 if (!child)
304 return textEdit()->toPlainText();
305 }
306
307 return QAccessibleWidgetEx::text(t, child);
308}
309
310/*! \reimp */
311void QAccessibleTextEdit::setText(Text t, int child, const QString &text)
312{
313 if (t != Value || (child > 0 && child <= childOffset)) {
314 QAccessibleWidgetEx::setText(t, child, text);
315 return;
316 }
317 if (textEdit()->isReadOnly())
318 return;
319
320 if (!child) {
321 textEdit()->setText(text);
322 return;
323 }
324 QTextBlock block = qTextBlockAt(textEdit()->document(), child - childOffset - 1);
325 if (!block.isValid())
326 return;
327
328 QTextCursor cursor(block);
329 cursor.select(QTextCursor::BlockUnderCursor);
330 cursor.insertText(text);
331}
332
333/*! \reimp */
334QAccessible::Role QAccessibleTextEdit::role(int child) const
335{
336 if (child > childOffset)
337 return EditableText;
338 return QAccessibleWidgetEx::role(child);
339}
340
341QVariant QAccessibleTextEdit::invokeMethodEx(QAccessible::Method method, int child,
342 const QVariantList &params)
343{
344 if (child)
345 return QVariant();
346
347 switch (method) {
348 case ListSupportedMethods: {
349 QSet<QAccessible::Method> set;
350 set << ListSupportedMethods << SetCursorPosition << GetCursorPosition;
351 return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >(
352 QAccessibleWidgetEx::invokeMethodEx(method, child, params)));
353 }
354 case SetCursorPosition:
355 setCursorPosition(params.value(0).toInt());
356 return true;
357 case GetCursorPosition:
358 return textEdit()->textCursor().position();
359 default:
360 return QAccessibleWidgetEx::invokeMethodEx(method, child, params);
361 }
362}
363
364int QAccessibleTextEdit::childCount() const
365{
366 return childOffset + textEdit()->document()->blockCount();
367}
368#endif // QT_NO_TEXTEDIT
369
370#ifndef QT_NO_STACKEDWIDGET
371// ======================= QAccessibleStackedWidget ======================
372QAccessibleStackedWidget::QAccessibleStackedWidget(QWidget *widget)
373 : QAccessibleWidgetEx(widget, LayeredPane)
374{
375 Q_ASSERT(qobject_cast<QStackedWidget *>(widget));
376}
377
378QVariant QAccessibleStackedWidget::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
379{
380 return QVariant();
381}
382
383
384int QAccessibleStackedWidget::childAt(int x, int y) const
385{
386 if (!stackedWidget()->isVisible())
387 return -1;
388 QWidget *currentWidget = stackedWidget()->currentWidget();
389 if (!currentWidget)
390 return -1;
391 QPoint position = currentWidget->mapFromGlobal(QPoint(x, y));
392 if (currentWidget->rect().contains(position))
393 return 1;
394 return -1;
395}
396
397int QAccessibleStackedWidget::childCount() const
398{
399 return stackedWidget()->count();
400}
401
402int QAccessibleStackedWidget::indexOfChild(const QAccessibleInterface *child) const
403{
404 if (!child || (stackedWidget()->currentWidget() != child->object()))
405 return -1;
406 return 1;
407}
408
409int QAccessibleStackedWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
410{
411 *target = 0;
412
413 QObject *targetObject = 0;
414 switch (relation) {
415 case Child:
416 if (entry != 1)
417 return -1;
418 targetObject = stackedWidget()->currentWidget();
419 break;
420 default:
421 return QAccessibleWidgetEx::navigate(relation, entry, target);
422 }
423 *target = QAccessible::queryAccessibleInterface(targetObject);
424 return *target ? 0 : -1;
425}
426
427QStackedWidget *QAccessibleStackedWidget::stackedWidget() const
428{
429 return static_cast<QStackedWidget *>(object());
430}
431#endif // QT_NO_STACKEDWIDGET
432
433#ifndef QT_NO_TOOLBOX
434// ======================= QAccessibleToolBox ======================
435QAccessibleToolBox::QAccessibleToolBox(QWidget *widget)
436 : QAccessibleWidgetEx(widget, LayeredPane)
437{
438 Q_ASSERT(qobject_cast<QToolBox *>(widget));
439}
440
441QString QAccessibleToolBox::text(Text textType, int child) const
442{
443 if (textType != Value || child <= 0 || child > toolBox()->count())
444 return QAccessibleWidgetEx::text(textType, child);
445 return toolBox()->itemText(child - 1);
446}
447
448void QAccessibleToolBox::setText(Text textType, int child, const QString &text)
449{
450 if (textType != Value || child <= 0 || child > toolBox()->count()) {
451 QAccessibleWidgetEx::setText(textType, child, text);
452 return;
453 }
454 toolBox()->setItemText(child - 1, text);
455}
456
457QAccessible::State QAccessibleToolBox::state(int child) const
458{
459 QWidget *childWidget = toolBox()->widget(child - 1);
460 if (!childWidget)
461 return QAccessibleWidgetEx::state(child);
462 QAccessible::State childState = QAccessible::Normal;
463 if (toolBox()->currentWidget() == childWidget)
464 childState |= QAccessible::Expanded;
465 else
466 childState |= QAccessible::Collapsed;
467 return childState;
468}
469
470QVariant QAccessibleToolBox::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
471{
472 return QVariant();
473}
474
475int QAccessibleToolBox::childCount() const
476{
477 return toolBox()->count();
478}
479
480int QAccessibleToolBox::indexOfChild(const QAccessibleInterface *child) const
481{
482 if (!child)
483 return -1;
484 QWidget *childWidget = qobject_cast<QWidget *>(child->object());
485 if (!childWidget)
486 return -1;
487 int index = toolBox()->indexOf(childWidget);
488 if (index != -1)
489 ++index;
490 return index;
491}
492
493int QAccessibleToolBox::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
494{
495 *target = 0;
496 if (entry <= 0 || entry > toolBox()->count())
497 return QAccessibleWidgetEx::navigate(relation, entry, target);
498 int index = -1;
499 if (relation == QAccessible::Up)
500 index = entry - 2;
501 else if (relation == QAccessible::Down)
502 index = entry;
503 *target = QAccessible::queryAccessibleInterface(toolBox()->widget(index));
504 return *target ? 0: -1;
505}
506
507QToolBox * QAccessibleToolBox::toolBox() const
508{
509 return static_cast<QToolBox *>(object());
510}
511#endif // QT_NO_TOOLBOX
512
513// ======================= QAccessibleMdiArea ======================
514#ifndef QT_NO_MDIAREA
515QAccessibleMdiArea::QAccessibleMdiArea(QWidget *widget)
516 : QAccessibleWidgetEx(widget, LayeredPane)
517{
518 Q_ASSERT(qobject_cast<QMdiArea *>(widget));
519}
520
521QAccessible::State QAccessibleMdiArea::state(int child) const
522{
523 if (child < 0)
524 return QAccessibleWidgetEx::state(child);
525 if (child == 0)
526 return QAccessible::Normal;
527 QList<QMdiSubWindow *> subWindows = mdiArea()->subWindowList();
528 if (subWindows.isEmpty() || child > subWindows.count())
529 return QAccessibleWidgetEx::state(child);
530 if (subWindows.at(child - 1) == mdiArea()->activeSubWindow())
531 return QAccessible::Focused;
532 return QAccessible::Normal;
533}
534
535QVariant QAccessibleMdiArea::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
536{
537 return QVariant();
538}
539
540int QAccessibleMdiArea::childCount() const
541{
542 return mdiArea()->subWindowList().count();
543}
544
545int QAccessibleMdiArea::indexOfChild(const QAccessibleInterface *child) const
546{
547 if (!child || !child->object() || mdiArea()->subWindowList().isEmpty())
548 return -1;
549 if (QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(child->object())) {
550 int index = mdiArea()->subWindowList().indexOf(window);
551 if (index != -1)
552 return ++index;
553 }
554 return -1;
555}
556
557int QAccessibleMdiArea::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
558{
559 *target = 0;
560 QWidget *targetObject = 0;
561 QList<QMdiSubWindow *> subWindows = mdiArea()->subWindowList();
562 switch (relation) {
563 case Child:
564 if (entry < 1 || subWindows.isEmpty() || entry > subWindows.count())
565 return -1;
566 targetObject = subWindows.at(entry - 1);
567 break;
568 case Up:
569 case Down:
570 case Left:
571 case Right:
572 targetObject = mdiAreaNavigate(mdiArea(), relation, entry);
573 break;
574 default:
575 return QAccessibleWidgetEx::navigate(relation, entry, target);
576 }
577 *target = QAccessible::queryAccessibleInterface(targetObject);
578 return *target ? 0: -1;
579}
580
581QMdiArea *QAccessibleMdiArea::mdiArea() const
582{
583 return static_cast<QMdiArea *>(object());
584}
585
586// ======================= QAccessibleMdiSubWindow ======================
587QAccessibleMdiSubWindow::QAccessibleMdiSubWindow(QWidget *widget)
588 : QAccessibleWidgetEx(widget, QAccessible::Window)
589{
590 Q_ASSERT(qobject_cast<QMdiSubWindow *>(widget));
591}
592
593QString QAccessibleMdiSubWindow::text(Text textType, int child) const
594{
595 if (textType == QAccessible::Name && (child == 0 || child == 1)) {
596 QString title = mdiSubWindow()->windowTitle();
597 title.replace(QLatin1String("[*]"), QLatin1String(""));
598 return title;
599 }
600 return QAccessibleWidgetEx::text(textType, child);
601}
602
603void QAccessibleMdiSubWindow::setText(Text textType, int child, const QString &text)
604{
605 if (textType == QAccessible::Name && (child == 0 || child == 1))
606 mdiSubWindow()->setWindowTitle(text);
607 else
608 QAccessibleWidgetEx::setText(textType, child, text);
609}
610
611QAccessible::State QAccessibleMdiSubWindow::state(int child) const
612{
613 if (child != 0 || !mdiSubWindow()->parent())
614 return QAccessibleWidgetEx::state(child);
615 QAccessible::State state = QAccessible::Normal | QAccessible::Focusable;
616 if (!mdiSubWindow()->isMaximized())
617 state |= (QAccessible::Movable | QAccessible::Sizeable);
618 if (mdiSubWindow()->isAncestorOf(QApplication::focusWidget())
619 || QApplication::focusWidget() == mdiSubWindow())
620 state |= QAccessible::Focused;
621 if (!mdiSubWindow()->isVisible())
622 state |= QAccessible::Invisible;
623 if (!mdiSubWindow()->parentWidget()->contentsRect().contains(mdiSubWindow()->geometry()))
624 state |= QAccessible::Offscreen;
625 if (!mdiSubWindow()->isEnabled())
626 state |= QAccessible::Unavailable;
627 return state;
628}
629
630QVariant QAccessibleMdiSubWindow::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
631{
632 return QVariant();
633}
634
635int QAccessibleMdiSubWindow::childCount() const
636{
637 if (mdiSubWindow()->widget())
638 return 1;
639 return 0;
640}
641
642int QAccessibleMdiSubWindow::indexOfChild(const QAccessibleInterface *child) const
643{
644 if (child && child->object() && child->object() == mdiSubWindow()->widget())
645 return 1;
646 return -1;
647}
648
649int QAccessibleMdiSubWindow::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
650{
651 *target = 0;
652
653 if (!mdiSubWindow()->parent())
654 return QAccessibleWidgetEx::navigate(relation, entry, target);
655
656 QWidget *targetObject = 0;
657 QMdiSubWindow *source = mdiSubWindow();
658 switch (relation) {
659 case Child:
660 if (entry != 1 || !source->widget())
661 return -1;
662 targetObject = source->widget();
663 break;
664 case Up:
665 case Down:
666 case Left:
667 case Right: {
668 if (entry != 0)
669 break;
670 QWidget *parent = source->parentWidget();
671 while (parent && !parent->inherits("QMdiArea"))
672 parent = parent->parentWidget();
673 QMdiArea *mdiArea = qobject_cast<QMdiArea *>(parent);
674 if (!mdiArea)
675 break;
676 int index = mdiArea->subWindowList().indexOf(source);
677 if (index == -1)
678 break;
679 if (QWidget *dest = mdiAreaNavigate(mdiArea, relation, index + 1)) {
680 *target = QAccessible::queryAccessibleInterface(dest);
681 return *target ? 0 : -1;
682 }
683 break;
684 }
685 default:
686 return QAccessibleWidgetEx::navigate(relation, entry, target);
687 }
688 *target = QAccessible::queryAccessibleInterface(targetObject);
689 return *target ? 0: -1;
690}
691
692QRect QAccessibleMdiSubWindow::rect(int child) const
693{
694 if (mdiSubWindow()->isHidden())
695 return QRect();
696 if (!mdiSubWindow()->parent())
697 return QAccessibleWidgetEx::rect(child);
698 const QPoint pos = mdiSubWindow()->mapToGlobal(QPoint(0, 0));
699 if (child == 0)
700 return QRect(pos, mdiSubWindow()->size());
701 if (child == 1 && mdiSubWindow()->widget()) {
702 if (mdiSubWindow()->widget()->isHidden())
703 return QRect();
704 const QRect contentsRect = mdiSubWindow()->contentsRect();
705 return QRect(pos.x() + contentsRect.x(), pos.y() + contentsRect.y(),
706 contentsRect.width(), contentsRect.height());
707 }
708 return QRect();
709}
710
711int QAccessibleMdiSubWindow::childAt(int x, int y) const
712{
713 if (!mdiSubWindow()->isVisible())
714 return -1;
715 if (!mdiSubWindow()->parent())
716 return QAccessibleWidgetEx::childAt(x, y);
717 const QRect globalGeometry = rect(0);
718 if (!globalGeometry.isValid())
719 return -1;
720 const QRect globalChildGeometry = rect(1);
721 if (globalChildGeometry.isValid() && globalChildGeometry.contains(QPoint(x, y)))
722 return 1;
723 if (globalGeometry.contains(QPoint(x, y)))
724 return 0;
725 return -1;
726}
727
728QMdiSubWindow *QAccessibleMdiSubWindow::mdiSubWindow() const
729{
730 return static_cast<QMdiSubWindow *>(object());
731}
732#endif // QT_NO_MDIAREA
733
734// ======================= QAccessibleWorkspace ======================
735#ifndef QT_NO_WORKSPACE
736QAccessibleWorkspace::QAccessibleWorkspace(QWidget *widget)
737 : QAccessibleWidgetEx(widget, LayeredPane)
738{
739 Q_ASSERT(qobject_cast<QWorkspace *>(widget));
740}
741
742QAccessible::State QAccessibleWorkspace::state(int child) const
743{
744 if (child < 0)
745 return QAccessibleWidgetEx::state(child);
746 if (child == 0)
747 return QAccessible::Normal;
748 QWidgetList subWindows = workspace()->windowList();
749 if (subWindows.isEmpty() || child > subWindows.count())
750 return QAccessibleWidgetEx::state(child);
751 if (subWindows.at(child - 1) == workspace()->activeWindow())
752 return QAccessible::Focused;
753 return QAccessible::Normal;
754}
755
756QVariant QAccessibleWorkspace::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
757{
758 return QVariant();
759}
760
761int QAccessibleWorkspace::childCount() const
762{
763 return workspace()->windowList().count();
764}
765
766int QAccessibleWorkspace::indexOfChild(const QAccessibleInterface *child) const
767{
768 if (!child || !child->object() || workspace()->windowList().isEmpty())
769 return -1;
770 if (QWidget *window = qobject_cast<QWidget *>(child->object())) {
771 int index = workspace()->windowList().indexOf(window);
772 if (index != -1)
773 return ++index;
774 }
775 return -1;
776}
777
778int QAccessibleWorkspace::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
779{
780 *target = 0;
781 QWidget *targetObject = 0;
782 QWidgetList subWindows = workspace()->windowList();
783 switch (relation) {
784 case Child:
785 if (entry < 1 || subWindows.isEmpty() || entry > subWindows.count())
786 return -1;
787 targetObject = subWindows.at(entry - 1);
788 break;
789 case Up:
790 case Down:
791 case Left:
792 case Right:
793 targetObject = mdiAreaNavigate(workspace(), relation, entry);
794 break;
795 default:
796 return QAccessibleWidgetEx::navigate(relation, entry, target);
797 }
798 *target = QAccessible::queryAccessibleInterface(targetObject);
799 return *target ? 0: -1;
800}
801
802QWorkspace *QAccessibleWorkspace::workspace() const
803{
804 return static_cast<QWorkspace *>(object());
805}
806#endif
807
808#ifndef QT_NO_DIALOGBUTTONBOX
809// ======================= QAccessibleDialogButtonBox ======================
810QAccessibleDialogButtonBox::QAccessibleDialogButtonBox(QWidget *widget)
811 : QAccessibleWidgetEx(widget, Grouping)
812{
813 Q_ASSERT(qobject_cast<QDialogButtonBox*>(widget));
814}
815
816QVariant QAccessibleDialogButtonBox::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
817{
818 return QVariant();
819}
820#endif // QT_NO_DIALOGBUTTONBOX
821
822#ifndef QT_NO_TEXTBROWSER
823QAccessibleTextBrowser::QAccessibleTextBrowser(QWidget *widget)
824 : QAccessibleTextEdit(widget)
825{
826 Q_ASSERT(qobject_cast<QTextBrowser *>(widget));
827}
828
829QAccessible::Role QAccessibleTextBrowser::role(int child) const
830{
831 if (child != 0)
832 return QAccessibleTextEdit::role(child);
833 return QAccessible::StaticText;
834}
835#endif // QT_NO_TEXTBROWSER
836
837#ifndef QT_NO_CALENDARWIDGET
838// ===================== QAccessibleCalendarWidget ========================
839QAccessibleCalendarWidget::QAccessibleCalendarWidget(QWidget *widget)
840 : QAccessibleWidgetEx(widget, Table)
841{
842 Q_ASSERT(qobject_cast<QCalendarWidget *>(widget));
843}
844
845QVariant QAccessibleCalendarWidget::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
846{
847 return QVariant();
848}
849
850int QAccessibleCalendarWidget::childCount() const
851{
852 return calendarWidget()->isNavigationBarVisible() ? 2 : 1;
853}
854
855int QAccessibleCalendarWidget::indexOfChild(const QAccessibleInterface *child) const
856{
857 if (!child || !child->object() || childCount() <= 0)
858 return -1;
859 if (qobject_cast<QAbstractItemView *>(child->object()))
860 return childCount();
861 return 1;
862}
863
864int QAccessibleCalendarWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
865{
866 *target = 0;
867 if (entry <= 0 || entry > childCount())
868 return QAccessibleWidgetEx::navigate(relation, entry, target);
869 QWidget *targetWidget = 0;
870 switch (relation) {
871 case Child:
872 if (childCount() == 1) {
873 targetWidget = calendarView();
874 } else {
875 if (entry == 1)
876 targetWidget = navigationBar();
877 else
878 targetWidget = calendarView();
879 }
880 break;
881 case Up:
882 if (entry == 2)
883 targetWidget = navigationBar();
884 break;
885 case Down:
886 if (entry == 1 && childCount() == 2)
887 targetWidget = calendarView();
888 break;
889 default:
890 return QAccessibleWidgetEx::navigate(relation, entry, target);
891 }
892 *target = queryAccessibleInterface(targetWidget);
893 return *target ? 0: -1;
894}
895
896QRect QAccessibleCalendarWidget::rect(int child) const
897{
898 if (!calendarWidget()->isVisible() || child > childCount())
899 return QRect();
900 if (child == 0)
901 return QAccessibleWidgetEx::rect(child);
902 QWidget *childWidget = 0;
903 if (childCount() == 2)
904 childWidget = child == 1 ? navigationBar() : calendarView();
905 else
906 childWidget = calendarView();
907 return QRect(childWidget->mapToGlobal(QPoint(0, 0)), childWidget->size());
908}
909
910int QAccessibleCalendarWidget::childAt(int x, int y) const
911{
912 const QPoint globalTargetPos = QPoint(x, y);
913 if (!rect(0).contains(globalTargetPos))
914 return -1;
915 if (rect(1).contains(globalTargetPos))
916 return 1;
917 if (rect(2).contains(globalTargetPos))
918 return 2;
919 return 0;
920}
921
922QCalendarWidget *QAccessibleCalendarWidget::calendarWidget() const
923{
924 return static_cast<QCalendarWidget *>(object());
925}
926
927QAbstractItemView *QAccessibleCalendarWidget::calendarView() const
928{
929 foreach (QObject *child, calendarWidget()->children()) {
930 if (child->objectName() == QLatin1String("qt_calendar_calendarview"))
931 return static_cast<QAbstractItemView *>(child);
932 }
933 return 0;
934}
935
936QWidget *QAccessibleCalendarWidget::navigationBar() const
937{
938 foreach (QObject *child, calendarWidget()->children()) {
939 if (child->objectName() == QLatin1String("qt_calendar_navigationbar"))
940 return static_cast<QWidget *>(child);
941 }
942 return 0;
943}
944#endif // QT_NO_CALENDARWIDGET
945
946#ifndef QT_NO_DOCKWIDGET
947QAccessibleDockWidget::QAccessibleDockWidget(QWidget *widget)
948 : QAccessibleWidgetEx(widget, Window)
949{
950
951}
952
953int QAccessibleDockWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **iface) const
954{
955 if (relation == Child) {
956 if (entry == 1) {
957 *iface = new QAccessibleTitleBar(dockWidget());
958 return 0;
959 } else if (entry == 2) {
960 if (dockWidget()->widget())
961 *iface = QAccessible::queryAccessibleInterface(dockWidget()->widget());
962 return 0;
963 }
964 *iface = 0;
965 return -1;
966 }
967 return QAccessibleWidgetEx::navigate(relation, entry, iface);
968}
969
970int QAccessibleDockWidget::childAt(int x, int y) const
971{
972 for (int i = childCount(); i >= 0; --i) {
973 if (rect(i).contains(x,y))
974 return i;
975 }
976 return -1;
977}
978
979int QAccessibleDockWidget::childCount() const
980{
981 return dockWidget()->widget() ? 2 : 1;
982}
983
984int QAccessibleDockWidget::indexOfChild(const QAccessibleInterface *child) const
985{
986 if (child) {
987 if (qobject_cast<QDockWidget *>(child->object()) == dockWidget() && child->role(0) == TitleBar) {
988 return 1;
989 } else {
990 return 2; //###
991 }
992 }
993 return -1;
994}
995
996QAccessible::Role QAccessibleDockWidget::role(int child) const
997{
998 switch (child) {
999 case 0:
1000 return Window;
1001 case 1:
1002 return TitleBar;
1003 case 2:
1004 //###
1005 break;
1006 default:
1007 break;
1008 }
1009 return NoRole;
1010}
1011
1012QAccessible::State QAccessibleDockWidget::state(int child) const
1013{
1014 //### mark tabified widgets as invisible
1015 return QAccessibleWidgetEx::state(child);
1016}
1017
1018QRect QAccessibleDockWidget::rect (int child ) const
1019{
1020 QRect rect;
1021 bool mapToGlobal = true;
1022 if (child == 0) {
1023 if (dockWidget()->isFloating()) {
1024 rect = dockWidget()->frameGeometry();
1025 mapToGlobal = false;
1026 } else {
1027 rect = dockWidget()->rect();
1028 }
1029 }else if (child == 1) {
1030 QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
1031 rect = layout->titleArea();
1032 }else if (child == 2) {
1033 if (dockWidget()->widget())
1034 rect = dockWidget()->widget()->geometry();
1035 }
1036 if (rect.isNull())
1037 return rect;
1038
1039 if (mapToGlobal)
1040 rect.moveTopLeft(dockWidget()->mapToGlobal(rect.topLeft()));
1041
1042 return rect;
1043}
1044
1045QVariant QAccessibleDockWidget::invokeMethodEx(QAccessible::Method, int, const QVariantList &)
1046{
1047 return QVariant();
1048}
1049
1050QDockWidget *QAccessibleDockWidget::dockWidget() const
1051{
1052 return static_cast<QDockWidget *>(object());
1053}
1054
1055////
1056// QAccessibleTitleBar
1057////
1058QAccessibleTitleBar::QAccessibleTitleBar(QDockWidget *widget)
1059 : m_dockWidget(widget)
1060{
1061
1062}
1063
1064int QAccessibleTitleBar::navigate(RelationFlag relation, int entry, QAccessibleInterface **iface) const
1065{
1066 if (entry == 0 || relation == Self) {
1067 *iface = new QAccessibleTitleBar(dockWidget());
1068 return 0;
1069 }
1070 switch (relation) {
1071 case Child:
1072 case FocusChild:
1073 if (entry >= 1) {
1074 QDockWidgetLayout *layout = dockWidgetLayout();
1075 int index = 1;
1076 int role;
1077 for (role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
1078 QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
1079 if (!w->isVisible())
1080 continue;
1081 if (index == entry)
1082 break;
1083 ++index;
1084 }
1085 *iface = 0;
1086 return role > QDockWidgetLayout::FloatButton ? -1 : index;
1087 }
1088 break;
1089 case Ancestor:
1090 {
1091 QAccessibleDockWidget *target = new QAccessibleDockWidget(dockWidget());
1092 int index;
1093 if (entry == 1) {
1094 *iface = target;
1095 return 0;
1096 }
1097 index = target->navigate(Ancestor, entry - 1, iface);
1098 delete target;
1099 return index;
1100
1101 break;}
1102 case Sibling:
1103 return navigate(Child, entry, iface);
1104 break;
1105 default:
1106 break;
1107 }
1108 *iface = 0;
1109 return -1;
1110}
1111
1112QAccessible::Relation QAccessibleTitleBar::relationTo(int /*child*/, const QAccessibleInterface * /*other*/, int /*otherChild*/) const
1113{
1114 return Unrelated; //###
1115}
1116
1117int QAccessibleTitleBar::indexOfChild(const QAccessibleInterface * /*child*/) const
1118{
1119 return -1;
1120}
1121
1122int QAccessibleTitleBar::childCount() const
1123{
1124 QDockWidgetLayout *layout = dockWidgetLayout();
1125 int count = 0;
1126 for (int role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
1127 QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
1128 if (w && w->isVisible())
1129 ++count;
1130 }
1131 return count;
1132}
1133
1134QString QAccessibleTitleBar::text(Text t, int child) const
1135{
1136 if (!child) {
1137 if (t == Value) {
1138 return dockWidget()->windowTitle();
1139 }
1140 }
1141 return QString();
1142}
1143
1144QAccessible::State QAccessibleTitleBar::state(int child) const
1145{
1146 QAccessible::State state = Normal;
1147 if (child) {
1148 QDockWidgetLayout *layout = dockWidgetLayout();
1149 QAbstractButton *b = static_cast<QAbstractButton *>(layout->widgetForRole((QDockWidgetLayout::Role)child));
1150 if (b) {
1151 if (b->isDown())
1152 state |= Pressed;
1153 }
1154 } else {
1155 QDockWidget *w = dockWidget();
1156 if (w->testAttribute(Qt::WA_WState_Visible) == false)
1157 state |= Invisible;
1158 if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow())
1159 state |= Focusable;
1160 if (w->hasFocus())
1161 state |= Focused;
1162 if (!w->isEnabled())
1163 state |= Unavailable;
1164 }
1165
1166 return state;
1167}
1168
1169QRect QAccessibleTitleBar::rect (int child ) const
1170{
1171 bool mapToGlobal = true;
1172 QRect rect;
1173 if (child == 0) {
1174 if (dockWidget()->isFloating()) {
1175 rect = dockWidget()->frameGeometry();
1176 QPoint globalPos = dockWidget()->mapToGlobal( dockWidget()->widget()->rect().topLeft() );
1177 globalPos.ry()--;
1178 rect.setBottom(globalPos.y());
1179 mapToGlobal = false;
1180 } else {
1181 QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
1182 rect = layout->titleArea();
1183 }
1184 }else if (child >= 1 && child <= childCount()) {
1185 QDockWidgetLayout *layout = dockWidgetLayout();
1186 int index = 1;
1187 for (int role = QDockWidgetLayout::CloseButton; role <= QDockWidgetLayout::FloatButton; ++role) {
1188 QWidget *w = layout->widgetForRole((QDockWidgetLayout::Role)role);
1189 if (!w || !w->isVisible())
1190 continue;
1191 if (index == child) {
1192 rect = w->geometry();
1193 break;
1194 }
1195 ++index;
1196 }
1197 }
1198 if (rect.isNull())
1199 return rect;
1200
1201 if (mapToGlobal)
1202 rect.moveTopLeft(dockWidget()->mapToGlobal(rect.topLeft()));
1203 return rect;
1204}
1205
1206int QAccessibleTitleBar::childAt(int x, int y) const
1207{
1208 for (int i = childCount(); i >= 0; --i) {
1209 if (rect(i).contains(x,y))
1210 return i;
1211 }
1212 return -1;
1213}
1214
1215QObject *QAccessibleTitleBar::object() const
1216{
1217 return m_dockWidget;
1218}
1219
1220QDockWidgetLayout *QAccessibleTitleBar::dockWidgetLayout() const
1221{
1222 return qobject_cast<QDockWidgetLayout*>(dockWidget()->layout());
1223}
1224
1225QDockWidget *QAccessibleTitleBar::dockWidget() const
1226{
1227 return m_dockWidget;
1228}
1229
1230QString QAccessibleTitleBar::actionText(int action, Text t, int child) const
1231{
1232 QString str;
1233 if (child >= 1 && child <= childCount()) {
1234 if (t == Name) {
1235 switch (action) {
1236 case Press:
1237 case DefaultAction:
1238 if (child == QDockWidgetLayout::CloseButton) {
1239 str = QDockWidget::tr("Close");
1240 } else if (child == QDockWidgetLayout::FloatButton) {
1241 str = dockWidget()->isFloating() ? QDockWidget::tr("Dock")
1242 : QDockWidget::tr("Float");
1243 }
1244 break;
1245 default:
1246 break;
1247 }
1248 }
1249 }
1250 return str;
1251}
1252
1253bool QAccessibleTitleBar::doAction(int action, int child, const QVariantList& /*params*/)
1254{
1255 if (!child || !dockWidget()->isEnabled())
1256 return false;
1257
1258 switch (action) {
1259 case DefaultAction:
1260 case Press: {
1261 QDockWidgetLayout *layout = dockWidgetLayout();
1262 QAbstractButton *btn = static_cast<QAbstractButton *>(layout->widgetForRole((QDockWidgetLayout::Role)child));
1263 if (btn)
1264 btn->animateClick();
1265 return true;
1266 break;}
1267 default:
1268 break;
1269 }
1270
1271 return false;
1272}
1273
1274int QAccessibleTitleBar::userActionCount (int /*child*/) const
1275{
1276 return 0;
1277}
1278
1279QAccessible::Role QAccessibleTitleBar::role(int child) const
1280{
1281 switch (child) {
1282 case 0:
1283 return TitleBar;
1284 break;
1285 default:
1286 if (child >= 1 && child <= childCount())
1287 return PushButton;
1288 break;
1289 }
1290
1291 return NoRole;
1292}
1293
1294void QAccessibleTitleBar::setText(Text /*t*/, int /*child*/, const QString &/*text*/)
1295{
1296
1297}
1298
1299bool QAccessibleTitleBar::isValid() const
1300{
1301 return dockWidget();
1302}
1303
1304#endif // QT_NO_DOCKWIDGET
1305
1306#ifndef QT_NO_TEXTEDIT
1307void QAccessibleTextEdit::addSelection(int startOffset, int endOffset)
1308{
1309 setSelection(0, startOffset, endOffset);
1310}
1311
1312QString QAccessibleTextEdit::attributes(int offset, int *startOffset, int *endOffset)
1313{
1314 // TODO - wait for a definition of attributes
1315 Q_UNUSED(offset);
1316 Q_UNUSED(startOffset);
1317 Q_UNUSED(endOffset);
1318 return QString();
1319}
1320
1321int QAccessibleTextEdit::cursorPosition()
1322{
1323 return textEdit()->textCursor().position();
1324}
1325
1326QRect QAccessibleTextEdit::characterRect(int offset, CoordinateType coordType)
1327{
1328 QTextEdit *edit = textEdit();
1329 QTextCursor cursor(edit->document());
1330 cursor.setPosition(offset);
1331
1332 if (cursor.position() != offset)
1333 return QRect();
1334
1335 QRect r = edit->cursorRect(cursor);
1336 if (cursor.movePosition(QTextCursor::NextCharacter)) {
1337 r.setWidth(edit->cursorRect(cursor).y() - r.y());
1338 } else {
1339 // we don't know the width of the character - maybe because we're at document end
1340 // in that case, IAccessible2 tells us to return the width of a default character
1341 int averageCharWidth = QFontMetrics(cursor.charFormat().font()).averageCharWidth();
1342 if (edit->layoutDirection() == Qt::RightToLeft)
1343 averageCharWidth *= -1;
1344 r.setWidth(averageCharWidth);
1345 }
1346
1347 switch (coordType) {
1348 case RelativeToScreen:
1349 r.moveTo(edit->viewport()->mapToGlobal(r.topLeft()));
1350 break;
1351 case RelativeToParent:
1352 break;
1353 }
1354
1355 return r;
1356}
1357
1358int QAccessibleTextEdit::selectionCount()
1359{
1360 return textEdit()->textCursor().hasSelection() ? 1 : 0;
1361}
1362
1363int QAccessibleTextEdit::offsetAtPoint(const QPoint &point, CoordinateType coordType)
1364{
1365 QTextEdit *edit = textEdit();
1366
1367 QPoint p = point;
1368 if (coordType == RelativeToScreen)
1369 p = edit->viewport()->mapFromGlobal(p);
1370 // convert to document coordinates
1371 p += QPoint(edit->horizontalScrollBar()->value(), edit->verticalScrollBar()->value());
1372
1373 return edit->document()->documentLayout()->hitTest(p, Qt::ExactHit);
1374}
1375
1376void QAccessibleTextEdit::selection(int selectionIndex, int *startOffset, int *endOffset)
1377{
1378 *startOffset = *endOffset = 0;
1379 QTextCursor cursor = textEdit()->textCursor();
1380
1381 if (selectionIndex != 0 || !cursor.hasSelection())
1382 return;
1383
1384 *startOffset = cursor.selectionStart();
1385 *endOffset = cursor.selectionEnd();
1386}
1387
1388QString QAccessibleTextEdit::text(int startOffset, int endOffset)
1389{
1390 QTextCursor cursor(textEdit()->document());
1391
1392 cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
1393 cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
1394
1395 return cursor.selectedText();
1396}
1397
1398QString QAccessibleTextEdit::textBeforeOffset (int offset, BoundaryType boundaryType,
1399 int *startOffset, int *endOffset)
1400{
1401 // TODO - what exactly is before?
1402 Q_UNUSED(offset);
1403 Q_UNUSED(boundaryType);
1404 Q_UNUSED(startOffset);
1405 Q_UNUSED(endOffset);
1406 return QString();
1407}
1408
1409QString QAccessibleTextEdit::textAfterOffset(int offset, BoundaryType boundaryType,
1410 int *startOffset, int *endOffset)
1411{
1412 // TODO - what exactly is after?
1413 Q_UNUSED(offset);
1414 Q_UNUSED(boundaryType);
1415 Q_UNUSED(startOffset);
1416 Q_UNUSED(endOffset);
1417 return QString();
1418}
1419
1420QString QAccessibleTextEdit::textAtOffset(int offset, BoundaryType boundaryType,
1421 int *startOffset, int *endOffset)
1422{
1423 Q_ASSERT(startOffset);
1424 Q_ASSERT(endOffset);
1425
1426 *startOffset = *endOffset = -1;
1427 QTextEdit *edit = textEdit();
1428
1429 QTextCursor cursor(edit->document());
1430 if (offset >= characterCount())
1431 return QString();
1432
1433 switch (boundaryType) {
1434 case CharBoundary:
1435 cursor.setPosition(offset);
1436 *startOffset = cursor.position();
1437 cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
1438 *endOffset = cursor.position();
1439 break;
1440 case WordBoundary:
1441 cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
1442 *startOffset = cursor.position();
1443 cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
1444 *endOffset = cursor.position();
1445 break;
1446 case SentenceBoundary:
1447 // TODO - what's a sentence?
1448 return QString();
1449 case LineBoundary:
1450 cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::MoveAnchor);
1451 *startOffset = cursor.position();
1452 cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
1453 *endOffset = cursor.position();
1454 break;
1455 case ParagraphBoundary:
1456 cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
1457 *startOffset = cursor.position();
1458 cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
1459 *endOffset = cursor.position();
1460 break;
1461 case NoBoundary: {
1462 *startOffset = 0;
1463 const QString txt = edit->toPlainText();
1464 *endOffset = txt.count();
1465 return txt; }
1466 default:
1467 qDebug("AccessibleTextAdaptor::textAtOffset: Unknown boundary type %d", boundaryType);
1468 return QString();
1469 }
1470
1471 return cursor.selectedText();
1472}
1473
1474void QAccessibleTextEdit::removeSelection(int selectionIndex)
1475{
1476 if (selectionIndex != 0)
1477 return;
1478
1479 QTextCursor cursor = textEdit()->textCursor();
1480 cursor.clearSelection();
1481 textEdit()->setTextCursor(cursor);
1482}
1483
1484void QAccessibleTextEdit::setCursorPosition(int position)
1485{
1486 QTextCursor cursor = textEdit()->textCursor();
1487 cursor.setPosition(position);
1488 textEdit()->setTextCursor(cursor);
1489}
1490
1491void QAccessibleTextEdit::setSelection(int selectionIndex, int startOffset, int endOffset)
1492{
1493 if (selectionIndex != 0)
1494 return;
1495
1496 QTextCursor cursor = textEdit()->textCursor();
1497 cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
1498 cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
1499 textEdit()->setTextCursor(cursor);
1500}
1501
1502int QAccessibleTextEdit::characterCount()
1503{
1504 return textEdit()->toPlainText().count();
1505}
1506
1507void QAccessibleTextEdit::scrollToSubstring(int startIndex, int endIndex)
1508{
1509 QTextEdit *edit = textEdit();
1510
1511 QTextCursor cursor(edit->document());
1512 cursor.setPosition(startIndex);
1513 QRect r = edit->cursorRect(cursor);
1514
1515 cursor.setPosition(endIndex);
1516 r.setBottomRight(edit->cursorRect(cursor).bottomRight());
1517
1518 r.moveTo(r.x() + edit->horizontalScrollBar()->value(),
1519 r.y() + edit->verticalScrollBar()->value());
1520
1521 // E V I L, but ensureVisible is not public
1522 if (!QMetaObject::invokeMethod(edit, "_q_ensureVisible", Q_ARG(QRectF, r)))
1523 qWarning("AccessibleTextEdit::scrollToSubstring failed!");
1524}
1525
1526static QTextCursor cursorForRange(QTextEdit *textEdit, int startOffset, int endOffset)
1527{
1528 QTextCursor cursor(textEdit->document());
1529 cursor.setPosition(startOffset, QTextCursor::MoveAnchor);
1530 cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
1531
1532 return cursor;
1533}
1534
1535void QAccessibleTextEdit::copyText(int startOffset, int endOffset)
1536{
1537 QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
1538
1539 if (!cursor.hasSelection())
1540 return;
1541
1542// QApplication::clipboard()->setMimeData(new QTextEditMimeData(cursor.selection()));
1543}
1544
1545void QAccessibleTextEdit::deleteText(int startOffset, int endOffset)
1546{
1547 QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
1548
1549 cursor.removeSelectedText();
1550}
1551
1552void QAccessibleTextEdit::insertText(int offset, const QString &text)
1553{
1554 QTextCursor cursor(textEdit()->document());
1555 cursor.setPosition(offset);
1556
1557 cursor.insertText(text);
1558}
1559
1560void QAccessibleTextEdit::cutText(int startOffset, int endOffset)
1561{
1562 QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
1563
1564 if (!cursor.hasSelection())
1565 return;
1566
1567// QApplication::clipboard()->setMimeData(new QTextEditMimeData(cursor.selection()));
1568 cursor.removeSelectedText();
1569}
1570
1571void QAccessibleTextEdit::pasteText(int offset)
1572{
1573 QTextEdit *edit = textEdit();
1574
1575 QTextCursor oldCursor = edit->textCursor();
1576 QTextCursor newCursor = oldCursor;
1577 newCursor.setPosition(offset);
1578
1579 edit->setTextCursor(newCursor);
1580#ifndef QT_NO_CLIPBOARD
1581 edit->paste();
1582#endif
1583 edit->setTextCursor(oldCursor);
1584}
1585
1586void QAccessibleTextEdit::replaceText(int startOffset, int endOffset, const QString &text)
1587{
1588 QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset);
1589
1590 cursor.removeSelectedText();
1591 cursor.insertText(text);
1592}
1593
1594void QAccessibleTextEdit::setAttributes(int startOffset, int endOffset, const QString &attributes)
1595{
1596 // TODO
1597 Q_UNUSED(startOffset);
1598 Q_UNUSED(endOffset);
1599 Q_UNUSED(attributes);
1600}
1601
1602#endif // QT_NO_TEXTEDIT
1603
1604#ifndef QT_NO_MAINWINDOW
1605QAccessibleMainWindow::QAccessibleMainWindow(QWidget *widget)
1606 : QAccessibleWidgetEx(widget, Application) { }
1607
1608QVariant QAccessibleMainWindow::invokeMethodEx(QAccessible::Method /*method*/, int /*child*/, const QVariantList & /*params*/)
1609{
1610 return QVariant();
1611}
1612
1613int QAccessibleMainWindow::childCount() const
1614{
1615 QList<QWidget*> kids = childWidgets(mainWindow(), true);
1616 return kids.count();
1617}
1618
1619int QAccessibleMainWindow::indexOfChild(const QAccessibleInterface *iface) const
1620{
1621 QList<QWidget*> kids = childWidgets(mainWindow(), true);
1622 int childIndex = kids.indexOf(static_cast<QWidget*>(iface->object()));
1623 return childIndex == -1 ? -1 : ++childIndex;
1624}
1625
1626int QAccessibleMainWindow::navigate(RelationFlag relation, int entry, QAccessibleInterface **iface) const
1627{
1628 if (relation == Child && entry >= 1) {
1629 QList<QWidget*> kids = childWidgets(mainWindow(), true);
1630 if (entry <= kids.count()) {
1631 *iface = QAccessible::queryAccessibleInterface(kids.at(entry - 1));
1632 return *iface ? 0 : -1;
1633 }
1634 }
1635 return QAccessibleWidgetEx::navigate(relation, entry, iface);
1636}
1637
1638int QAccessibleMainWindow::childAt(int x, int y) const
1639{
1640 QWidget *w = widget();
1641 if (!w->isVisible())
1642 return -1;
1643 QPoint gp = w->mapToGlobal(QPoint(0, 0));
1644 if (!QRect(gp.x(), gp.y(), w->width(), w->height()).contains(x, y))
1645 return -1;
1646
1647 QWidgetList kids = childWidgets(mainWindow(), true);
1648 QPoint rp = mainWindow()->mapFromGlobal(QPoint(x, y));
1649 for (int i = 0; i < kids.size(); ++i) {
1650 QWidget *child = kids.at(i);
1651 if (!child->isWindow() && !child->isHidden() && child->geometry().contains(rp)) {
1652 return i + 1;
1653 }
1654 }
1655 return 0;
1656}
1657
1658QMainWindow *QAccessibleMainWindow::mainWindow() const
1659{
1660 return qobject_cast<QMainWindow *>(object());
1661}
1662
1663#endif //QT_NO_MAINWINDOW
1664
1665QT_END_NAMESPACE
1666
1667#endif // QT_NO_ACCESSIBILITY
Note: See TracBrowser for help on using the repository browser.