Warning, file /libraries/libqaccessibilityclient/src/qaccessibilityclient/accessibleobject.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2012 Frederik Gladhorn <gladhorn@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "accessibleobject.h" 0008 0009 #include <QString> 0010 #include <QDebug> 0011 0012 #include "accessibleobject_p.h" 0013 #include "registry_p.h" 0014 0015 #include <atspi/atspi-constants.h> 0016 0017 using namespace QAccessibleClient; 0018 0019 AccessibleObject::AccessibleObject() 0020 :d(nullptr) 0021 { 0022 } 0023 0024 AccessibleObject::AccessibleObject(RegistryPrivate *registryPrivate, const QString &service, const QString &path) 0025 :d(nullptr) 0026 { 0027 Q_ASSERT(registryPrivate); 0028 Q_ASSERT(!service.isEmpty()); 0029 Q_ASSERT(!path.isEmpty()); 0030 if (registryPrivate->m_cache) { 0031 const QString id = path + service; 0032 d = registryPrivate->m_cache->get(id); 0033 if (!d) { 0034 d = QSharedPointer<AccessibleObjectPrivate>(new AccessibleObjectPrivate(registryPrivate, service, path)); 0035 registryPrivate->m_cache->add(id, d); 0036 } 0037 } else { 0038 d = QSharedPointer<AccessibleObjectPrivate>(new AccessibleObjectPrivate(registryPrivate, service, path)); 0039 } 0040 } 0041 0042 AccessibleObject::AccessibleObject(const QSharedPointer<AccessibleObjectPrivate> &dd) 0043 :d(dd) 0044 { 0045 } 0046 0047 AccessibleObject::AccessibleObject(const AccessibleObject &other) 0048 : d(other.d) 0049 { 0050 } 0051 0052 AccessibleObject::~AccessibleObject() 0053 { 0054 } 0055 0056 QString AccessibleObject::id() const 0057 { 0058 if (!d || !d->registryPrivate) 0059 return QString(); 0060 return d->path + d->service; 0061 } 0062 0063 QUrl AccessibleObject::url() const 0064 { 0065 if (!d || !d->registryPrivate) 0066 return QUrl(); 0067 QUrl u; 0068 u.setScheme(d->registryPrivate->ACCESSIBLE_OBJECT_SCHEME_STRING); 0069 u.setPath(d->path); 0070 u.setFragment(d->service); 0071 return u; 0072 } 0073 0074 bool AccessibleObject::isValid() const 0075 { 0076 return d && d->registryPrivate 0077 && (!d->service.isEmpty()) 0078 && (!d->path.isEmpty()) 0079 && (d->path != QLatin1String("/org/a11y/atspi/null")); 0080 } 0081 0082 AccessibleObject &AccessibleObject::operator=(const AccessibleObject &other) 0083 { 0084 d = other.d; 0085 return *this; 0086 } 0087 0088 bool AccessibleObject::operator==(const AccessibleObject &other) const 0089 { 0090 return (d == other.d) || (d && other.d && *d == *other.d); 0091 } 0092 0093 AccessibleObject AccessibleObject::parent() const 0094 { 0095 return d->registryPrivate->parentAccessible(*this); 0096 } 0097 0098 QList<AccessibleObject> AccessibleObject::children() const 0099 { 0100 return d->registryPrivate->children(*this); 0101 } 0102 0103 QVector< QList<AccessibleObject> > AccessibleObject::children(const QList<Role> &roles) const 0104 { 0105 QVector< QList<AccessibleObject> > result(roles.count()); 0106 QList<AccessibleObject> all = children(); 0107 for(int i = 0; i < all.count(); ++i) { 0108 const AccessibleObject &child = all[i]; 0109 int index = roles.indexOf(child.role()); 0110 if (index < 0) continue; 0111 result[index].append(child); 0112 } 0113 return result; 0114 } 0115 0116 int AccessibleObject::childCount() const 0117 { 0118 return d->registryPrivate->childCount(*this); 0119 } 0120 0121 AccessibleObject AccessibleObject::child(int index) const 0122 { 0123 return d->registryPrivate->child(*this, index); 0124 } 0125 0126 int AccessibleObject::indexInParent() const 0127 { 0128 return d->registryPrivate->indexInParent(*this); 0129 } 0130 0131 QString AccessibleObject::accessibleId() const 0132 { 0133 return d->registryPrivate->accessibleId(*this); 0134 } 0135 0136 QString AccessibleObject::name() const 0137 { 0138 return d->registryPrivate->name(*this); 0139 } 0140 0141 QString AccessibleObject::description() const 0142 { 0143 return d->registryPrivate->description(*this); 0144 } 0145 0146 AccessibleObject::Role AccessibleObject::role() const 0147 { 0148 return d->registryPrivate->role(*this); 0149 } 0150 0151 QString AccessibleObject::roleName() const 0152 { 0153 return d->registryPrivate->roleName(*this); 0154 } 0155 0156 QString AccessibleObject::localizedRoleName() const 0157 { 0158 return d->registryPrivate->localizedRoleName(*this); 0159 } 0160 0161 int AccessibleObject::layer() const 0162 { 0163 return d->registryPrivate->layer(*this); 0164 } 0165 0166 int AccessibleObject::mdiZOrder() const 0167 { 0168 return d->registryPrivate->mdiZOrder(*this); 0169 } 0170 0171 double AccessibleObject::alpha() const 0172 { 0173 return d->registryPrivate->alpha(*this); 0174 } 0175 0176 QRect AccessibleObject::boundingRect() const 0177 { 0178 if( supportedInterfaces() & AccessibleObject::ComponentInterface ){ 0179 return d->registryPrivate->boundingRect(*this); 0180 } else { 0181 qWarning() << "boundingRect called on accessible that does not implement component"; 0182 return QRect(); 0183 } 0184 } 0185 0186 QRect AccessibleObject::characterRect(int offset) const 0187 { 0188 if( supportedInterfaces() & AccessibleObject::TextInterface ){ 0189 return d->registryPrivate->characterRect(*this, offset); 0190 } else { 0191 qWarning() << "characterRect called on accessible that does not implement text"; 0192 return QRect(); 0193 } 0194 } 0195 0196 AccessibleObject::Interfaces AccessibleObject::supportedInterfaces() const 0197 { 0198 return d->registryPrivate->supportedInterfaces(*this); 0199 } 0200 0201 int AccessibleObject::caretOffset() const 0202 { 0203 if( supportedInterfaces() & AccessibleObject::TextInterface ){ 0204 return d->registryPrivate->caretOffset(*this); 0205 } else { 0206 qWarning() << "caretOffset called on accessible that does not implement text"; 0207 return 0; 0208 } 0209 } 0210 0211 int AccessibleObject::characterCount() const 0212 { 0213 if( supportedInterfaces() & AccessibleObject::TextInterface ){ 0214 return d->registryPrivate->characterCount(*this); 0215 } else { 0216 qWarning() << "characterCount called on accessible that does not implement text"; 0217 return 0; 0218 } 0219 } 0220 0221 QString AccessibleObject::text(int startOffset, int endOffset) const 0222 { 0223 if( supportedInterfaces() & AccessibleObject::TextInterface ) 0224 return d->registryPrivate->text(*this, startOffset, endOffset); 0225 qWarning() << "text called on accessible that does not implement text"; 0226 return QString(); 0227 } 0228 0229 QString AccessibleObject::textWithBoundary(int offset, TextBoundary boundary, int *startOffset, int *endOffset) const 0230 { 0231 if (supportedInterfaces() & AccessibleObject::TextInterface) 0232 return d->registryPrivate->textWithBoundary(*this, offset, boundary, startOffset, endOffset); 0233 qWarning() << "text called on accessible that does not implement text"; 0234 return QString(); 0235 } 0236 0237 bool AccessibleObject::setText(const QString &text) 0238 { 0239 if( supportedInterfaces() & AccessibleObject::EditableTextInterface ) 0240 return d->registryPrivate->setText(*this, text); 0241 qWarning() << "setText called on accessible that does not implement editableText"; 0242 return false; 0243 } 0244 0245 bool AccessibleObject::insertText(const QString &text, int position, int length) 0246 { 0247 if( supportedInterfaces() & AccessibleObject::EditableTextInterface ) 0248 return d->registryPrivate->insertText(*this, text, position, length); 0249 qWarning() << "insertText called on accessible that does not implement editableText"; 0250 return false; 0251 } 0252 0253 bool AccessibleObject::copyText(int startPos, int endPos) 0254 { 0255 if( supportedInterfaces() & AccessibleObject::EditableTextInterface ) 0256 return d->registryPrivate->copyText(*this, startPos, endPos); 0257 qWarning() << "copyText called on accessible that does not implement editableText"; 0258 return false; 0259 } 0260 0261 bool AccessibleObject::cutText(int startPos, int endPos) 0262 { 0263 if( supportedInterfaces() & AccessibleObject::EditableTextInterface ) 0264 return d->registryPrivate->cutText(*this, startPos, endPos); 0265 qWarning() << "cutText called on accessible that does not implement editableText"; 0266 return false; 0267 } 0268 0269 bool AccessibleObject::deleteText(int startPos, int endPos) 0270 { 0271 if( supportedInterfaces() & AccessibleObject::EditableTextInterface ) 0272 return d->registryPrivate->deleteText(*this, startPos, endPos); 0273 qWarning() << "deleteText called on accessible that does not implement editableText"; 0274 return false; 0275 } 0276 0277 bool AccessibleObject::pasteText(int position) 0278 { 0279 if( supportedInterfaces() & AccessibleObject::EditableTextInterface ) 0280 return d->registryPrivate->pasteText(*this, position); 0281 qWarning() << "pasteText called on accessible that does not implement editableText"; 0282 return false; 0283 } 0284 0285 QList< QPair<int,int> > AccessibleObject::textSelections() const 0286 { 0287 if(supportedInterfaces() & AccessibleObject::Text) 0288 return d->registryPrivate->textSelections(*this); 0289 qWarning() << "textSelections called on accessible that does not implement text"; 0290 return QList< QPair<int,int> >(); 0291 } 0292 0293 void AccessibleObject::setTextSelections(const QList< QPair<int,int> > &selections) 0294 { 0295 if(supportedInterfaces() & AccessibleObject::Text) 0296 return d->registryPrivate->setTextSelections(*this, selections); 0297 qWarning() << "setTextSelections called on accessible that does not implement text"; 0298 } 0299 0300 QPoint AccessibleObject::focusPoint() const 0301 { 0302 Interfaces ifaces = supportedInterfaces(); 0303 if (ifaces & TextInterface) { 0304 int offset = caretOffset(); 0305 QRect r = characterRect(offset); 0306 if (r.x() != 0 || r.y() != 0) 0307 return r.center(); 0308 } 0309 if (ifaces & ComponentInterface) { 0310 QRect r = boundingRect(); 0311 if (!r.isNull()) 0312 return r.center(); 0313 } 0314 AccessibleObject p = parent(); 0315 if (p.isValid()) 0316 return p.focusPoint(); // recursive 0317 return QPoint(); 0318 } 0319 0320 AccessibleObject AccessibleObject::application() const 0321 { 0322 return d->registryPrivate->application(*this); 0323 } 0324 0325 QString AccessibleObject::appToolkitName() const 0326 { 0327 return d->registryPrivate->appToolkitName(*this); 0328 } 0329 0330 QString AccessibleObject::appVersion() const 0331 { 0332 return d->registryPrivate->appVersion(*this); 0333 } 0334 0335 int AccessibleObject::appId() const 0336 { 0337 return d->registryPrivate->appId(*this); 0338 } 0339 0340 QString AccessibleObject::appLocale(LocaleType lctype) const 0341 { 0342 return d->registryPrivate->appLocale(*this, lctype); 0343 } 0344 0345 QString AccessibleObject::appBusAddress() const 0346 { 0347 return d->registryPrivate->appBusAddress(*this); 0348 } 0349 0350 double AccessibleObject::minimumValue() const 0351 { 0352 return d->registryPrivate->minimumValue(*this); 0353 } 0354 0355 double AccessibleObject::maximumValue() const 0356 { 0357 return d->registryPrivate->maximumValue(*this); 0358 } 0359 0360 double AccessibleObject::minimumValueIncrement() const 0361 { 0362 return d->registryPrivate->minimumValueIncrement(*this); 0363 } 0364 0365 double AccessibleObject::currentValue() const 0366 { 0367 return d->registryPrivate->currentValue(*this); 0368 } 0369 0370 bool AccessibleObject::setCurrentValue(double value) 0371 { 0372 return d->registryPrivate->setCurrentValue(*this, value); 0373 } 0374 0375 QList<AccessibleObject> AccessibleObject::selection() const 0376 { 0377 return d->registryPrivate->selection(*this); 0378 } 0379 0380 QString AccessibleObject::imageDescription() const 0381 { 0382 return d->registryPrivate->imageDescription(*this); 0383 } 0384 0385 QString AccessibleObject::imageLocale() const 0386 { 0387 return d->registryPrivate->imageLocale(*this); 0388 } 0389 0390 QRect AccessibleObject::imageRect() const 0391 { 0392 return d->registryPrivate->imageRect(*this); 0393 } 0394 0395 QVector< QSharedPointer<QAction> > AccessibleObject::actions() const 0396 { 0397 // Actions in atspi are supposed to be static what means they cannot change in 0398 // between (e.g. actions removed or added or edited) so we can safely just 0399 // fetch them only once and store the result for the life-time of the object, 0400 if (!d->actionsFetched) { 0401 d->actionsFetched = true; 0402 d->actions = d->registryPrivate->actions(*this); 0403 } 0404 return d->actions; 0405 } 0406 0407 bool AccessibleObject::hasSelectableText() const 0408 { 0409 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SELECTABLE_TEXT); 0410 } 0411 0412 bool AccessibleObject::hasToolTip() const 0413 { 0414 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_HAS_TOOLTIP); 0415 } 0416 0417 bool AccessibleObject::isActive() const 0418 { 0419 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_ACTIVE); 0420 } 0421 0422 bool AccessibleObject::isCheckable() const 0423 { 0424 //FIXME: Find better AccessibleObject::isCheckable 0425 //return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_); 0426 0427 Role role = d->registryPrivate->role(*this); 0428 if (role == AccessibleObject::CheckBox || 0429 role == AccessibleObject::CheckableMenuItem || 0430 role == AccessibleObject::RadioButton || 0431 role == AccessibleObject::RadioMenuItem || 0432 role == AccessibleObject::ToggleButton) 0433 return true; 0434 return false; 0435 } 0436 0437 bool AccessibleObject::isChecked() const 0438 { 0439 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_CHECKED); 0440 } 0441 0442 bool AccessibleObject::isDefunct() const 0443 { 0444 return d->defunct; 0445 } 0446 0447 bool AccessibleObject::isDefault() const 0448 { 0449 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_IS_DEFAULT); 0450 } 0451 0452 bool AccessibleObject::isEditable() const 0453 { 0454 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_EDITABLE); 0455 } 0456 0457 bool AccessibleObject::isEnabled() const 0458 { 0459 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_ENABLED); 0460 } 0461 0462 bool AccessibleObject::isExpandable() const 0463 { 0464 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_EXPANDABLE); 0465 } 0466 0467 bool AccessibleObject::isExpanded() const 0468 { 0469 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_EXPANDED); 0470 } 0471 0472 bool AccessibleObject::isFocusable() const 0473 { 0474 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_FOCUSABLE); 0475 } 0476 0477 bool AccessibleObject::isFocused() const 0478 { 0479 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_FOCUSED); 0480 } 0481 0482 bool AccessibleObject::isMultiLine() const 0483 { 0484 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_MULTI_LINE); 0485 } 0486 0487 bool AccessibleObject::isSelectable() const 0488 { 0489 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SELECTABLE); 0490 } 0491 0492 bool AccessibleObject::isSelected() const 0493 { 0494 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SELECTED); 0495 } 0496 0497 bool AccessibleObject::isSensitive() const 0498 { 0499 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SENSITIVE); 0500 } 0501 0502 bool AccessibleObject::isSingleLine() const 0503 { 0504 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SINGLE_LINE); 0505 } 0506 0507 QString AccessibleObject::stateString() const 0508 { 0509 QStringList s; 0510 if (isActive()) s << QStringLiteral("Active"); 0511 if (isCheckable()) s << QStringLiteral("Checkable"); 0512 if (isChecked()) s << QStringLiteral("Checked"); 0513 if (isEditable()) s << QStringLiteral("Editable"); 0514 if (isExpandable()) s << QStringLiteral("Expandable"); 0515 if (isExpanded()) s << QStringLiteral("Expanded"); 0516 if (isFocusable()) s << QStringLiteral("Focusable"); 0517 if (isFocused()) s << QStringLiteral("Focused"); 0518 if (isMultiLine()) s << QStringLiteral("MultiLine"); 0519 if (isSelectable()) s << QStringLiteral("Selectable"); 0520 if (isSelected()) s << QStringLiteral("Selected"); 0521 if (isSensitive()) s << QStringLiteral("Sensitive"); 0522 if (isSingleLine()) s << QStringLiteral("SingleLine"); 0523 return s.join(QLatin1String(", ")); 0524 } 0525 0526 bool AccessibleObject::isVisible() const 0527 { 0528 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_VISIBLE); 0529 } 0530 0531 bool AccessibleObject::supportsAutocompletion() const 0532 { 0533 return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SUPPORTS_AUTOCOMPLETION); 0534 } 0535 0536 #ifndef QT_NO_DEBUG_STREAM 0537 QACCESSIBILITYCLIENT_EXPORT QDebug QAccessibleClient::operator<<(QDebug d, const AccessibleObject &object) 0538 { 0539 d.nospace(); 0540 d << "AccessibleObject("; 0541 if (object.d) { 0542 d << "service=" << object.d->service; 0543 d << " path=" << object.d->path; 0544 d << " name=" << object.name(); 0545 } else { 0546 d << "invalid"; 0547 } 0548 d << ")"; 0549 return d.space(); 0550 } 0551 #endif