summaryrefslogtreecommitdiffstats
path: root/src/kernel/qaccessible.cpp
blob: 539caae221f518eb67c975e96f9544490be9b24c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
/****************************************************************************
**
** Implementation of QAccessible and QAccessibleObject classes
**
** Copyright (C) 2000-2008 Trolltech ASA.  All rights reserved.
**
** This file is part of the kernel module of the Qt GUI Toolkit.
**
** This file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free
** Software Foundation and appearing in the files LICENSE.GPL2
** and LICENSE.GPL3 included in the packaging of this file.
** Alternatively you may (at your option) use any later version
** of the GNU General Public License if such license has been
** publicly approved by Trolltech ASA (or its successors, if any)
** and the KDE Free Qt Foundation.
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** This file may be used under the terms of the Q Public License as
** defined by Trolltech ASA and appearing in the file LICENSE.QPL
** included in the packaging of this file.  Licensees holding valid Qt
** Commercial licenses may use this file in accordance with the Qt
** Commercial License Agreement provided with the Software.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
** herein.
**
**********************************************************************/

#include "qaccessible.h"

#if defined(QT_ACCESSIBILITY_SUPPORT)

#include "qptrdict.h"
#include "qmetaobject.h"
#include <private/qpluginmanager_p.h>
#include "qapplication.h"
#include <stdlib.h>

/*!
    \class QAccessible qaccessible.h
    \brief The QAccessible class provides enums and static functions
    relating to accessibility.

    \ingroup misc

    Accessibility clients use implementations of the
    QAccessibleInterface to read the information an accessible object
    exposes, or to call functions to manipulate the accessible object.

\omit
    Qt provides implementations of the QAccessibleInterface for most
    widget classes in a plugin. This plugin is located in the \e
    accessibility subdirectory of the plugins installation directory.
    The default installation directory for plugins is \c INSTALL/plugins,
    where \c INSTALL is the directory where Qt was installed.  Calling
    queryAccessibleInterface( QObject *object, QAccessibleInterface
    **iface ) will ask all plugins located in this directory for an
    implementation that exposes the information for objects of the
    class of \e object.

    To make a Qt application accessible you have to distribute the
    accessibility plugin provded with Qt together with your
    application. Simply add the plugins created in
    INSTALL/plugins/accessibility to your distribution process. Use \l
    QApplication::addLibraryPath() to specify a plugin directory for
    your application, and copy the files into an \e accessibility
    subdirectory of one of those plugin directories. Qt's
    accessibility framework will load the plugins upon request and use
    the implementations provided to expose an object's accessibility
    information.
\endomit

    See the \link plugins-howto.html plugin documentation \endlink for
    more details about how to redistribute Qt plugins.
*/

/*!
    \enum QAccessible::State

    This enum type defines bitflags that can be combined to indicate
    the state of the accessible object. The values are:

    \value Normal
    \value Unavailable
    \value Selected
    \value Focused
    \value Pressed
    \value Checked
    \value Mixed
    \value ReadOnly
    \value HotTracked
    \value Default
    \value Expanded
    \value Collapsed
    \value Busy
    \value Floating
    \value Marqueed
    \value Animated
    \value Invisible
    \value Offscreen
    \value Sizeable
    \value Moveable
    \value SelfVoicing
    \value Focusable
    \value Selectable
    \value Linked
    \value Traversed
    \value MultiSelectable
    \value ExtSelectable
    \value AlertLow
    \value AlertMedium
    \value AlertHigh
    \value Protected
    \value Valid
*/

/*!
    \enum QAccessible::Event

    This enum type defines event types when the state of the
    accessible object has changed. The event types are:

    \value SoundPlayed
    \value Alert
    \value ForegroundChanged
    \value MenuStart
    \value MenuEnd
    \value PopupMenuStart
    \value PopupMenuEnd
    \value ContextHelpStart
    \value ContextHelpEnd
    \value DragDropStart
    \value DragDropEnd
    \value DialogStart
    \value DialogEnd
    \value ScrollingStart
    \value ScrollingEnd
    \value ObjectCreated
    \value ObjectDestroyed
    \value ObjectShow
    \value ObjectHide
    \value ObjectReorder
    \value Focus
    \value Selection
    \value SelectionAdd
    \value SelectionRemove
    \value SelectionWithin
    \value StateChanged
    \value LocationChanged
    \value NameChanged
    \value DescriptionChanged
    \value ValueChanged
    \value ParentChanged
    \value HelpChanged
    \value DefaultActionChanged
    \value AcceleratorChanged
    \value MenuCommand
*/

