accessible/qaccessiblewidget.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/****************************************************************************-
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/****************************************************************************
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
5** -
6** This file is part of the QtGui module 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 Digia. For licensing terms and -
14** conditions see http://qt.digia.com/licensing. For further information -
15** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software -
20** Foundation and appearing in the file LICENSE.LGPL included in the -
21** packaging of this file. Please review the following information to -
22** ensure the GNU Lesser General Public License version 2.1 requirements -
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
24** -
25** In addition, as a special exception, Digia gives you certain additional -
26** rights. These rights are described in the Digia Qt LGPL Exception -
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
28** -
29** GNU General Public License Usage -
30** Alternatively, this file may be used under the terms of the GNU -
31** General Public License version 3.0 as published by the Free Software -
32** Foundation and appearing in the file LICENSE.GPL included in the -
33** packaging of this file. Please review the following information to -
34** ensure the GNU General Public License version 3.0 requirements will be -
35** met: http://www.gnu.org/copyleft/gpl.html. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42#include "qaccessiblewidget.h" -
43 -
44#ifndef QT_NO_ACCESSIBILITY -
45 -
46#include "qaction.h" -
47#include "qapplication.h" -
48#include "qgroupbox.h" -
49#include "qlabel.h" -
50#include "qtooltip.h" -
51#include "qwhatsthis.h" -
52#include "qwidget.h" -
53#include "qdebug.h" -
54#include <qmath.h> -
55#include <QRubberBand> -
56#include <QFocusFrame> -
57#include <QMenu> -
58 -
59QT_BEGIN_NAMESPACE -
60 -
61static QList<QWidget*> childWidgets(const QWidget *widget) -
62{ -
63 QList<QObject*> list = widget->children(); -
64 QList<QWidget*> widgets; -
65 for (int i = 0; i < list.size(); ++i) { -
66 QWidget *w = qobject_cast<QWidget *>(list.at(i)); -
67 if (w && !w->isWindow() -
68 && !qobject_cast<QFocusFrame*>(w) -
69#if !defined(QT_NO_MENU) -
70 && !qobject_cast<QMenu*>(w) -
71#endif -
72 && w->objectName() != QLatin1String("qt_rubberband")) -
73 widgets.append(w); -
74 } -
75 return widgets; -
76} -
77 -
78static QString buddyString(const QWidget *widget) -
79{ -
80 if (!widget) -
81 return QString(); -
82 QWidget *parent = widget->parentWidget(); -
83 if (!parent) -
84 return QString(); -
85#ifndef QT_NO_SHORTCUT -
86 QObjectList ol = parent->children(); -
87 for (int i = 0; i < ol.size(); ++i) { -
88 QLabel *label = qobject_cast<QLabel*>(ol.at(i)); -
89 if (label && label->buddy() == widget) -
90 return label->text(); -
91 } -
92#endif -
93 -
94#ifndef QT_NO_GROUPBOX -
95 QGroupBox *groupbox = qobject_cast<QGroupBox*>(parent); -
96 if (groupbox) -
97 return groupbox->title(); -
98#endif -
99 -
100 return QString(); -
101} -
102 -
103/* This function will return the offset of the '&' in the text that would be -
104 preceding the accelerator character. -
105 If this text does not have an accelerator, -1 will be returned. */ -
106static int qt_accAmpIndex(const QString &text) -
107{ -
108#ifndef QT_NO_SHORTCUT -
109 if (text.isEmpty()) -
110 return -1; -
111 -
112 int fa = 0; -
113 QChar ac; -
114 while ((fa = text.indexOf(QLatin1Char('&'), fa)) != -1) { -
115 ++fa; -
116 if (fa < text.length()) { -
117 // ignore "&&" -
118 if (text.at(fa) == QLatin1Char('&')) { -
119 -
120 ++fa; -
121 continue; -
122 } else { -
123 return fa - 1; -
124 break;
dead code: break;
-
125 } -
126 } -
127 } -
128 -
129 return -1; -
130#else -
131 Q_UNUSED(text); -
132 return -1; -
133#endif -
134} -
135 -
136QString Q_WIDGETS_EXPORT qt_accStripAmp(const QString &text) -
137{ -
138 QString newText(text); -
139 int ampIndex = qt_accAmpIndex(newText); -
140 if (ampIndex != -1) -
141 newText.remove(ampIndex, 1); -
142 -
143 return newText.replace(QLatin1String("&&"), QLatin1String("&")); -
144} -
145 -
146QString Q_WIDGETS_EXPORT qt_accHotKey(const QString &text) -
147{ -
148 int ampIndex = qt_accAmpIndex(text); -
149 if (ampIndex != -1) -
150 return QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + text.at(ampIndex + 1); -
151 -
152 return QString(); -
153} -
154 -
155class QAccessibleWidgetPrivate -
156{ -
157public: -
158 QAccessibleWidgetPrivate() -
159 :role(QAccessible::Client) -
160 {} -
161 -
162 QAccessible::Role role; -
163 QString name; -
164 QStringList primarySignals; -
165}; -
166 -
167/*! -
168 \class QAccessibleWidget -
169 \brief The QAccessibleWidget class implements the QAccessibleInterface for QWidgets. -
170 \internal -
171 -
172 \ingroup accessibility -
173 \inmodule QtWidgets -
174 -
175 This class is part of \l {Accessibility for QWidget Applications}. -
176 -
177 This class is convenient to use as a base class for custom -
178 implementations of QAccessibleInterfaces that provide information -
179 about widget objects. -
180 -
181 The class provides functions to retrieve the parentObject() (the -
182 widget's parent widget), and the associated widget(). Controlling -
183 signals can be added with addControllingSignal(), and setters are -
184 provided for various aspects of the interface implementation, for -
185 example setValue(), setDescription(), setAccelerator(), and -
186 setHelp(). -
187 -
188 \sa QAccessible, QAccessibleObject -
189*/ -
190 -
191/*! -
192 Creates a QAccessibleWidget object for widget \a w. -
193 \a role and \a name are optional parameters that set the object's -
194 role and name properties. -
195*/ -
196QAccessibleWidget::QAccessibleWidget(QWidget *w, QAccessible::Role role, const QString &name) -
197: QAccessibleObject(w) -
198{ -
199 Q_ASSERT(widget()); -
200 d = new QAccessibleWidgetPrivate(); -
201 d->role = role; -
202 d->name = name; -
203} -
204 -
205/*! \reimp */ -
206QWindow *QAccessibleWidget::window() const -
207{ -
208 return widget()->windowHandle(); -
209} -
210 -
211/*! -
212 Destroys this object. -
213*/ -
214QAccessibleWidget::~QAccessibleWidget() -
215{ -
216 delete d; -
217} -
218 -
219/*! -
220 Returns the associated widget. -
221*/ -
222QWidget *QAccessibleWidget::widget() const -
223{ -
224 return qobject_cast<QWidget*>(object()); -
225} -
226 -
227/*! -
228 Returns the associated widget's parent object, which is either the -
229 parent widget, or qApp for top-level widgets. -
230*/ -
231QObject *QAccessibleWidget::parentObject() const -
232{ -
233 QObject *parent = object()->parent(); -
234 if (!parent) -
235 parent = qApp; -
236 return parent; -
237} -
238 -
239/*! \reimp */ -
240QRect QAccessibleWidget::rect() const -
241{ -
242 QWidget *w = widget(); -
243 if (!w->isVisible()) -
244 return QRect(); -
245 QPoint wpos = w->mapToGlobal(QPoint(0, 0)); -
246 -
247 return QRect(wpos.x(), wpos.y(), w->width(), w->height()); -
248} -
249 -
250QT_BEGIN_INCLUDE_NAMESPACE -
251#include <private/qobject_p.h> -
252QT_END_INCLUDE_NAMESPACE -
253 -
254class QACConnectionObject : public QObject -
255{ -
256 Q_DECLARE_PRIVATE(QObject) -
257public: -
258 inline bool isSender(const QObject *receiver, const char *signal) const -
259 { return d_func()->isSender(receiver, signal); } -
260 inline QObjectList receiverList(const char *signal) const -
261 { return d_func()->receiverList(signal); } -
262 inline QObjectList senderList() const -
263 { return d_func()->senderList(); } -
264}; -
265 -
266/*! -
267 Registers \a signal as a controlling signal. -
268 -
269 An object is a Controller to any other object connected to a -
270 controlling signal. -
271*/ -
272void QAccessibleWidget::addControllingSignal(const QString &signal) -
273{ -
274 QByteArray s = QMetaObject::normalizedSignature(signal.toLatin1()); -
275 if (object()->metaObject()->indexOfSignal(s) < 0) -
276 qWarning("Signal %s unknown in %s", s.constData(), object()->metaObject()->className()); -
277 d->primarySignals << QLatin1String(s); -
278} -
279 -
280static inline bool isAncestor(const QObject *obj, const QObject *child) -
281{ -
282 while (child) { -
283 if (child == obj) -
284 return true; -
285 child = child->parent(); -
286 } -
287 return false; -
288} -
289 -
290/*! \reimp */ -
291QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > -
292QAccessibleWidget::relations(QAccessible::Relation match /*= QAccessible::AllRelations*/) const -
293{ -
294 QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > rels; -
295 if (match & QAccessible::Label) { -
296 const QAccessible::Relation rel = QAccessible::Label; -
297 if (QWidget *parent = widget()->parentWidget()) { -
298#ifndef QT_NO_SHORTCUT -
299 // first check for all siblings that are labels to us -
300 // ideally we would go through all objects and check, but that -
301 // will be too expensive -
302 const QList<QWidget*> kids = childWidgets(parent); -
303 for (int i = 0; i < kids.count(); ++i) { -
304 if (QLabel *labelSibling = qobject_cast<QLabel*>(kids.at(i))) { -
305 if (labelSibling->buddy() == widget()) { -
306 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(labelSibling); -
307 rels.append(qMakePair(iface, rel)); -
308 } -
309 } -
310 } -
311#endif -
312#ifndef QT_NO_GROUPBOX -
313 QGroupBox *groupbox = qobject_cast<QGroupBox*>(parent); -
314 if (groupbox && !groupbox->title().isEmpty()) { -
315 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(groupbox); -
316 rels.append(qMakePair(iface, rel)); -
317 } -
318#endif -
319 } -
320 } -
321 -
322 if (match & QAccessible::Controlled) { -
323 QObjectList allReceivers; -
324 QACConnectionObject *connectionObject = (QACConnectionObject*)object(); -
325 for (int sig = 0; sig < d->primarySignals.count(); ++sig) { -
326 const QObjectList receivers = connectionObject->receiverList(d->primarySignals.at(sig).toLatin1()); -
327 allReceivers += receivers; -
328 } -
329 -
330 allReceivers.removeAll(object()); //### The object might connect to itself internally -
331 -
332 for (int i = 0; i < allReceivers.count(); ++i) { -
333 const QAccessible::Relation rel = QAccessible::Controlled; -
334 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(allReceivers.at(i)); -
335 if (iface) -
336 rels.append(qMakePair(iface, rel)); -
337 } -
338 } -
339 -
340 return rels; -
341} -
342 -
343/*! \reimp */ -
344QAccessibleInterface *QAccessibleWidget::parent() const -
345{ -
346 QObject *parentWidget= widget()->parentWidget(); -
347 if (!parentWidget) -
348 parentWidget = qApp; -
349 return QAccessible::queryAccessibleInterface(parentWidget); -
350} -
351 -
352/*! \reimp */ -
353QAccessibleInterface *QAccessibleWidget::child(int index) const -
354{ -
355 QWidgetList childList = childWidgets(widget()); -
356 if (index >= 0 && index < childList.size()) -
357 return QAccessible::queryAccessibleInterface(childList.at(index)); -
358 return 0; -
359} -
360 -
361/*! \reimp */ -
362QAccessibleInterface *QAccessibleWidget::focusChild() const -
363{ -
364 if (widget()->hasFocus()) -
365 return QAccessible::queryAccessibleInterface(object()); -
366 -
367 QWidget *fw = widget()->focusWidget(); -
368 if (!fw) -
369 return 0; -
370 -
371 if (isAncestor(widget(), fw) || fw == widget()) -
372 return QAccessible::queryAccessibleInterface(fw); -
373 return 0; -
374} -
375 -
376/*! \reimp */ -
377int QAccessibleWidget::childCount() const -
378{ -
379 QWidgetList cl = childWidgets(widget()); -
380 return cl.size(); -
381} -
382 -
383/*! \reimp */ -
384int QAccessibleWidget::indexOfChild(const QAccessibleInterface *child) const -
385{ -
386 QWidgetList cl = childWidgets(widget()); -
387 return cl.indexOf(qobject_cast<QWidget *>(child->object())); -
388} -
389 -
390// from qwidget.cpp -
391extern QString qt_setWindowTitle_helperHelper(const QString &, const QWidget*); -
392 -
393/*! \reimp */ -
394QString QAccessibleWidget::text(QAccessible::Text t) const -
395{ -
396 QString str; -
397 -
398 switch (t) { -
399 case QAccessible::Name: -
400 if (!d->name.isEmpty()) { -
401 str = d->name; -
402 } else if (!widget()->accessibleName().isEmpty()) { -
403 str = widget()->accessibleName(); -
404 } else if (widget()->isWindow()) { -
405 if (widget()->isMinimized()) -
406 str = qt_setWindowTitle_helperHelper(widget()->windowIconText(), widget()); -
407 else -
408 str = qt_setWindowTitle_helperHelper(widget()->windowTitle(), widget()); -
409 } else { -
410 str = qt_accStripAmp(buddyString(widget())); -
411 } -
412 break; -
413 case QAccessible::Description: -
414 if (!widget()->accessibleDescription().isEmpty()) -
415 str = widget()->accessibleDescription(); -
416#ifndef QT_NO_TOOLTIP -
417 else -
418 str = widget()->toolTip(); -
419#endif -
420 break; -
421 case QAccessible::Help: -
422#ifndef QT_NO_WHATSTHIS -
423 str = widget()->whatsThis(); -
424#endif -
425 break; -
426 case QAccessible::Accelerator: -
427 str = qt_accHotKey(buddyString(widget())); -
428 break; -
429 case QAccessible::Value: -
430 break; -
431 default: -
432 break; -
433 } -
434 return str; -
435} -
436 -
437/*! \reimp */ -
438QStringList QAccessibleWidget::actionNames() const -
439{ -
440 QStringList names; -
441 if (widget()->isEnabled()) { -
442 if (widget()->focusPolicy() != Qt::NoFocus) -
443 names << setFocusAction(); -
444 } -
445 return names; -
446} -
447 -
448/*! \reimp */ -
449void QAccessibleWidget::doAction(const QString &actionName) -
450{ -
451 if (!widget()->isEnabled()) -
452 return; -
453 -
454 if (actionName == setFocusAction()) { -
455 if (widget()->isWindow()) -
456 widget()->activateWindow(); -
457 widget()->setFocus(); -
458 } -
459} -
460 -
461/*! \reimp */ -
462QStringList QAccessibleWidget::keyBindingsForAction(const QString & /* actionName */) const -
463{ -
464 return QStringList(); -
465} -
466 -
467/*! \reimp */ -
468QAccessible::Role QAccessibleWidget::role() const -
469{ -
470 return d->role; -
471} -
472 -
473/*! \reimp */ -
474QAccessible::State QAccessibleWidget::state() const -
475{ -
476 QAccessible::State state; -
477 -
478 QWidget *w = widget(); -
479 if (w->testAttribute(Qt::WA_WState_Visible) == false) -
480 state.invisible = true; -
481 if (w->focusPolicy() != Qt::NoFocus) -
482 state.focusable = true; -
483 if (w->hasFocus()) -
484 state.focused = true; -
485 if (!w->isEnabled()) -
486 state.disabled = true; -
487 if (w->isWindow()) { -
488 if (w->windowFlags() & Qt::WindowSystemMenuHint) -
489 state.movable = true; -
490 if (w->minimumSize() != w->maximumSize()) -
491 state.sizeable = true; -
492 if (w->isActiveWindow()) -
493 state.active = true; -
494 } -
495 -
496 return state; -
497} -
498 -
499/*! \reimp */ -
500QColor QAccessibleWidget::foregroundColor() const -
501{ -
502 return widget()->palette().color(widget()->foregroundRole()); -
503} -
504 -
505/*! \reimp */ -
506QColor QAccessibleWidget::backgroundColor() const -
507{ -
508 return widget()->palette().color(widget()->backgroundRole()); -
509} -
510 -
511/*! \reimp */ -
512void *QAccessibleWidget::interface_cast(QAccessible::InterfaceType t) -
513{ -
514 if (t == QAccessible::ActionInterface) -
515 return static_cast<QAccessibleActionInterface*>(this); -
516 return 0; -
517} -
518 -
519QT_END_NAMESPACE -
520 -
521#endif //QT_NO_ACCESSIBILITY -
522 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial