Qt Accessibility Client

accessibleobject.cpp
1 /*
2  SPDX-FileCopyrightText: 2012 Frederik Gladhorn <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 
7 #include "accessibleobject.h"
8 #include "qaccessibilityclient_debug.h"
9 
10 #include <QString>
11 #include <QDebug>
12 
13 #include "accessibleobject_p.h"
14 #include "registry_p.h"
15 
16 #include <atspi/atspi-constants.h>
17 
18 using namespace QAccessibleClient;
19 
21  :d(nullptr)
22 {
23 }
24 
25 AccessibleObject::AccessibleObject(RegistryPrivate *registryPrivate, const QString &service, const QString &path)
26  :d(nullptr)
27 {
28  Q_ASSERT(registryPrivate);
29  Q_ASSERT(!service.isEmpty());
30  Q_ASSERT(!path.isEmpty());
31  if (registryPrivate->m_cache) {
32  const QString id = path + service;
33  d = registryPrivate->m_cache->get(id);
34  if (!d) {
35  d = QSharedPointer<AccessibleObjectPrivate>(new AccessibleObjectPrivate(registryPrivate, service, path));
36  registryPrivate->m_cache->add(id, d);
37  }
38  } else {
39  d = QSharedPointer<AccessibleObjectPrivate>(new AccessibleObjectPrivate(registryPrivate, service, path));
40  }
41 }
42 
44  :d(dd)
45 {
46 }
47 
49  : d(other.d)
50 {
51 }
52 
54 {
55 }
56 
58 {
59  if (!d || !d->registryPrivate)
60  return QString();
61  return d->path + d->service;
62 }
63 
65 {
66  if (!d || !d->registryPrivate)
67  return QUrl();
68  QUrl u;
69  u.setScheme(d->registryPrivate->ACCESSIBLE_OBJECT_SCHEME_STRING);
70  u.setPath(d->path);
71  u.setFragment(d->service);
72  return u;
73 }
74 
76 {
77  return d && d->registryPrivate
78  && (!d->service.isEmpty())
79  && (!d->path.isEmpty())
80  && (d->path != QLatin1String("/org/a11y/atspi/null"));
81 }
82 
84 {
85  d = other.d;
86  return *this;
87 }
88 
90 {
91  return (d == other.d) || (d && other.d && *d == *other.d);
92 }
93 
95 {
96  return d->registryPrivate->parentAccessible(*this);
97 }
98 
100 {
101  return d->registryPrivate->children(*this);
102 }
103 
105 {
106  QVector< QList<AccessibleObject> > result(roles.count());
107  const QList<AccessibleObject> all = children();
108  for(int i = 0; i < all.count(); ++i) {
109  const AccessibleObject &child = all[i];
110  int index = roles.indexOf(child.role());
111  if (index < 0) continue;
112  result[index].append(child);
113  }
114  return result;
115 }
116 
118 {
119  return d->registryPrivate->childCount(*this);
120 }
121 
123 {
124  return d->registryPrivate->child(*this, index);
125 }
126 
128 {
129  return d->registryPrivate->indexInParent(*this);
130 }
131 
133 {
134  return d->registryPrivate->accessibleId(*this);
135 }
136 
138 {
139  return d->registryPrivate->name(*this);
140 }
141 
143 {
144  return d->registryPrivate->description(*this);
145 }
146 
148 {
149  return d->registryPrivate->role(*this);
150 }
151 
153 {
154  return d->registryPrivate->roleName(*this);
155 }
156 
158 {
159  return d->registryPrivate->localizedRoleName(*this);
160 }
161 
163 {
164  return d->registryPrivate->layer(*this);
165 }
166 
168 {
169  return d->registryPrivate->mdiZOrder(*this);
170 }
171 
173 {
174  return d->registryPrivate->alpha(*this);
175 }
176 
178 {
179  if( supportedInterfaces() & AccessibleObject::ComponentInterface ){
180  return d->registryPrivate->boundingRect(*this);
181  } else {
182  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "boundingRect called on accessible that does not implement component";
183  return QRect();
184  }
185 }
186 
188 {
189  if( supportedInterfaces() & AccessibleObject::TextInterface ){
190  return d->registryPrivate->characterRect(*this, offset);
191  } else {
192  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "characterRect called on accessible that does not implement text";
193  return QRect();
194  }
195 }
196 
198 {
199  return d->registryPrivate->supportedInterfaces(*this);
200 }
201 
203 {
204  if( supportedInterfaces() & AccessibleObject::TextInterface ){
205  return d->registryPrivate->caretOffset(*this);
206  } else {
207  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "caretOffset called on accessible that does not implement text";
208  return 0;
209  }
210 }
211 
213 {
214  if( supportedInterfaces() & AccessibleObject::TextInterface ){
215  return d->registryPrivate->characterCount(*this);
216  } else {
217  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "characterCount called on accessible that does not implement text";
218  return 0;
219  }
220 }
221 
222 QString AccessibleObject::text(int startOffset, int endOffset) const
223 {
224  if( supportedInterfaces() & AccessibleObject::TextInterface )
225  return d->registryPrivate->text(*this, startOffset, endOffset);
226  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "text called on accessible that does not implement text";
227  return QString();
228 }
229 
230 QString AccessibleObject::textWithBoundary(int offset, TextBoundary boundary, int *startOffset, int *endOffset) const
231 {
232  if (supportedInterfaces() & AccessibleObject::TextInterface)
233  return d->registryPrivate->textWithBoundary(*this, offset, boundary, startOffset, endOffset);
234  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "text called on accessible that does not implement text";
235  return QString();
236 }
237 
239 {
240  if( supportedInterfaces() & AccessibleObject::EditableTextInterface )
241  return d->registryPrivate->setText(*this, text);
242  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "setText called on accessible that does not implement editableText";
243  return false;
244 }
245 
246 bool AccessibleObject::insertText(const QString &text, int position, int length)
247 {
248  if( supportedInterfaces() & AccessibleObject::EditableTextInterface )
249  return d->registryPrivate->insertText(*this, text, position, length);
250  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "insertText called on accessible that does not implement editableText";
251  return false;
252 }
253 
254 bool AccessibleObject::copyText(int startPos, int endPos)
255 {
256  if( supportedInterfaces() & AccessibleObject::EditableTextInterface )
257  return d->registryPrivate->copyText(*this, startPos, endPos);
258  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "copyText called on accessible that does not implement editableText";
259  return false;
260 }
261 
262 bool AccessibleObject::cutText(int startPos, int endPos)
263 {
264  if( supportedInterfaces() & AccessibleObject::EditableTextInterface )
265  return d->registryPrivate->cutText(*this, startPos, endPos);
266  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "cutText called on accessible that does not implement editableText";
267  return false;
268 }
269 
270 bool AccessibleObject::deleteText(int startPos, int endPos)
271 {
272  if( supportedInterfaces() & AccessibleObject::EditableTextInterface )
273  return d->registryPrivate->deleteText(*this, startPos, endPos);
274  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "deleteText called on accessible that does not implement editableText";
275  return false;
276 }
277 
278 bool AccessibleObject::pasteText(int position)
279 {
280  if( supportedInterfaces() & AccessibleObject::EditableTextInterface )
281  return d->registryPrivate->pasteText(*this, position);
282  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "pasteText called on accessible that does not implement editableText";
283  return false;
284 }
285 
287 {
288  if(supportedInterfaces() & AccessibleObject::Text)
289  return d->registryPrivate->textSelections(*this);
290  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "textSelections called on accessible that does not implement text";
291  return QList< QPair<int,int> >();
292 }
293 
295 {
296  if(supportedInterfaces() & AccessibleObject::Text)
297  return d->registryPrivate->setTextSelections(*this, selections);
298  qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "setTextSelections called on accessible that does not implement text";
299 }
300 
302 {
303  Interfaces ifaces = supportedInterfaces();
304  if (ifaces & TextInterface) {
305  const int offset = caretOffset();
306  const QRect r = characterRect(offset);
307  if (r.x() != 0 || r.y() != 0)
308  return r.center();
309  }
310  if (ifaces & ComponentInterface) {
311  const QRect r = boundingRect();
312  if (!r.isNull())
313  return r.center();
314  }
315  AccessibleObject p = parent();
316  if (p.isValid())
317  return p.focusPoint(); // recursive
318  return QPoint();
319 }
320 
322 {
323  return d->registryPrivate->application(*this);
324 }
325 
327 {
328  return d->registryPrivate->appToolkitName(*this);
329 }
330 
332 {
333  return d->registryPrivate->appVersion(*this);
334 }
335 
337 {
338  return d->registryPrivate->appId(*this);
339 }
340 
342 {
343  return d->registryPrivate->appLocale(*this, lctype);
344 }
345 
347 {
348  return d->registryPrivate->appBusAddress(*this);
349 }
350 
352 {
353  return d->registryPrivate->minimumValue(*this);
354 }
355 
357 {
358  return d->registryPrivate->maximumValue(*this);
359 }
360 
362 {
363  return d->registryPrivate->minimumValueIncrement(*this);
364 }
365 
367 {
368  return d->registryPrivate->currentValue(*this);
369 }
370 
372 {
373  return d->registryPrivate->setCurrentValue(*this, value);
374 }
375 
377 {
378  return d->registryPrivate->selection(*this);
379 }
380 
382 {
383  return d->registryPrivate->imageDescription(*this);
384 }
385 
387 {
388  return d->registryPrivate->imageLocale(*this);
389 }
390 
392 {
393  return d->registryPrivate->imageRect(*this);
394 }
395 
397 {
398  // Actions in atspi are supposed to be static what means they cannot change in
399  // between (e.g. actions removed or added or edited) so we can safely just
400  // fetch them only once and store the result for the life-time of the object,
401  if (!d->actionsFetched) {
402  d->actionsFetched = true;
403  d->actions = d->registryPrivate->actions(*this);
404  }
405  return d->actions;
406 }
407 
409 {
410  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SELECTABLE_TEXT);
411 }
412 
414 {
415  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_HAS_TOOLTIP);
416 }
417 
419 {
420  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_ACTIVE);
421 }
422 
424 {
425  //FIXME: Find better AccessibleObject::isCheckable
426  //return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_);
427 
428  Role role = d->registryPrivate->role(*this);
429  if (role == AccessibleObject::CheckBox ||
430  role == AccessibleObject::CheckableMenuItem ||
431  role == AccessibleObject::RadioButton ||
432  role == AccessibleObject::RadioMenuItem ||
433  role == AccessibleObject::ToggleButton)
434  return true;
435  return false;
436 }
437 
439 {
440  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_CHECKED);
441 }
442 
444 {
445  return d->defunct;
446 }
447 
449 {
450  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_IS_DEFAULT);
451 }
452 
454 {
455  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_EDITABLE);
456 }
457 
459 {
460  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_ENABLED);
461 }
462 
464 {
465  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_EXPANDABLE);
466 }
467 
469 {
470  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_EXPANDED);
471 }
472 
474 {
475  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_FOCUSABLE);
476 }
477 
479 {
480  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_FOCUSED);
481 }
482 
484 {
485  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_MULTI_LINE);
486 }
487 
489 {
490  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SELECTABLE);
491 }
492 
494 {
495  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SELECTED);
496 }
497 
499 {
500  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SENSITIVE);
501 }
502 
504 {
505  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SINGLE_LINE);
506 }
507 
509 {
510  QStringList s;
511  if (isActive()) s << QStringLiteral("Active");
512  if (isCheckable()) s << QStringLiteral("Checkable");
513  if (isChecked()) s << QStringLiteral("Checked");
514  if (isEditable()) s << QStringLiteral("Editable");
515  if (isExpandable()) s << QStringLiteral("Expandable");
516  if (isExpanded()) s << QStringLiteral("Expanded");
517  if (isFocusable()) s << QStringLiteral("Focusable");
518  if (isFocused()) s << QStringLiteral("Focused");
519  if (isMultiLine()) s << QStringLiteral("MultiLine");
520  if (isSelectable()) s << QStringLiteral("Selectable");
521  if (isSelected()) s << QStringLiteral("Selected");
522  if (isSensitive()) s << QStringLiteral("Sensitive");
523  if (isSingleLine()) s << QStringLiteral("SingleLine");
524  if (isEnabled()) s << QStringLiteral("Enabled");
525  return s.join(QLatin1String(", "));
526 }
527 
529 {
530  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_VISIBLE);
531 }
532 
534 {
535  return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SUPPORTS_AUTOCOMPLETION);
536 }
537 
538 #ifndef QT_NO_DEBUG_STREAM
539 QACCESSIBILITYCLIENT_EXPORT QDebug QAccessibleClient::operator<<(QDebug d, const AccessibleObject &object)
540 {
541  d.nospace();
542  d << "AccessibleObject(";
543  if (object.d) {
544  d << "service=" << object.d->service;
545  d << " path=" << object.d->path;
546  d << " name=" << object.name();
547  } else {
548  d << "invalid";
549  }
550  d << ")";
551  return d.space();
552 }
553 #endif
bool isDefunct() const
Returns if the AccessibleObject is defunct - that means it does not properly respont to requests and ...
bool hasToolTip() const
Returns if the AccessibleObject has a tool tip.
int characterCount() const
Returns the number of characters.
QString appBusAddress() const
The application dbus address.
AccessibleObject application() const
Returns the application object.
Role
The role indicates the type of UI element that an AccessibleObject represents.
bool isValid() const
Returns true if this object is valid.
int indexInParent() const
Returns this accessible's index in it's parent's list of children.
Interfaces supportedInterfaces() const
Returns List of interfaces supported by the accessible.
QString appToolkitName() const
Returns the toolkit name.
int count(const T &value) const const
bool isExpanded() const
Returns if the AccessibleObject is currently expanded.
QDebug & nospace()
void append(const T &value)
double alpha() const
Obtain the alpha value of the component.
double currentValue() const
The current value of the valuator.
QDebug & space()
int x() const const
int y() const const
int appId() const
Returns the unique application identifier.
QString textWithBoundary(int offset, TextBoundary boundary, int *startOffset=nullptr, int *endOffset=nullptr) const
Returns the text of the TextInterface by boundary.
bool isCheckable() const
Returns if the AccessibleObject is checkable (often indicates a check action)
QString roleName() const
Returns the name of the role of this accessible.
QRect boundingRect() const
Returns a bounding rectangle for the accessible.
QString appLocale(LocaleType lctype=LocaleTypeMessages) const
The application locale.
void setScheme(const QString &scheme)
AccessibleObject()
Construct an invalid AccessibleObject.
double maximumValue() const
The maximum value allowed by this valuator.
AccessibleObject child(int index) const
Returns a specific child at position index.
bool supportsAutocompletion() const
Returns if the AccessibleObject supports automatic text completion.
bool isVisible() const
Returns if the AccessibleObject is currently visible (it can still be off the screen,...
QUrl url() const
Returns a QUrl that references the AccessibleObject.
QRect imageRect() const
The image boundaries.
void setTextSelections(const QList< QPair< int, int > > &selections)
Set text selections, usually only one selection will be set, use a list containing one QPair with the...
bool isSelectable() const
Returns if the AccessibleObject is selectable.
bool insertText(const QString &text, int position=0, int length=-1)
Insert the text into the EditableTextInterface.
bool isDefault() const
Returns if the AccessibleObject is the default widget (e.g. a button in a dialog)
bool isFocused() const
Returns if the AccessibleObject is currently focused.
bool setText(const QString &text)
Set the text of the EditableTextInterface.
int indexOf(const T &value, int from) const const
bool pasteText(int position)
Paste the text from the clipboard into the EditableTextInterface.
bool isFocusable() const
Returns if the AccessibleObject is focusable.
bool isEmpty() const const
QString imageDescription() const
A description text of the image.
bool isChecked() const
Returns if the AccessibleObject is currently checked.
QString id() const
Returns a unique identifier for the object.
int childCount() const
Returns the number of children for this accessible.
QPoint center() const const
QList< AccessibleObject > children() const
Returns this accessible's children in a list.
AccessibleObject parent() const
Returns this object's parent.
bool isNull() const const
QString localizedRoleName() const
Returns the name of the role of this accessible.
QString join(const QString &separator) const const
QList< AccessibleObject > selection() const
Returns the selection of accessible objects.
bool setCurrentValue(const double value)
Set the value of the valuator.
bool hasSelectableText() const
Returns if the AccessibleObject allows text selections.
T * get() const const
bool isExpandable() const
Returns if the AccessibleObject can be expanded to show more information.
bool isActive() const
Returns if the AccessibleObject is currently active.
This class represents an accessible object.
QString appVersion() const
Returns the toolkit version.
bool cutText(int startPos, int endPos)
Cut the text from the EditableTextInterface into the clipboard.
QString stateString() const
Return a string representing states of this object.
bool isSensitive() const
Returns if the AccessibleObject reacts to input events.
int caretOffset() const
Returns the offset of the caret from the beginning of the text.
QString text(int startOffset=0, int endOffset=-1) const
Returns the text of the TextInterface.
Role role() const
Returns the role as integer value of this accessible.
QString imageLocale() const
The locale of the image.
void setPath(const QString &path, QUrl::ParsingMode mode)
QVector< QSharedPointer< QAction > > actions() const
Returns a list of actions supported by this accessible.
QString accessibleId() const
Returns the accessible id of this accessible.
double minimumValueIncrement() const
The smallest incremental change which this valuator allows.
double minimumValue() const
The minimum value allowed by this valuator.
bool isSelected() const
Returns if the AccessibleObject is currently selected.
void setFragment(const QString &fragment, QUrl::ParsingMode mode)
~AccessibleObject()
Destroys the AccessibleObject.
QList< QPair< int, int > > textSelections() const
Returns a list of selections the text has.
int mdiZOrder() const
Obtain the relative stacking order (i.e.
int layer() const
The ComponentLayer in which this object resides.
QRect characterRect(int offset) const
Returns a bounding rectangle for the character at position offset.
bool copyText(int startPos, int endPos)
Copy the text from the EditableTextInterface into the clipboard.
TextBoundary
The TextBoundaries enum represents the different boundaries when asking for text at a certain offset.
bool operator==(const AccessibleObject &other) const
Comparison operator.
QString name() const
Returns the name of this accessible.
AccessibleObject & operator=(const AccessibleObject &other)
Assignment operator.
QPoint focusPoint() const
Returns focus-point of the object.
bool deleteText(int startPos, int endPos)
Delete the text from the EditableTextInterface.
QString description() const
Returns the description for this accessible.
bool isMultiLine() const
Returns if the AccessibleObject is a multi line text edit.
bool isEnabled() const
Returns if the AccessibleObject is currently enabled.
bool isEditable() const
Returns if the AccessibleObject is an editable text.
bool isSingleLine() const
Returns if the AccessibleObject is a single line text edit.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Thu Dec 7 2023 04:00:59 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.