/*!
    \enum QAccessible::Role

    This enum defines a number of roles an accessible object can have.
    The roles are:

    \value NoRole
    \value TitleBar
    \value MenuBar
    \value ScrollBar
    \value Grip
    \value Sound
    \value Cursor
    \value Caret
    \value AlertMessage
    \value Window
    \value Client
    \value PopupMenu
    \value MenuItem
    \value ToolTip
    \value Application
    \value Document
    \value Pane
    \value Chart
    \value Dialog
    \value Border
    \value Grouping
    \value Separator
    \value ToolBar
    \value StatusBar
    \value Table
    \value ColumnHeader
    \value RowHeader
    \value Column
    \value Row
    \value Cell
    \value Link
    \value HelpBalloon
    \value Character
    \value List
    \value ListItem
    \value Outline
    \value OutlineItem
    \value PageTab
    \value PropertyPage
    \value Indicator
    \value Graphic
    \value StaticText
    \value EditableText
    \value PushButton
    \value CheckBox
    \value RadioButton
    \value ComboBox
    \value DropLest
    \value ProgressBar
    \value Dial
    \value HotkeyField
    \value Slider
    \value SpinBox
    \value Diagram
    \value Animation
    \value Equation
    \value ButtonDropDown
    \value ButtonMenu
    \value ButtonDropGrid
    \value Whitespace
    \value PageTabList
    \value Clock
*/

/*!
    \enum QAccessible::NavDirection

    This enum specifies which item to move to when navigating.

    \value NavUp	    sibling above
    \value NavDown	    sibling below
    \value NavLeft	    left sibling
    \value NavRight	    right sibling
    \value NavNext	    next sibling
    \value NavPrevious	    previous sibling
    \value NavFirstChild    first child
    \value NavLastChild	    last child
    \value NavFocusChild    child with focus
*/

/*!
    \enum QAccessible::Text

    This enum specifies string information that an accessible object
    returns.

    \value Name		    The name of the object
    \value Description	    A short text describing the object
    \value Value	    The value of the object
    \value Help		    A longer text giving information about how
			    to use the object
    \value DefaultAction    The default method to interact with the object
    \value Accelerator	    The keyboard shortcut that executes the
			    default action
*/

/*!
    \fn static void QAccessible::updateAccessibility( QObject *object, int control, Event reason )

    Notifies accessibility clients about a change in \a object's
    accessibility information.

    \a reason specifies the cause of the change, for example,
    ValueChange when the position of a slider has been changed. \a
    control is the ID of the child element that has changed. When \a
    control is 0, the object itself has changed.

    Call this function whenever the state of your accessible object or
    one of it's sub-elements has been changed either programmatically
    (e.g. by calling QLabel::setText()) or by user interaction.

    If there are no accessibility tools listening to this event, the
    performance penalty for calling this function is minor, but if determining
    the parameters of the call is expensive you can use isActive() to
    avoid unnecessary performance penalties if no client is listening.
*/

static QPluginManager<QAccessibleFactoryInterface> *qAccessibleManager = 0;

class AccessibleCache : public QObject, public QPtrDict<QAccessibleInterface>
{
    Q_OBJECT
public:
    AccessibleCache()
        : QPtrDict<QAccessibleInterface>(73)
    {
    }

    void addObject(QObject *object, QAccessibleInterface *iface)
    {
        insert(object, iface);
        connect(object, SIGNAL(destroyed(QObject*)), this, SLOT(removeObject(QObject*)));
    }

public slots:
    void removeObject(QObject *object);
};

#include "qaccessible.moc"

static AccessibleCache *qAccessibleInterface = 0;
static bool cleanupAdded = FALSE;

static void qAccessibleCleanup()
{
    if ( qAccessibleInterface && qAccessibleInterface->count() && qAccessibleManager )
	qAccessibleManager->setAutoUnload( FALSE );

    delete qAccessibleInterface;
    qAccessibleInterface = 0;
    delete qAccessibleManager;
    qAccessibleManager = 0;
}

#ifdef Q_WS_MAC
QObject *QAccessible::queryAccessibleObject(QAccessibleInterface *o)
{
    if(qAccessibleInterface) {
	for(QPtrDictIterator<QAccessibleInterface> it(*qAccessibleInterface); it.current(); ++it) {
	    if(it.current() == o)
		return (QObject*)it.currentKey();
	}
    }
    return NULL;
}
#endif

void AccessibleCache::removeObject(QObject *object)
{
    if (!object)
        return;

    remove(object);
    if (!count()) {
        delete this;
        qAccessibleInterface = 0;
    }
}


