diff --git a/examples/accessibleapps/accessibleproperties.h b/examples/accessibleapps/accessibleproperties.h index 10bf5bb..8e15294 100644 --- a/examples/accessibleapps/accessibleproperties.h +++ b/examples/accessibleapps/accessibleproperties.h @@ -1,57 +1,57 @@ /* Copyright 2012 Sebastian Sauer This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef ACCESSIBLEPROPERTIES_H #define ACCESSIBLEPROPERTIES_H #include #include #include "qaccessibilityclient/accessibleobject.h" class ObjectProperties : public QStandardItemModel { Q_OBJECT public: enum Role { NameRole, ValueRole }; explicit ObjectProperties(QObject *parent = nullptr); - virtual ~ObjectProperties(); + ~ObjectProperties() override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; QHash roleNames() const override; void setAccessibleObject(const QAccessibleClient::AccessibleObject &acc); QAccessibleClient::AccessibleObject currentObject() const { return m_acc; } public Q_SLOTS: void doubleClicked(const QModelIndex &index); void slotDataChanged(QStandardItem *item); private: QStandardItem* append(const QString &name, const QVariant &value = QVariant(), QStandardItem *parentItem = nullptr, QStandardItem **changeHandler = nullptr); QString stateString(const QAccessibleClient::AccessibleObject &acc); QAccessibleClient::AccessibleObject m_acc; QStandardItem* m_textItem; QStandardItem* m_valueItem; }; #endif diff --git a/examples/accessibleapps/accessibletree.h b/examples/accessibleapps/accessibletree.h index 3e4744b..cc956f9 100644 --- a/examples/accessibleapps/accessibletree.h +++ b/examples/accessibleapps/accessibletree.h @@ -1,95 +1,95 @@ /* * Copyright 2012 Frederik Gladhorn * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef ACCESSIBLETREE_H #define ACCESSIBLETREE_H #include #include class AccessibleTree; class AccessibleWrapper { public: AccessibleWrapper(const QAccessibleClient::AccessibleObject &object, AccessibleWrapper *parent) : acc(object), m_parent(parent) {} QAccessibleClient::AccessibleObject acc; ~AccessibleWrapper() { qDeleteAll(m_children); } int childCount(); AccessibleWrapper *child(int index); AccessibleWrapper *parent(); private: friend class AccessibleTree; AccessibleWrapper *m_parent; QList m_children; }; class AccessibleTree :public QAbstractItemModel { Q_OBJECT public: explicit AccessibleTree(QObject* parent = nullptr); - ~AccessibleTree(); + ~AccessibleTree() override; void setRegistry(QAccessibleClient::Registry *registry); QModelIndex indexForAccessible(const QAccessibleClient::AccessibleObject &object); bool addAccessible(const QAccessibleClient::AccessibleObject &object); bool removeAccessible(const QAccessibleClient::AccessibleObject &object); bool removeAccessible(const QModelIndex &index); void updateAccessible(const QAccessibleClient::AccessibleObject &object); QList apps() const { return m_apps; } - virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; - virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; - virtual QModelIndex parent(const QModelIndex& child) const; - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex& child) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; public Q_SLOTS: void resetModel(); /*! \brief Updates all applications in the tree. Removes and adds top level applications. This is less invasive then modelReset. */ void updateTopLevelApps(); Q_SIGNALS: void navigationError(const QModelIndex &) const; private: QAccessibleClient::Registry *m_registry; QList m_apps; }; #endif // ACCESSIBLETREE_H diff --git a/examples/accessibleapps/eventview.cpp b/examples/accessibleapps/eventview.cpp index 7483679..4773adb 100644 --- a/examples/accessibleapps/eventview.cpp +++ b/examples/accessibleapps/eventview.cpp @@ -1,425 +1,425 @@ /* Copyright 2012 Frederik Gladhorn This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "eventview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include class EventsModel : public QStandardItemModel { public: enum Role { AccessibleRole = 0, RoleRole = 1, EventRole = 2, ActionRole = 3, EventTypeRole = Qt::UserRole, UrlRole, AppNameRole, AppUrlRole }; explicit EventsModel(EventsWidget *view) : QStandardItemModel(view), m_view(view) { clearLog(); } - ~EventsModel() {} + ~EventsModel() override {} - QHash roleNames() const + QHash roleNames() const override { QHash roles; roles[AccessibleRole] = "accessible"; roles[RoleRole] = "role"; roles[EventRole] = "event"; roles[EventTypeRole] = "eventType"; roles[UrlRole] = "url"; roles[AppNameRole] = "appName"; roles[AppUrlRole] = "appUrl"; return roles; } QString roleLabel(Role role) const { switch (role) { case AccessibleRole: return QString("Accessible"); case RoleRole: return QString("Role"); case EventRole: return QString("Event"); case ActionRole: return QString("Action"); case EventTypeRole: case UrlRole: case AppNameRole: case AppUrlRole: break; } return QString(); } void clearLog() { clear(); m_apps.clear(); setColumnCount(4); QStringList headerLabels; Q_FOREACH(Role r, QList() << AccessibleRole << RoleRole << EventRole << ActionRole) headerLabels << roleLabel(r); setHorizontalHeaderLabels(headerLabels); } struct LogItem { QStandardItem *appItem; bool isNewAppItem; LogItem(QStandardItem *appItem, bool isNewAppItem) : appItem(appItem), isNewAppItem(isNewAppItem) {} }; LogItem addLog(QList item) { QString appUrl = item.first()->data(AppUrlRole).toString(); QStandardItem *appItem = nullptr; QMap::ConstIterator it = m_apps.constFind(appUrl); bool isNewAppItem = it == m_apps.constEnd(); if (isNewAppItem) { QString appName = item.first()->data(AppNameRole).toString(); m_apps[appUrl] = appItem = new QStandardItem(appName); appItem->setData(appUrl, EventsModel::AppUrlRole); invisibleRootItem()->appendRow(appItem); } else { appItem = it.value(); } appItem->appendRow(item); return LogItem(appItem, isNewAppItem); } private: EventsWidget *m_view; QMap m_apps; }; class EventsProxyModel : public QSortFilterProxyModel { public: explicit EventsProxyModel(QWidget *parent = nullptr) : QSortFilterProxyModel(parent), m_types(EventsWidget::AllEvents) {} EventsWidget::EventTypes filter() const { return m_types; } QString accessibleFilter() const { return m_accessibleFilter; } QString roleFilter() const { return m_roleFilter; } void setFilter(EventsWidget::EventTypes types) { m_types = types; invalidateFilter(); } void setAccessibleFilter(const QString &filter) { m_accessibleFilter = filter; invalidateFilter(); } void setRoleFilter(const QString &filter) { m_roleFilter = filter; invalidateFilter(); } protected: - virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override { if (!source_parent.isValid()) return true; if (!m_types.testFlag(EventsWidget::AllEvents)) { QModelIndex index = sourceModel()->index(source_row, 0, source_parent); EventsWidget::EventType type = index.data(EventsModel::EventTypeRole).value(); if (!m_types.testFlag(type)) return false; } if (!m_accessibleFilter.isEmpty()) { QModelIndex index = sourceModel()->index(source_row, EventsModel::AccessibleRole, source_parent); QString accessibleName = index.data(Qt::DisplayRole).toString(); if (!accessibleName.contains(m_accessibleFilter, Qt::CaseInsensitive)) return false; } if (!m_roleFilter.isEmpty()) { QModelIndex index = sourceModel()->index(source_row, EventsModel::RoleRole, source_parent); QString roleName = index.data(Qt::DisplayRole).toString(); if (!roleName.contains(m_roleFilter, Qt::CaseInsensitive)) return false; } return true; } private: EventsWidget::EventTypes m_types; QString m_accessibleFilter; QString m_roleFilter; }; using namespace QAccessibleClient; QAccessible::UpdateHandler EventsWidget::m_originalAccessibilityUpdateHandler = nullptr; QObject *EventsWidget::m_textEditForAccessibilityUpdateHandler = nullptr; EventsWidget::EventsWidget(QAccessibleClient::Registry *registry, QWidget *parent) : QWidget(parent), m_registry(registry), m_model(new EventsModel(this)), m_proxyModel(new EventsProxyModel(this)) { m_ui.setupUi(this); m_ui.eventListView->setAccessibleName(QLatin1String("Events View")); m_ui.eventListView->setAccessibleDescription(QString("Displays all received events")); m_proxyModel->setSourceModel(m_model); m_ui.eventListView->setModel(m_proxyModel); connect(m_ui.accessibleFilterEdit, SIGNAL(textChanged(QString)), this, SLOT(accessibleFilterChanged())); connect(m_ui.roleFilterEdit, SIGNAL(textChanged(QString)), this, SLOT(roleFilterChanged())); QStandardItemModel *filerModel = new QStandardItemModel(); QStandardItem *firstFilterItem = new QStandardItem(QString("Event Filter")); firstFilterItem->setFlags(Qt::ItemIsEnabled); filerModel->appendRow(firstFilterItem); QVector< EventType > filterList; filterList << StateChanged << NameChanged << DescriptionChanged << Window << Focus << Document << Object << Text << Table << Others; for(int i = 0; i < filterList.count(); ++i) { EventType t = filterList[i]; QStandardItem* item = new QStandardItem(eventName(t)); item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); item->setData(QVariant::fromValue(t), EventsModel::EventTypeRole); item->setData(Qt::Checked, Qt::CheckStateRole); filerModel->appendRow(QList() << item); } m_ui.filterComboBox->setModel(filerModel); m_ui.clearButton->setFixedWidth(QFontMetrics(m_ui.clearButton->font()).boundingRect(m_ui.clearButton->text()).width() + 4); m_ui.clearButton->setFixedHeight(m_ui.filterComboBox->sizeHint().height()); connect(m_ui.clearButton, SIGNAL(clicked()), this, SLOT(clearLog())); connect(m_ui.filterComboBox->model(), SIGNAL(itemChanged(QStandardItem*)), this, SLOT(checkStateChanged())); connect(m_ui.eventListView, SIGNAL(activated(QModelIndex)), this, SLOT(eventActivated(QModelIndex))); // Collect multiple addLog calls and process them after 500 ms earliest. This // makes sure multiple calls to addLog will be compressed to one only one // view refresh what improves performance. m_pendingTimer.setInterval(500); connect(&m_pendingTimer, SIGNAL(timeout()), this, SLOT(processPending())); m_textEditForAccessibilityUpdateHandler = m_ui.eventListView; checkStateChanged(); // We need to wait for a11y to be active for this hack. QTimer::singleShot(500, this, SLOT(installUpdateHandler())); } void EventsWidget::installUpdateHandler() { m_originalAccessibilityUpdateHandler = QAccessible::installUpdateHandler(customUpdateHandler); if (!m_originalAccessibilityUpdateHandler) QTimer::singleShot(500, this, SLOT(installUpdateHandler())); } #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) void EventsWidget::customUpdateHandler(QAccessibleEvent *event) { QObject *object = event->object(); #else void EventsWidget::customUpdateHandler(QObject *object, int who, QAccessible::Event reason) { #endif if (object == m_textEditForAccessibilityUpdateHandler) return; //if (m_originalAccessibilityUpdateHandler) // m_originalAccessibilityUpdateHandler(object, who, reason); } QString EventsWidget::eventName(EventType eventType) const { QString s; switch (eventType) { case EventsWidget::Focus: s = QLatin1String("Focus"); break; case EventsWidget::StateChanged: s = QLatin1String("State"); break; case EventsWidget::NameChanged: s = QLatin1String("Name"); break; case EventsWidget::DescriptionChanged: s = QLatin1String("Description"); break; case EventsWidget::Window: s = QLatin1String("Window"); break; case EventsWidget::Document: s = QLatin1String("Document"); break; case EventsWidget::Object: s = QLatin1String("Object"); break; case EventsWidget::Text: s = QLatin1String("Text"); break; case EventsWidget::Table: s = QLatin1String("Table"); break; case EventsWidget::Others: s = QLatin1String("Others"); break; } return s; } void EventsWidget::loadSettings(QSettings &settings) { settings.beginGroup("events"); bool eventsFilterOk; EventTypes eventsFilter = EventTypes(settings.value("eventsFilter").toInt(&eventsFilterOk)); if (!eventsFilterOk) eventsFilter = AllEvents; QAbstractItemModel *model = m_ui.filterComboBox->model(); if (eventsFilter != m_proxyModel->filter()) { for (int i = 1; i < model->rowCount(); ++i) { QModelIndex index = model->index(i, 0); EventType type = model->data(index, EventsModel::EventTypeRole).value(); if (eventsFilter.testFlag(type)) model->setData(index, Qt::Checked, Qt::CheckStateRole); else model->setData(index, Qt::Unchecked, Qt::CheckStateRole); } m_proxyModel->setFilter(eventsFilter); } QByteArray eventListViewState = settings.value("listViewHeader").toByteArray(); if (!eventListViewState.isEmpty()) m_ui.eventListView->header()->restoreState(eventListViewState); settings.endGroup(); } void EventsWidget::saveSettings(QSettings &settings) { settings.beginGroup("events"); settings.setValue("eventsFilter", int(m_proxyModel->filter())); QByteArray eventListViewState = m_ui.eventListView->header()->saveState(); settings.setValue("listViewHeader", eventListViewState); settings.endGroup(); } void EventsWidget::clearLog() { m_model->clearLog(); } void EventsWidget::processPending() { m_pendingTimer.stop(); QVector< QList > pendingLogs = m_pendingLogs; m_pendingLogs.clear(); //bool wasMax = true;//m_ui.eventListView->verticalScrollBar()->value() - 10 >= m_ui.eventListView->verticalScrollBar()->maximum(); QStandardItem *lastItem = nullptr; QStandardItem *lastAppItem = nullptr; for(int i = 0; i < pendingLogs.count(); ++i) { QList item = pendingLogs[i]; EventsModel::LogItem logItem = m_model->addLog(item); // Logic to scroll to the last added logItem of the last appItem that is expanded. // For appItem's not expanded the logItem is added but no scrolling will happen. if (lastItem && lastAppItem && lastAppItem != logItem.appItem) lastItem = nullptr; bool selected = lastItem; if (lastAppItem != logItem.appItem) { lastAppItem = logItem.appItem; QModelIndex index = m_proxyModel->mapFromSource(m_model->indexFromItem(logItem.appItem)); if (logItem.isNewAppItem) { m_ui.eventListView->setExpanded(index, true); selected = true; } else { selected = m_ui.eventListView->isExpanded(index); } } if (selected) lastItem = item.first(); } if (lastItem) { // scroll down to the lastItem. //m_ui.eventListView->verticalScrollBar()->setValue(m_ui.eventListView->verticalScrollBar()->maximum()); QModelIndex index = m_proxyModel->mapFromSource(m_model->indexFromItem(lastItem)); m_ui.eventListView->scrollTo(index, QAbstractItemView::PositionAtBottom); //m_ui.eventListView->scrollTo(index, QAbstractItemView::EnsureVisible); } } void EventsWidget::addLog(const QAccessibleClient::AccessibleObject &object, EventsWidget::EventType eventType, const QString &text) { if (!object.isValid()) return; QStandardItem *nameItem = new QStandardItem(object.name()); nameItem->setData(QVariant::fromValue(eventType), EventsModel::EventTypeRole); nameItem->setData(object.url().toString(), EventsModel::UrlRole); AccessibleObject app = object.application(); if (app.isValid()) { nameItem->setData(app.name(), EventsModel::AppNameRole); nameItem->setData(app.url().toString(), EventsModel::AppUrlRole); } QStandardItem *roleItem = new QStandardItem(object.roleName()); QStandardItem *typeItem = new QStandardItem(eventName(eventType)); QStandardItem *textItem = new QStandardItem(text); m_pendingLogs.append(QList() << nameItem << roleItem << typeItem << textItem); if (!m_pendingTimer.isActive()) { m_pendingTimer.start(); } } void EventsWidget::checkStateChanged() { EventTypes types; QStringList names; bool allEvents = true; QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("EventType")); Q_ASSERT(e.isValid()); QAbstractItemModel *model = m_ui.filterComboBox->model(); for (int i = 1; i < model->rowCount(); ++i) { QModelIndex index = model->index(i, 0); bool checked = model->data(index, Qt::CheckStateRole).toBool(); if (checked) { EventType type = model->data(index, EventsModel::EventTypeRole).value(); types |= type; names.append(QString::fromLatin1(e.valueToKey(type))); } else { allEvents = false; } } m_proxyModel->setFilter(types); } void EventsWidget::eventActivated(const QModelIndex &index) { Q_ASSERT(index.isValid()); QModelIndex parent = index.parent(); QModelIndex firstIndex = m_proxyModel->index(index.row(), 0, parent); QString s = m_proxyModel->data(firstIndex, parent.isValid() ? EventsModel::UrlRole : EventsModel::AppUrlRole).toString(); QUrl url(s); if (!url.isValid()) { qWarning() << Q_FUNC_INFO << "Invalid url=" << s; return; } emit anchorClicked(url); } void EventsWidget::accessibleFilterChanged() { m_proxyModel->setAccessibleFilter(m_ui.accessibleFilterEdit->text()); } void EventsWidget::roleFilterChanged() { m_proxyModel->setRoleFilter(m_ui.roleFilterEdit->text()); } diff --git a/examples/accessibleapps/mainwindow.h b/examples/accessibleapps/mainwindow.h index a6e32c4..e67ccd1 100644 --- a/examples/accessibleapps/mainwindow.h +++ b/examples/accessibleapps/mainwindow.h @@ -1,130 +1,130 @@ /* Copyright 2012 Frederik Gladhorn This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include #include #include #include "qaccessibilityclient/accessibleobject.h" #include "qaccessibilityclient/registry.h" #include "clientcachedialog.h" class AccessibleTree; class ObjectProperties; class EventsWidget; class UiView; class MainWindow :public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); - ~MainWindow(); + ~MainWindow() override; protected: - void closeEvent(QCloseEvent *event); + void closeEvent(QCloseEvent *event) override; private Q_SLOTS: void selectionChanged(const QModelIndex ¤t, const QModelIndex &); void treeCustomContextMenuRequested(const QPoint &pos); void anchorClicked(const QUrl &url); void showClientCache(); void copyValue(); void added(const QAccessibleClient::AccessibleObject &object); void removed(const QAccessibleClient::AccessibleObject &object); void defunct(const QAccessibleClient::AccessibleObject &object); void windowCreated(const QAccessibleClient::AccessibleObject &object); void windowDestroyed(const QAccessibleClient::AccessibleObject &object); void windowClosed(const QAccessibleClient::AccessibleObject &object); void windowReparented(const QAccessibleClient::AccessibleObject &object); void windowMinimized(const QAccessibleClient::AccessibleObject &object); void windowMaximized(const QAccessibleClient::AccessibleObject &object); void windowRestored(const QAccessibleClient::AccessibleObject &object); void windowActivated(const QAccessibleClient::AccessibleObject &object); void windowDeactivated(const QAccessibleClient::AccessibleObject &object); void windowDesktopCreated(const QAccessibleClient::AccessibleObject &object); void windowDesktopDestroyed(const QAccessibleClient::AccessibleObject &object); void windowRaised(const QAccessibleClient::AccessibleObject &object); void windowLowered(const QAccessibleClient::AccessibleObject &object); void windowMoved(const QAccessibleClient::AccessibleObject &object); void windowResized(const QAccessibleClient::AccessibleObject &object); void windowShaded(const QAccessibleClient::AccessibleObject &object); void windowUnshaded(const QAccessibleClient::AccessibleObject &object); void stateChanged(const QAccessibleClient::AccessibleObject &object, const QString &state, bool active); void childAdded(const QAccessibleClient::AccessibleObject &object, int childIndex); void childRemoved(const QAccessibleClient::AccessibleObject &object, int childIndex); void visibleDataChanged(const QAccessibleClient::AccessibleObject &object); void selectionChanged(const QAccessibleClient::AccessibleObject &object); void modelChanged(const QAccessibleClient::AccessibleObject &object); void focusChanged(const QAccessibleClient::AccessibleObject &object); void textCaretMoved(const QAccessibleClient::AccessibleObject &object, int pos); void textSelectionChanged(const QAccessibleClient::AccessibleObject &object); void textChanged(const QAccessibleClient::AccessibleObject &object, const QString& text, int startOffset, int endOffset); void textInserted(const QAccessibleClient::AccessibleObject &object, const QString& text, int startOffset, int endOffset); void textRemoved(const QAccessibleClient::AccessibleObject &object, const QString& text, int startOffset, int endOffset); void accessibleNameChanged(const QAccessibleClient::AccessibleObject &object); void accessibleDescriptionChanged(const QAccessibleClient::AccessibleObject &object); private: void initActions(); void initMenu(); void initUi(); void addLog(const QAccessibleClient::AccessibleObject &object, const QString &eventName, const QString &text = QString()); void setCurrentObject(const QAccessibleClient::AccessibleObject &object); void updateDetails(const QAccessibleClient::AccessibleObject &object, bool force = false); QAccessibleClient::Registry *m_registry; QTreeView *m_accessibleObjectTreeView; AccessibleTree *m_accessibleObjectTreeModel; QTreeView *m_propertyView; ObjectProperties *m_propertyModel; EventsWidget *m_eventsWidget; UiView *m_uiview; QAction *m_resetTreeAction; QAction *m_followFocusAction; QAction *m_showClientCacheAction; QAction *m_enableA11yAction; QAction *m_enableScreenReaderAction; QAction *m_quitAction; QAction *m_copyValueAction; }; #endif diff --git a/examples/accessibleapps/uiview.h b/examples/accessibleapps/uiview.h index bd2d877..7679286 100644 --- a/examples/accessibleapps/uiview.h +++ b/examples/accessibleapps/uiview.h @@ -1,73 +1,73 @@ /* Copyright 2012 Sebastian Sauer This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef UIVIEW_H #define UIVIEW_H #include "qaccessibilityclient/accessibleobject.h" #include "qaccessibilityclient/registry.h" #include #include #include #include namespace QAccessibleClient { class AccessibleObject; } class UiView; class UiWidget : public QWidget { public: UiWidget(UiView *view); void setAccessibleObject(const QAccessibleClient::AccessibleObject &acc); - virtual QSize sizeHint() const; + QSize sizeHint() const override; protected: QImage *m_image; QPixmap m_screen; QRect m_bounds; QAccessibleClient::AccessibleObject m_object; QMap m_roleColors; - virtual void paintEvent(QPaintEvent *event); + void paintEvent(QPaintEvent *event) override; private: QPixmap grabScreen() const; QRect bounds(const QAccessibleClient::AccessibleObject &acc) const; void drawObject(QPainter *painter, const QAccessibleClient::AccessibleObject &acc, int depth = 0); }; class UiView :public QScrollArea { Q_OBJECT public: UiView(QWidget *parent = nullptr); - ~UiView(); + ~UiView() override; void setAccessibleObject(const QAccessibleClient::AccessibleObject &acc); private: UiWidget *m_uiWidget; QWidget* createWidget(const QAccessibleClient::AccessibleObject &acc, QRect &bounds); }; #endif diff --git a/src/qaccessibilityclient/cachestrategy_p.h b/src/qaccessibilityclient/cachestrategy_p.h index d4625e4..05e77e6 100644 --- a/src/qaccessibilityclient/cachestrategy_p.h +++ b/src/qaccessibilityclient/cachestrategy_p.h @@ -1,108 +1,108 @@ /* Copyright 2012 Sebastian Sauer This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef QACCESSIBILITYCLIENT_CACHESTRATEGY_P_H #define QACCESSIBILITYCLIENT_CACHESTRATEGY_P_H #include "accessibleobject.h" #include namespace QAccessibleClient { class ObjectCache { public: virtual QStringList ids() const = 0; virtual QSharedPointer get(const QString &id) const = 0; virtual void add(const QString &id, const QSharedPointer &objectPrivate) = 0; virtual bool remove(const QString &id) = 0; virtual void clear() = 0; virtual AccessibleObject::Interfaces interfaces(const AccessibleObject &object) = 0; virtual void setInterfaces(const AccessibleObject &object, AccessibleObject::Interfaces interfaces) = 0; virtual quint64 state(const AccessibleObject &object) = 0; virtual void setState(const AccessibleObject &object, quint64 state) = 0; virtual void cleanState(const AccessibleObject &object) = 0; virtual ~ObjectCache() {} static const quint64 StateNotFound = ~0; }; class CacheWeakStrategy : public ObjectCache { public: - virtual QStringList ids() const + QStringList ids() const override { return accessibleObjectsHash.keys(); } - virtual QSharedPointer get(const QString &id) const + QSharedPointer get(const QString &id) const override { return accessibleObjectsHash[id].first; } - virtual void add(const QString &id, const QSharedPointer &objectPrivate) + void add(const QString &id, const QSharedPointer &objectPrivate) override { accessibleObjectsHash[id] = QPair, AccessibleObjectPrivate*>(objectPrivate, objectPrivate.data()); } - virtual bool remove(const QString &id) + bool remove(const QString &id) override { QPair, AccessibleObjectPrivate*> data = accessibleObjectsHash.take(id); return (interfaceHash.remove(data.second) >= 1) || (stateHash.remove(data.second) >= 1); } - virtual void clear() + void clear() override { accessibleObjectsHash.clear(); stateHash.clear(); interfaceHash.clear(); } - virtual AccessibleObject::Interfaces interfaces(const AccessibleObject &object) + AccessibleObject::Interfaces interfaces(const AccessibleObject &object) override { if (!interfaceHash.contains(object.d.data())) return AccessibleObject::InvalidInterface; return interfaceHash.value(object.d.data()); } - virtual void setInterfaces(const AccessibleObject &object, AccessibleObject::Interfaces interfaces) + void setInterfaces(const AccessibleObject &object, AccessibleObject::Interfaces interfaces) override { interfaceHash.insert(object.d.data(), interfaces); } - virtual quint64 state(const AccessibleObject &object) + quint64 state(const AccessibleObject &object) override { if (!stateHash.contains(object.d.data())) return ObjectCache::StateNotFound; return stateHash.value(object.d.data()); } - virtual void setState(const AccessibleObject &object, quint64 state) + void setState(const AccessibleObject &object, quint64 state) override { stateHash[object.d.data()] = state; } - virtual void cleanState(const AccessibleObject &object) + void cleanState(const AccessibleObject &object) override { stateHash.remove(object.d.data()); } private: QHash, AccessibleObjectPrivate*> > accessibleObjectsHash; QHash interfaceHash; QHash stateHash; }; } #endif diff --git a/src/qaccessibilityclient/registry.h b/src/qaccessibilityclient/registry.h index a0eb2b0..d93657f 100644 --- a/src/qaccessibilityclient/registry.h +++ b/src/qaccessibilityclient/registry.h @@ -1,363 +1,363 @@ /* Copyright 2012 Frederik Gladhorn This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef QACCESSIBILITYCLIENT_REGISTRY_H #define QACCESSIBILITYCLIENT_REGISTRY_H #include #include "qaccessibilityclient_export.h" #include "accessibleobject.h" #include #define accessibleRegistry (QAccessibleClient::Registry::instance()) namespace QAccessibleClient { class RegistryPrivate; class RegistryPrivateCacheApi; /** This class represents the global accessibility registry. It provides information about running applications. All updates of accessible objects will result in signals emitted by this class. */ class QACCESSIBILITYCLIENT_EXPORT Registry : public QObject { Q_OBJECT Q_ENUMS(EventListener) public: /** This enum describes the different types of events that can be observed. */ enum EventListener { NoEventListeners = 0x0, /*!< No event listeners registered or wanted */ Window = 0x1, /*!< Window changes, such as new applications being started */ Focus = 0x2, /*!< Focus listener reacts to focus changes - see signal \sa focusChanged */ //FocusPoint = 0x4, //BoundsChanged = 0x8, //LinkSelected = 0x10, StateChanged = 0x20, /*!< State of the accessible changed - see signal \sa stateChanged */ ChildrenChanged = 0x40, /*!< Children changed - see signal \sa childrenChanged */ VisibleDataChanged = 0x80, /*!< Visibility of the accessible changed - see signal \sa visibleDataChanged */ SelectionChanged = 0x100, /*!< Selection changed - see signal \sa selectionChanged */ ModelChanged = 0x200, /*!< The model changed - see signal \sa modelChanged */ TextCaretMoved = 0x400, /*!< The text caret moved its position - see signal \sa textCaretMoved */ TextChanged = 0x800, /*!< The text changed - see signal \sa textChanged */ TextSelectionChanged = 0x1000, /*!< The text selection changed - see signal \sa textSelectionChanged */ PropertyChanged = 0x2000, /*!< A property changed. See signals \sa accessibleNameChanged and \sa accessibleDescriptionChanged */ //TextBoundsChanged = 0x2000, //TextAttributesChanged = 0x4000, //AttributesChanged = 0x8000, AllEventListeners = 0xffffffff /*!< All possible event listeners */ }; Q_DECLARE_FLAGS(EventListeners, EventListener) /** Construct a Registry object with \a parent as QObject parent. */ explicit Registry(QObject *parent = nullptr); /** Destroys this Registry. */ - virtual ~Registry(); + ~Registry() override; public Q_SLOTS: /** Returns true if the accessibility stack is enabled. This means that an atspi registry daemon is running and available as org.a11y.bus at the session dbus. The org.a11y.bus implments the org.a11y.Status dbus interface that offers the IsEnabled property. The \a isEnabled and \a setEnabled methods do read/write the boolean value of that org.a11y.Status.IsEnabled dbus property.. */ bool isEnabled() const; /** Activates accessibility when \a enabled and tells toolkits to provide updates such as focus changes. */ void setEnabled(bool enable); /** Returns true if the screen reader is enabled. This means that there is potentially a screen reader, if installed, that is enabled or disabled. This allows to enable system wide a screen reader with just one switch. */ bool isScreenReaderEnabled() const; /** Tells the system that a screen reader is \a enabled. */ void setScreenReaderEnabled(bool enable); /** In order to get notified of changes in accessible applications it is neccessary to subscribe to the listeners that are relevant. This will unsubscribe all previously subscribed event listeners. */ void subscribeEventListeners(const EventListeners &listeners) const; /** Returns the active event listeners. */ EventListeners subscribedEventListeners() const; /** List of all currently running applications that expose an accessibility interface. */ QList applications() const; /** Creates the AccessibleObject for the \a url. This can be used to deserialize an AccessibleObject after passing it around as string. The returned QUrl returns a scheme of "accessibleobject". */ AccessibleObject accessibleFromUrl(const QUrl &url) const; Q_SIGNALS: /** Emitted if the \a isEnabled state changed. If the accessibility daemon got enabled or disabled either by us or ny someone else then this signal is emitted. */ void enabledChanged(bool enabled); /** Emitted if the \a isScreenReaderEnabled state changed. If the screen reader enabled property got enabled or disabled either by us or by someone else then this signal is emitted. */ void screenReaderEnabledChanged(bool enabled); /** Emitted if a AccessibleObject is created. This signal indicates that the \a AccessibleObject instance was created and is going to be added/attached. */ void added(const QAccessibleClient::AccessibleObject &object); /** Emitted if a AccessibleObject is destroyed. This signal indicates that the \a AccessibleObject instance was destroyed and ended its life-time. */ void removed(const QAccessibleClient::AccessibleObject &object); /** Emitted if a AccessibleObject is marked defunct. This signal indicates that the \a AccessibleObject became invalid and does not point any longer to any valid accessible object. */ void defunct(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is created void windowCreated(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is destroyed void windowDestroyed(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is closed void windowClosed(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is reparented void windowReparented(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is minimized void windowMinimized(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is maximized void windowMaximized(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is restored to normal size void windowRestored(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is activated void windowActivated(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is deactivated void windowDeactivated(const QAccessibleClient::AccessibleObject &object); /// Emitted when a desktop window is created void windowDesktopCreated(const QAccessibleClient::AccessibleObject &object); /// Emitted when a desktop window is destroyed void windowDesktopDestroyed(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is raised void windowRaised(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is lowered void windowLowered(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is moved void windowMoved(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is resized void windowResized(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is shaded void windowShaded(const QAccessibleClient::AccessibleObject &object); /// Emitted when a window is unshaded void windowUnshaded(const QAccessibleClient::AccessibleObject &object); //void boundsChanged(const QAccessibleClient::AccessibleObject &object); //void linkSelected(const QAccessibleClient::AccessibleObject &object); /** \brief Notifies about a state change in an object. The \a state of \a object has change. If the state is now set \a active is true, otherwise the state was removed. */ void stateChanged(const QAccessibleClient::AccessibleObject &object, const QString &state, bool active); /** \brief Notifies about a new AccessibleObject The childAdded signal is emitted when a new accessible object is created. This signal depends on the implementation of the server side and is not reliable for all applications. The parameter \a childIndex is the index of the child that has been added. \sa AccessibleObject::child(), childRemoved() */ void childAdded(const QAccessibleClient::AccessibleObject &parent, int childIndex); /** \brief Notifies that an AccessibleObject has been removed The parameter \a childIndex is the index of the child that has been removed. \sa AccessibleObject::child(), childAdded() */ void childRemoved(const QAccessibleClient::AccessibleObject &parent, int childIndex); /** \brief Notifies that the \a object's visible data changed. */ void visibleDataChanged(const QAccessibleClient::AccessibleObject &object); /** \brief Notifies that the \a object's selection changed. */ void selectionChanged(const QAccessibleClient::AccessibleObject &object); /** \brief Notifies that the \a object's table model changed. */ void modelChanged(const QAccessibleClient::AccessibleObject &object); /** \brief Emitted when the focus changed. When subscribed to the Focus EventListener then this signal is emitted every time the focus changes. \a object is the newly focused AccessibleObject. */ void focusChanged(const QAccessibleClient::AccessibleObject &object); /** \brief Emitted when the text cared moved. When subscribed to the TextCaretMoved EventListener then this signal is emitted every time the caret in an accessible object that implements a text-interface (like QLineEdit, QTextArea and QComboBox) moved to another position. */ void textCaretMoved(const QAccessibleClient::AccessibleObject &object, int pos); /** \brief Emitted when the text selection changed. When subscribed to the TextSelectionChanged EventListener then this signal is emitted every time the selection in an accessible object that implements a text-interface (like QLineEdit, QTextArea and QComboBox) changed. */ void textSelectionChanged(const QAccessibleClient::AccessibleObject &object); /** \brief Emitted when an accessible name changes When subscribed to the PropertyChanged EventListener, this signal is emitted whenever the accessible-name property changes its value. */ void accessibleNameChanged(const QAccessibleClient::AccessibleObject &object); /** \brief Emitted when an accessible description changes When subscribed to the PropertyChanged EventListener, this signal is emitted whenever the accessible-description property changes its value. */ void accessibleDescriptionChanged(const QAccessibleClient::AccessibleObject &object); /** \brief Emitted when an object's text was changed. The new text will be \a text. The change starts at \a startOffset and goes to \a endOffset. \sa textInserted, textRemoved */ void textChanged(const QAccessibleClient::AccessibleObject &object, const QString& text, int startOffset, int endOffset); /** \brief Emitted when text was inserted in an object's text. The new text will be \a text. The change starts at \a startOffset and goes to \a endOffset. \sa textInserted, textRemoved */ void textInserted(const QAccessibleClient::AccessibleObject &object, const QString& text, int startOffset, int endOffset); /** \brief Emitted when an object's text was removed. The removed text will be \a text, but this string may be emtpy for some implementations. The removal starts at \a startOffset and goes to \a endOffset. \sa textInserted, textRemoved */ void textRemoved(const QAccessibleClient::AccessibleObject &object, const QString& text, int startOffset, int endOffset); //void textBoundsChanged(const QAccessibleClient::AccessibleObject &object); //void textAttributesChanged(const QAccessibleClient::AccessibleObject &object); //void attributesChanged(const QAccessibleClient::AccessibleObject &object); private: Q_DISABLE_COPY(Registry) RegistryPrivate *d; friend class RegistryPrivate; friend class RegistryPrivateCacheApi; enum CacheType { NoCache, WeakCache}; CacheType cacheType() const; void setCacheType(CacheType type); AccessibleObject clientCacheObject(const QString &id) const; QStringList clientCacheObjects() const; void clearClientCache(); }; Q_DECLARE_OPERATORS_FOR_FLAGS(Registry::EventListeners) } #endif