Warning, file /libraries/libqaccessibilityclient/examples/accessibleapps/accessibleproperties.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 Sebastian Sauer <sebastian.sauer@kdab.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "accessibleproperties.h"
0008 
0009 #include "qaccessibilityclient/registry.h"
0010 
0011 using namespace QAccessibleClient;
0012 
0013 ObjectProperties::ObjectProperties(QObject *parent)
0014     : QStandardItemModel(parent)
0015 {
0016     setColumnCount(2);
0017     setHorizontalHeaderLabels( QStringList() << QStringLiteral("Property") << QStringLiteral("Value") );
0018 
0019     connect(this, SIGNAL(itemChanged(QStandardItem *)), this, SLOT(slotDataChanged(QStandardItem *)));
0020 }
0021 
0022 ObjectProperties::~ObjectProperties()
0023 {
0024 }
0025 
0026 void ObjectProperties::slotDataChanged(QStandardItem *item) {
0027     if (item == m_textItem) {
0028         QString newText = item->data(Qt::EditRole).toString();
0029         m_acc.setText(newText);
0030     } else if (item == m_valueItem) {
0031         bool couldConvert;
0032         double value = item->data(Qt::EditRole).toDouble(&couldConvert);
0033         if (couldConvert) {
0034             m_acc.setCurrentValue(value);
0035         }
0036 
0037         m_valueItem = nullptr; //Prevent recursion
0038         item->setData(m_acc.currentValue(), Qt::DisplayRole);
0039         m_valueItem = item;
0040     }
0041 }
0042 
0043 QVariant ObjectProperties::headerData(int section, Qt::Orientation orientation, int role) const
0044 {
0045     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
0046         if (section == 0) {
0047             return QStringLiteral("Property");
0048         }
0049         if (section == 1) {
0050             return QStringLiteral("Value");
0051         }
0052     }
0053     return QVariant();
0054 }
0055 
0056 QHash<int,QByteArray> ObjectProperties::roleNames() const
0057 {
0058     QHash<int, QByteArray> roles;
0059     roles[NameRole] = "name";
0060     roles[ValueRole] = "value";
0061     return roles;
0062 }
0063 
0064 void ObjectProperties::setAccessibleObject(const QAccessibleClient::AccessibleObject &acc)
0065 {
0066     beginResetModel();
0067     m_acc = acc;
0068     m_textItem = nullptr;
0069     m_valueItem = nullptr;
0070 
0071     clear();
0072 
0073     if (!acc.isValid()) {
0074         endResetModel();
0075         return;
0076     }
0077 
0078     QAccessibleClient::AccessibleObject::Interfaces interfaces = acc.supportedInterfaces();
0079     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::AccessibleInterface)) {
0080         QStandardItem *item = append(QStringLiteral("Accessible"));
0081         append(QStringLiteral("Name"), acc.name(), item);
0082         append(QStringLiteral("Description"), acc.description(), item);
0083         append(QStringLiteral("Role"), acc.roleName(), item);
0084         append(QStringLiteral("LocalizedRole"), acc.localizedRoleName(), item);
0085         append(QStringLiteral("Visible"), acc.isVisible(), item);
0086         append(QStringLiteral("Default"), acc.isDefault(), item);
0087         append(QStringLiteral("State"), acc.stateString(), item);
0088         append(QStringLiteral("AccessibleId"), acc.accessibleId(), item);
0089         append(tr("Url"), acc.url(), item);
0090         AccessibleObject parent = acc.parent();
0091         if (parent.isValid())
0092             append(tr("Parent"), parent.url(), item);
0093         int childCount = acc.childCount();
0094         QStandardItem *children = append(QStringLiteral("Children"), acc.childCount(), item);
0095         for (int i = 0; i < childCount; ++i) {
0096             AccessibleObject child = acc.child(i);
0097             if (!child.isValid()) {
0098                 append(QLatin1String("Broken child"), QString::number(i), children);
0099             } else {
0100                 append(child.name().isEmpty() ? tr("[%1]").arg(child.roleName()) : child.name(), child.url(), children);
0101             }
0102         }
0103         //GetAttributes
0104     }
0105     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::ComponentInterface)) {
0106         QStandardItem *item = append(QStringLiteral("Component"));
0107         append(QStringLiteral("BoundingRect"), acc.boundingRect(), item);
0108         append(QStringLiteral("Layer"), acc.layer(), item);
0109         append(QStringLiteral("MDIZOrder"), acc.mdiZOrder(), item);
0110         append(QStringLiteral("Alpha"), acc.alpha(), item);
0111     }
0112     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::CollectionInterface)) {
0113         QStandardItem *item = append(QStringLiteral("Collection"));
0114         Q_UNUSED(item);
0115     }
0116     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::ApplicationInterface)) {
0117         QStandardItem *item = append(QStringLiteral("Application"));
0118         append(QStringLiteral("ToolkitName"), acc.appToolkitName(), item);
0119         append(QStringLiteral("Version"), acc.appVersion(), item);
0120         append(QStringLiteral("Id"), acc.appId(), item);
0121         append(QStringLiteral("Locale"), acc.appLocale(), item);
0122         append(QStringLiteral("BusAddress"), acc.appBusAddress(), item);
0123     }
0124     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::DocumentInterface)) {
0125         QStandardItem *item = append(QStringLiteral("Document"));
0126         Q_UNUSED(item);
0127         //GetLocale
0128         //GetAttributeValue
0129         //GetAttributes
0130     }
0131 
0132     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::EditableTextInterface)) {
0133         QStandardItem *item = append(QStringLiteral("EditableText"));
0134         Q_UNUSED(item);
0135     }
0136     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::HyperlinkInterface)) {
0137         QStandardItem *item = append(QStringLiteral("Hyperlink"));
0138         Q_UNUSED(item);
0139         /*
0140         <property name="NAnchors" type="n" access="read"/>
0141         <property name="StartIndex" type="i" access="read"/>
0142         <property name="EndIndex" type="i" access="read"/>
0143         <method name="GetObject">
0144             <arg direction="in" name="i" type="i"/>
0145             <arg direction="out" type="(so)"/>
0146             <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiObjectReference"/>
0147         </method>
0148         0<method name="GetURI">
0149             <arg direction="in" name="i" type="i"/>
0150             <arg direction="out" type="s"/>
0151         </method>
0152         <method name="IsValid">
0153             <arg direction="out" type="b"/>
0154         </method>
0155         */
0156     }
0157     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::HypertextInterface)) {
0158         QStandardItem *item = append(QStringLiteral("Hypertext"));
0159         Q_UNUSED(item);
0160         /*
0161         <method name="GetNLinks">
0162             <arg direction="out" type="i"/>
0163         </method>
0164         <method name="GetLink">
0165             <arg direction="in" name="linkIndex" type="i"/>
0166             <arg direction="out" type="(so)"/>
0167             <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiObjectReference"/>
0168         </method>
0169         <method name="GetLinkIndex">
0170             <arg direction="in" name="characterIndex" type="i"/>
0171             <arg direction="out" type="i"/>
0172         </method>
0173         */
0174     }
0175     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::ImageInterface)) {
0176         QStandardItem *item = append(QStringLiteral("Image"));
0177         append(QStringLiteral("Description"), acc.imageDescription(), item);
0178         append(QStringLiteral("Locale"), acc.imageLocale(), item);
0179         append(QStringLiteral("Rect"), acc.imageRect(), item);
0180     }
0181     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::SelectionInterface)) {
0182         QStandardItem *item = append(QStringLiteral("Selection"));
0183         for (const QAccessibleClient::AccessibleObject &s : acc.selection()) {
0184             append(s.name(), s.role(), item);
0185         }
0186     }
0187     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::TableInterface)) {
0188         QStandardItem *item = append(QStringLiteral("Table"));
0189         Q_UNUSED(item);
0190         /*
0191         <property name="NRows" type="i" access="read"/>
0192         <property name="NColumns" type="i" access="read"/>
0193         <property name="Caption" type="(so)" access="read">
0194             <annotation name="com.trolltech.QtDBus.QtTypeName" value="QSpiObjectReference"/>
0195         </property>
0196         <property name="Summary" type="(so)" access="read">
0197             <annotation name="com.trolltech.QtDBus.QtTypeName" value="QSpiObjectReference"/>
0198         </property>
0199         <property name="NSelectedRows" type="i" access="read"/>
0200         <property name="NSelectedColumns" type="i" access="read"/>
0201         <method name="GetRowDescription">
0202             <arg direction="in" name="row" type="i"/>
0203             <arg direction="out" type="s"/>
0204         </method>
0205         <method name="GetColumnDescription">
0206             <arg direction="in" name="column" type="i"/>
0207             <arg direction="out" type="s"/>
0208         </method>
0209         <method name="GetSelectedRows">
0210             <arg direction="out" type="ai"/>
0211             <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiIntList"/>
0212         </method>
0213         <method name="GetSelectedColumns">
0214             <arg direction="out" type="ai"/>
0215             <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiIntList"/>
0216         </method>
0217         */
0218     }
0219     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::TextInterface)) {
0220         QStandardItem *item = append(QStringLiteral("Text"));
0221         int offset = acc.caretOffset();
0222         append(QStringLiteral("CaretOffset"), offset, item);
0223         append(QStringLiteral("CharacterCount"), acc.characterCount(), item);
0224         append(QStringLiteral("CharacterRect"), acc.characterRect(offset), item);
0225 
0226         QString text = acc.text();
0227         if (interfaces.testFlag(QAccessibleClient::AccessibleObject::EditableTextInterface)) {
0228             append(QStringLiteral("Text"), text, item, &m_textItem);
0229         } else {
0230             append(QStringLiteral("Text"), text, item);
0231         }
0232 
0233         QList< QPair<int,int> > selections = acc.textSelections();
0234         QStandardItem *selectionsItem = append(QStringLiteral("Selections"), selections.count(), item);
0235         for (int i = 0; i < selections.count(); ++i) {
0236             QPair<int,int> sel = selections[i];
0237             int startOffset = sel.first;
0238             int endOffset = sel.second;
0239             Q_ASSERT(startOffset <= endOffset);
0240             append( QStringLiteral("%1:%2").arg(startOffset).arg(endOffset),
0241                     text.mid(startOffset, endOffset - startOffset),
0242                     selectionsItem );
0243         }
0244     }
0245     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::ValueInterface)) {
0246         QStandardItem *item = append(QStringLiteral("Value"));
0247         append(QStringLiteral("Current"), acc.currentValue(), item, &m_valueItem);
0248         append(QStringLiteral("Minimum"), acc.minimumValue(), item);
0249         append(QStringLiteral("Maximum"), acc.maximumValue(), item);
0250         append(QStringLiteral("Increment"), acc.minimumValueIncrement(), item);
0251     }
0252     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::SocketInterface)) {
0253         QStandardItem *item = append(QStringLiteral("Socket"));
0254         Q_UNUSED(item);
0255     }
0256 
0257     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::EventKeyboardInterface)) {
0258         QStandardItem *item = append(QStringLiteral("EventKeyboard"));
0259         Q_UNUSED(item);
0260     }
0261     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::EventMouseInterface)) {
0262         QStandardItem *item = append(QStringLiteral("EventMouse"));
0263         Q_UNUSED(item);
0264     }
0265     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::EventObjectInterface)) {
0266         QStandardItem *item = append(QStringLiteral("EventObject"));
0267         Q_UNUSED(item);
0268     }
0269     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::EventWindowInterface)) {
0270         QStandardItem *item = append(QStringLiteral("EventWindow"));
0271         Q_UNUSED(item);
0272     }
0273     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::EventFocusInterface)) {
0274         QStandardItem *item = append(QStringLiteral("EventFocus"));
0275         Q_UNUSED(item);
0276     }
0277 
0278     if (interfaces.testFlag(QAccessibleClient::AccessibleObject::ActionInterface)) {
0279         QStandardItem *item = append(QStringLiteral("Action"));
0280         for (const QSharedPointer<QAction> &a : acc.actions()) {
0281             QStandardItem *nameItem = new QStandardItem(a->text());
0282             QStandardItem *valueItem = new QStandardItem(a->whatsThis());
0283             nameItem->setEditable(false);
0284             valueItem->setEditable(false);
0285             item->appendRow(QList<QStandardItem*>() << nameItem << valueItem);
0286         }
0287     }
0288 
0289     endResetModel();
0290 }
0291 
0292 void ObjectProperties::doubleClicked(const QModelIndex &index)
0293 {
0294     if (!index.isValid() || !index.parent().isValid() || index.parent().data().toString() != QLatin1String("Action"))
0295         return;
0296 
0297     const auto actions{m_acc.actions()};
0298     for (const QSharedPointer<QAction> &action : actions) {
0299         if (action->text() == data(index).toString()) {
0300             action->trigger();
0301             return;
0302         }
0303     }
0304 }
0305 
0306 QStandardItem* ObjectProperties::append(const QString &name, const QVariant &value, QStandardItem *parentItem, QStandardItem **changeHandler)
0307 {
0308     if (!parentItem)
0309         parentItem = invisibleRootItem();
0310     QStandardItem *nameItem = new QStandardItem(name);
0311     QString text;
0312 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0313     switch (value.metaType().id()) {
0314 #else
0315     switch (value.type()) {
0316 #endif
0317         case QMetaType::QPoint: {
0318             QPoint p = value.toPoint();
0319             text = QStringLiteral("%1:%2").arg(p.x()).arg(p.y());
0320         } break;
0321         case QMetaType::QPointF: {
0322             QPointF p = value.toPointF();
0323             text = QStringLiteral("%1:%2").arg(p.x()).arg(p.y());
0324         } break;
0325         case QMetaType::QRect: {
0326             QRect r = value.toRect();
0327             text = QStringLiteral("%1:%2 %3x%4").arg(r.left()).arg(r.top()).arg(r.width()).arg(r.height());
0328         } break;
0329         case QMetaType::QRectF: {
0330             QRectF r = value.toRectF();
0331             text = QStringLiteral("%1:%2 %3x%4").arg(r.left()).arg(r.top()).arg(r.width()).arg(r.height());
0332         } break;
0333         default:
0334             text = value.toString();
0335             break;
0336     }
0337     QStandardItem *valueItem = new QStandardItem(text);
0338     parentItem->appendRow(QList<QStandardItem*>() << nameItem << valueItem);
0339     nameItem->setEditable(false);
0340 
0341     if (changeHandler) {
0342         *changeHandler = valueItem;
0343         valueItem->setEditable(true);
0344     } else {
0345         valueItem->setEditable(false);
0346     }
0347 
0348     return nameItem;
0349 }
0350 
0351 #include "moc_accessibleproperties.cpp"