/*!
    Sets \a iface to point to the implementation of the
    QAccessibleInterface for \a object, and returns \c QS_OK if
    successfull, or sets \a iface to 0 and returns \c QE_NOCOMPONENT if
    no accessibility implementation for \a object exists.

    The function uses the \link QObject::className() classname
    \endlink of \a object to find a suitable implementation. If no
    implementation for the object's class is available the function
    tries to find an implementation for the object's parent class.

    This function is called to answer an accessibility client's
    request for object information. You should never need to call this
    function yourself.
*/
QRESULT QAccessible::queryAccessibleInterface( QObject *object, QAccessibleInterface **iface )
{
    *iface = 0;
    if ( !object )
	return QE_INVALIDARG;

    if ( qAccessibleInterface ) {
	*iface = qAccessibleInterface->find( object );
	if ( *iface ) {
	    (*iface)->addRef();
	    return QS_OK;
	}
    }

    if ( !qAccessibleManager ) {
	qAccessibleManager = new QPluginManager<QAccessibleFactoryInterface>( IID_QAccessibleFactory, QApplication::libraryPaths(), "/accessible" );
	if ( !cleanupAdded ) {
	    tqAddPostRoutine( qAccessibleCleanup );
	    cleanupAdded = TRUE;
	}
    }

    QInterfacePtr<QAccessibleFactoryInterface> factory = 0;
    QMetaObject *mo = object->metaObject();
    while ( mo ) {
	qAccessibleManager->queryInterface( mo->className(), &factory );
	if ( factory )
	    break;
	mo = mo->superClass();
    }
    if ( factory )
	return factory->createAccessibleInterface( mo->className(), object, iface );

    return QE_NOCOMPONENT;
}

/*!
    Returns TRUE if an accessibility implementation has been requested,
    during the runtime of the application, otherwise returns FALSE. 
    
    Use this function to prevent potentially expensive notifications via
    updateAccessibility().

    \omit
    QListView uses this function to prevent index-lookups for item based
    notifications.
    \endomit
*/
bool QAccessible::isActive()
{
    return qAccessibleManager != 0;
}

/*!
    \class QAccessibleInterface qaccessible.h
    \brief The QAccessibleInterface class defines an interface that exposes information about accessible objects.

    \ingroup misc
*/

/*!
    \fn bool QAccessibleInterface::isValid() const

    Returns TRUE if all the data necessary to use this interface
    implementation is valid (e.g. all pointers are non-null),
    otherwise returns FALSE.
*/

/*!
    \fn int QAccessibleInterface::childCount() const

    Returns the number of children that belong to this object. A child
    can provide accessibility information on it's own (e.g. a child
    widget), or be a sub-element of this accessible object.

    All objects provide this information.

    \sa queryChild()
*/

/*!
    \fn QRESULT QAccessibleInterface::queryChild( int control, QAccessibleInterface **iface ) const

    Sets \a iface to point to the implementation of the
    QAccessibleInterface for the child specified with \a control. If
    the child doesn't provide accessibility information on it's own,
    the value of \a iface is set to 0. For those elements, this
    object is responsible for exposing the child's properties.

    All objects provide this information.

    \sa childCount(), queryParent()
*/

/*!
    \fn QRESULT QAccessibleInterface::queryParent( QAccessibleInterface **iface ) const

    Sets \a iface to point to the implementation of the
    QAccessibleInterface for the parent object, or to 0 if there is
    no such implementation or object.

    All objects provide this information.

    \sa queryChild()
*/

/*!
    \fn int QAccessibleInterface::controlAt( int x, int y ) const

    Returns the ID of the child that contains the screen coordinates
    (\a x, \a y). This function returns 0 if the point is positioned
    on the object itself. If the tested point is outside the
    boundaries of the object this function returns -1.

    All visual objects provide this information.
*/

/*!
    \fn QRect QAccessibleInterface::rect( int control ) const

    Returns the location of the child specified with \a control in
    screen coordinates. This function returns the location of the
    object itself if \a control is 0.

    All visual objects provide this information.
*/

/*!
    \fn int QAccessibleInterface::navigate( NavDirection direction, int startControl ) const

    This function traverses to another object, or to a sub-element of
    the current object. \a direction specifies in which direction to
    navigate, and \a startControl specifies the start point of the
    navigation, which is either 0 if the navigation starts at the
    object itself, or an ID of one of the object's sub-elements.

    The function returns the ID of the sub-element located in the \a
    direction specified. If there is nothing in the navigated \a
    direction, this function returns -1.

    All objects support navigation.
*/

/*!
    \fn QString QAccessibleInterface::text( Text t, int control ) const

    Returns a string property \a t of the child object specified by \a
    control, or the string property of the object itself if \a control
    is 0.

    The \e Name is a string used by clients to identify, find or
    announce an accessible object for the user. All objects must have
    a name that is unique within their container.

    An accessible object's \e Description provides textual information
    about an object's visual appearance. The description is primarily
    used to provide greater context for low-vision or blind users, but
    is also used for context searching or other applications. Not all
    objects have a description. An "OK" button would not need a
    description, but a toolbutton that shows a picture of a smiley
    would.

    The \e Value of an accessible object represents visual information
    contained by the object, e.g. the text in a line edit. Usually,
    the value can be modified by the user. Not all objects have a
    value, e.g. static text labels don't, and some objects have a
    state that already is the value, e.g. toggle buttons.

    The \e Help text provides information about the function and
    usage of an accessible object. Not all objects provide this
    information.

    An accessible object's \e DefaultAction describes the object's
    primary method of manipulation, and should be a verb or a short
    phrase, e.g. "Press" for a button.

    The accelerator is a keyboard shortcut that activates the default
    action of the object. A keyboard shortcut is the underlined
    character in the text of a menu, menu item or control, and is
    either the character itself, or a combination of this character
    and a modifier key like ALT, CTRL or SHIFT. Command controls like
    tool buttons also have shortcut keys and usually display them in
    their tooltip.

    \sa role(), state(), selection()
*/

/*!
    \fn void QAccessibleInterface::setText( Text t, int control, const QString &text )

    Sets the text property \a t of the child object \a control to \a
    text. If \a control is 0, the text property of the object itself
    is set.
*/

/*!
    \fn QAccessible::Role QAccessibleInterface::role( int control ) const

    Returns the role of the object if \a control is 0, or the role of
    the object's sub-element with ID \a control. The role of an object
    is usually static. All accessible objects have a role.

    \sa text(), state(), selection()
*/

/*!
    \fn QAccessible::State QAccessibleInterface::state( int control ) const

    Returns the current state of the object if \a control is 0, or the
    state of the object's sub-element element with ID \a control. All
    objects have a state.

    \sa text(), role(), selection()
*/

/*!
    \fn QMemArray<int> QAccessibleInterface::selection() const

    Returns the list of all the element IDs that are selected.

    \sa text(), role(), state()
*/

/*!
    \fn bool QAccessibleInterface::doDefaultAction( int control )

    Calling this function performs the default action of the child
    object specified by \a control, or the default action of the
    object itself if \a control is 0.
*/

/*!
    \fn bool QAccessibleInterface::setFocus( int control )

    Gives the focus to the child object specified by \a control, or to
    the object itself if \a control is 0.

    Returns TRUE if the focus could be set; otherwise returns FALSE.
*/

/*!
    \fn bool QAccessibleInterface::setSelected( int control, bool on, bool extend )

    Sets the selection of the child object with ID \a control to \a
    on. If \a extend is TRUE, all child elements between the focused
    item and the specified child object have their selection set to \a
    on.

    Returns TRUE if the selection could be set; otherwise returns
    FALSE.

    \sa setFocus(), clearSelection()
*/

/*!
    \fn void QAccessibleInterface::clearSelection()

    Removes any selection from the object.

    \sa setSelected()
*/



/*!
    \class QAccessibleObject qaccessible.h
    \brief The QAccessibleObject class implements parts of the
    QAccessibleInterface for QObjects.

    \ingroup misc

    This class is mainly provided for convenience. All subclasses of
    the QAccessibleInterface should use this class as the base class.
*/

/*!
    Creates a QAccessibleObject for \a object.
*/
QAccessibleObject::QAccessibleObject( QObject *object )
: object_(object)
{
    if ( !qAccessibleInterface ) {
	qAccessibleInterface = new AccessibleCache;
	if ( !cleanupAdded ) {
	    tqAddPostRoutine( qAccessibleCleanup );
	    cleanupAdded = TRUE;
	}
    }

    qAccessibleInterface->addObject(object, this);
}

/*!
    Destroys the QAccessibleObject.

    This only happens when a call to release() decrements the internal
    reference counter to zero.
*/
QAccessibleObject::~QAccessibleObject()
{
    if ( qAccessibleInterface ) {
	qAccessibleInterface->removeObject(object_);
	if ( !qAccessibleInterface->count() ) {
	    delete qAccessibleInterface;
	    qAccessibleInterface = 0;
	}
    }
}

/*!
    \reimp
*/
QRESULT QAccessibleObject::queryInterface( const QUuid &uuid, QUnknownInterface **iface )
{
    *iface = 0;
    if ( uuid == IID_QAccessible )
	*iface = (QAccessibleInterface*)this;
    else if ( uuid == IID_QUnknown )
	*iface = (QUnknownInterface*)this;
    else
	return QE_NOINTERFACE;

    (*iface)->addRef();
    return QS_OK;
}

/*!
    Returns the QObject for which this QAccessibleInterface
    implementation provides information. Use isValid() to make sure
    the object pointer is safe to use.
*/
QObject *QAccessibleObject::object() const
{
#if defined(QT_CHECK_RANGE)
    if ( !isValid() )
	tqWarning( "QAccessibleInterface is invalid. Crash pending..." );
#endif
    return object_;
}

/*!
    \reimp
*/
bool QAccessibleObject::isValid() const
{
    return !object_.isNull();
}

#endif