implemented accessible tree
This commit is contained in:
parent
73b50d98ca
commit
b30a63ff38
15 changed files with 306 additions and 257 deletions
|
@ -32,8 +32,6 @@ set(MODULE_SRC
|
|||
${CMAKE_CURRENT_LIST_DIR}/internal/accessibilitycontroller.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/accessibleobject.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/accessibleobject.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/accessiblecontrollerinterface.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/accessiblecontrollerinterface.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/accessibleiteminterface.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/accessibleiteminterface.h
|
||||
)
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#define MU_ACCESSIBILITY_IACCESSIBILITY_H
|
||||
|
||||
#include <QString>
|
||||
#include "async/notification.h"
|
||||
|
||||
namespace mu::accessibility {
|
||||
class IAccessibility
|
||||
|
@ -30,6 +31,7 @@ class IAccessibility
|
|||
public:
|
||||
enum class Role {
|
||||
NoRole = 0,
|
||||
Application,
|
||||
Panel,
|
||||
Button
|
||||
};
|
||||
|
@ -41,6 +43,11 @@ public:
|
|||
Focused
|
||||
};
|
||||
|
||||
virtual const IAccessibility* accessibleParent() const = 0;
|
||||
virtual async::Notification accessibleParentChanged() const = 0;
|
||||
virtual size_t accessibleChildCount() const = 0;
|
||||
virtual const IAccessibility* accessibleChild(size_t i) const = 0;
|
||||
|
||||
virtual Role accessibleRole() const = 0;
|
||||
virtual QString accessibleName() const = 0;
|
||||
virtual bool accessibleState(State st) const = 0;
|
||||
|
|
|
@ -33,8 +33,11 @@ class IAccessibilityController : MODULE_EXPORT_INTERFACE
|
|||
public:
|
||||
virtual ~IAccessibilityController() = default;
|
||||
|
||||
virtual void created(IAccessibility* parent, IAccessibility* item) = 0;
|
||||
virtual void destroyed(IAccessibility* item) = 0;
|
||||
virtual const IAccessibility* rootItem() const = 0;
|
||||
|
||||
virtual void reg(IAccessibility* item) = 0;
|
||||
virtual void unreg(IAccessibility* item) = 0;
|
||||
|
||||
virtual void actived(IAccessibility* item, bool isActive) = 0;
|
||||
virtual void focused(IAccessibility* item) = 0;
|
||||
};
|
||||
|
|
|
@ -25,26 +25,34 @@
|
|||
#include <QAccessible>
|
||||
|
||||
#include "accessibleobject.h"
|
||||
#include "accessiblecontrollerinterface.h"
|
||||
#include "accessibleiteminterface.h"
|
||||
|
||||
#include "async/async.h"
|
||||
#include "log.h"
|
||||
|
||||
#define ACCESSIBILITY_LOGGING_ENABLED
|
||||
|
||||
#ifdef ACCESSIBILITY_LOGGING_ENABLED
|
||||
#define MYLOG() LOGI()
|
||||
#else
|
||||
#define MYLOG() LOGN()
|
||||
#endif
|
||||
|
||||
using namespace mu::accessibility;
|
||||
|
||||
AccessibilityController::~AccessibilityController()
|
||||
{
|
||||
unreg(this);
|
||||
}
|
||||
|
||||
static QAccessibleInterface* muAccessibleFactory(const QString& classname, QObject* object)
|
||||
{
|
||||
if (classname == QLatin1String("mu::accessibility::AccessibleObject")) {
|
||||
return static_cast<QAccessibleInterface*>(new AccessibleItemInterface(object));
|
||||
}
|
||||
|
||||
if (classname == QLatin1String("mu::accessibility::AccessibilityController")) {
|
||||
return static_cast<QAccessibleInterface*>(new AccessibleControllerInterface(object));
|
||||
AccessibleObject* aobj = qobject_cast<AccessibleObject*>(object);
|
||||
IF_ASSERT_FAILED(aobj) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<QAccessibleInterface*>(new AccessibleItemInterface(aobj));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -54,54 +62,75 @@ static void updateHandlerNoop(QAccessibleEvent*)
|
|||
{
|
||||
}
|
||||
|
||||
static void rootObjectHandlerNoop(QObject*)
|
||||
{
|
||||
}
|
||||
|
||||
void AccessibilityController::init()
|
||||
{
|
||||
setObjectName("AccessibilityController");
|
||||
|
||||
QAccessible::installFactory(muAccessibleFactory);
|
||||
|
||||
QAccessible::setRootObject(this);
|
||||
QAccessible::installRootObjectHandler([](QObject*) {});
|
||||
reg(this);
|
||||
const Item& self = findItem(this);
|
||||
|
||||
QAccessible::installRootObjectHandler(nullptr);
|
||||
QAccessible::setRootObject(self.object);
|
||||
|
||||
//! NOTE Disabled any events from Qt
|
||||
QAccessible::installRootObjectHandler(rootObjectHandlerNoop);
|
||||
QAccessible::installUpdateHandler(updateHandlerNoop);
|
||||
}
|
||||
|
||||
void AccessibilityController::created(IAccessibility* parent, IAccessibility* item)
|
||||
const IAccessibility* AccessibilityController::rootItem() const
|
||||
{
|
||||
//! TODO Not working yet
|
||||
parent = nullptr;
|
||||
return this;
|
||||
}
|
||||
|
||||
QObject* prnObj = nullptr;
|
||||
if (parent) {
|
||||
prnObj = findItem(parent).object;
|
||||
} else {
|
||||
prnObj = this;
|
||||
void AccessibilityController::reg(IAccessibility* item)
|
||||
{
|
||||
if (findItem(item).isValid()) {
|
||||
LOGW() << "Already registered";
|
||||
return;
|
||||
}
|
||||
|
||||
MYLOG() << "item: " << item->accessibleName();
|
||||
|
||||
Item it;
|
||||
it.parent = parent;
|
||||
it.item = item;
|
||||
it.object = new AccessibleObject(item, prnObj);
|
||||
it.object = new AccessibleObject(item);
|
||||
it.object->setController(shared_from_this());
|
||||
it.iface = QAccessible::queryAccessibleInterface(it.object);
|
||||
|
||||
m_items.append(it);
|
||||
m_allItems.insert(item, it);
|
||||
|
||||
LOGI() << "parent: " << (parent ? parent->accessibleName() : "") << ", item: " << item->accessibleName();
|
||||
if (item->accessibleParent() == this) {
|
||||
m_children.append(item);
|
||||
}
|
||||
|
||||
item->accessibleParentChanged().onNotify(this, [this, item]() {
|
||||
const Item& it = findItem(item);
|
||||
if (!it.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QAccessibleEvent ev(it.object, QAccessible::ParentChanged);
|
||||
sendEvent(&ev);
|
||||
});
|
||||
|
||||
QAccessibleEvent ev(it.object, QAccessible::ObjectCreated);
|
||||
sendEvent(&ev);
|
||||
}
|
||||
|
||||
void AccessibilityController::destroyed(IAccessibility* aitem)
|
||||
void AccessibilityController::unreg(IAccessibility* aitem)
|
||||
{
|
||||
LOGI() << aitem->accessibleName();
|
||||
int idx = indexBy(aitem);
|
||||
IF_ASSERT_FAILED(idx >= 0) {
|
||||
return;
|
||||
MYLOG() << aitem->accessibleName();
|
||||
|
||||
Item item = m_allItems.take(aitem);
|
||||
|
||||
if (aitem->accessibleParent() == this) {
|
||||
m_children.removeOne(aitem);
|
||||
}
|
||||
Item item = m_items.takeAt(idx);
|
||||
|
||||
QAccessibleEvent ev(item.object, QAccessible::ObjectDestroyed);
|
||||
sendEvent(&ev);
|
||||
|
||||
|
@ -110,7 +139,7 @@ void AccessibilityController::destroyed(IAccessibility* aitem)
|
|||
|
||||
void AccessibilityController::actived(IAccessibility* aitem, bool isActive)
|
||||
{
|
||||
LOGI() << aitem->accessibleName() << " " << isActive;
|
||||
MYLOG() << aitem->accessibleName() << " " << isActive;
|
||||
const Item& item = findItem(aitem);
|
||||
IF_ASSERT_FAILED(item.isValid()) {
|
||||
return;
|
||||
|
@ -124,7 +153,7 @@ void AccessibilityController::actived(IAccessibility* aitem, bool isActive)
|
|||
|
||||
void AccessibilityController::focused(IAccessibility* aitem)
|
||||
{
|
||||
LOGI() << aitem->accessibleName();
|
||||
MYLOG() << aitem->accessibleName();
|
||||
const Item& item = findItem(aitem);
|
||||
IF_ASSERT_FAILED(item.isValid()) {
|
||||
return;
|
||||
|
@ -142,64 +171,127 @@ void AccessibilityController::sendEvent(QAccessibleEvent* ev)
|
|||
QAccessible::installUpdateHandler(updateHandlerNoop);
|
||||
}
|
||||
|
||||
const AccessibilityController::Item& AccessibilityController::findItem(IAccessibility* aitem) const
|
||||
const AccessibilityController::Item& AccessibilityController::findItem(const IAccessibility* aitem) const
|
||||
{
|
||||
for (int i = 0; i < m_items.count(); ++i) {
|
||||
if (m_items.at(i).item == aitem) {
|
||||
return m_items.at(i);
|
||||
}
|
||||
auto it = m_allItems.find(aitem);
|
||||
if (it != m_allItems.end()) {
|
||||
return it.value();
|
||||
}
|
||||
|
||||
static AccessibilityController::Item null;
|
||||
return null;
|
||||
}
|
||||
|
||||
int AccessibilityController::indexBy(IAccessibility* aitem) const
|
||||
QAccessibleInterface* AccessibilityController::parentIface(const IAccessibility* item) const
|
||||
{
|
||||
for (int i = 0; i < m_items.count(); ++i) {
|
||||
if (m_items.at(i).item == aitem) {
|
||||
return i;
|
||||
IF_ASSERT_FAILED(item) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const IAccessibility* parent = item->accessibleParent();
|
||||
if (!parent) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Item& it = findItem(parent);
|
||||
if (!it.isValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
return it.iface;
|
||||
}
|
||||
|
||||
int AccessibilityController::childCount(const IAccessibility* item) const
|
||||
{
|
||||
IF_ASSERT_FAILED(item) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Item& it = findItem(item);
|
||||
IF_ASSERT_FAILED(it.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return it.item->accessibleChildCount();
|
||||
}
|
||||
|
||||
QAccessibleInterface* AccessibilityController::child(const IAccessibility* item, int i) const
|
||||
{
|
||||
IF_ASSERT_FAILED(item) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const IAccessibility* chld = item->accessibleChild(static_cast<size_t>(i));
|
||||
IF_ASSERT_FAILED(chld) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Item& chldIt = findItem(chld);
|
||||
IF_ASSERT_FAILED(chldIt.isValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return chldIt.iface;
|
||||
}
|
||||
|
||||
int AccessibilityController::indexOfChild(const IAccessibility* item, const QAccessibleInterface* iface) const
|
||||
{
|
||||
TRACEFUNC;
|
||||
size_t count = item->accessibleChildCount();
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
const IAccessibility* ch = item->accessibleChild(i);
|
||||
const Item& chIt = findItem(ch);
|
||||
IF_ASSERT_FAILED(chIt.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chIt.iface == iface) {
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int AccessibilityController::childCount(const IAccessibility* aitem) const
|
||||
IAccessibility* AccessibilityController::accessibleParent() const
|
||||
{
|
||||
int count = 0;
|
||||
for (const Item& item: m_items) {
|
||||
if (item.parent == aitem) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
QAccessibleInterface* AccessibilityController::child(const IAccessibility* aitem, int i) const
|
||||
{
|
||||
int idx = -1;
|
||||
for (const Item& item: m_items) {
|
||||
if (item.parent == aitem) {
|
||||
++idx;
|
||||
if (idx == i) {
|
||||
return item.iface;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int AccessibilityController::indexOfChild(const IAccessibility* aitem, const QAccessibleInterface* iface) const
|
||||
mu::async::Notification AccessibilityController::accessibleParentChanged() const
|
||||
{
|
||||
int idx = -1;
|
||||
for (const Item& item: m_items) {
|
||||
if (item.parent == aitem) {
|
||||
++idx;
|
||||
if (item.iface == iface) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
static mu::async::Notification notification;
|
||||
return notification;
|
||||
}
|
||||
|
||||
size_t AccessibilityController::accessibleChildCount() const
|
||||
{
|
||||
return static_cast<size_t>(m_children.size());
|
||||
}
|
||||
|
||||
IAccessibility* AccessibilityController::accessibleChild(size_t i) const
|
||||
{
|
||||
return m_children.at(static_cast<int>(i));
|
||||
}
|
||||
|
||||
IAccessibility::Role AccessibilityController::accessibleRole() const
|
||||
{
|
||||
return IAccessibility::Role::Application;
|
||||
}
|
||||
|
||||
QString AccessibilityController::accessibleName() const
|
||||
{
|
||||
return QString("AccessibilityController");
|
||||
}
|
||||
|
||||
bool AccessibilityController::accessibleState(State st) const
|
||||
{
|
||||
switch (st) {
|
||||
case State::Undefined: return false;
|
||||
case State::Disabled: return false;
|
||||
case State::Active: return true;
|
||||
default: {
|
||||
LOGW() << "not handled state: " << static_cast<int>(st);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -25,29 +25,48 @@
|
|||
#include <memory>
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QHash>
|
||||
|
||||
#include "../iaccessibilitycontroller.h"
|
||||
#include "accessibleobject.h"
|
||||
#include "async/asyncable.h"
|
||||
|
||||
class QAccessibleInterface;
|
||||
class QAccessibleEvent;
|
||||
|
||||
namespace mu::accessibility {
|
||||
class AccessibilityController : public QObject, public IAccessibilityController,
|
||||
class AccessibilityController : public IAccessibilityController, public IAccessibility, public async::Asyncable,
|
||||
public std::enable_shared_from_this<AccessibilityController>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AccessibilityController() = default;
|
||||
~AccessibilityController();
|
||||
|
||||
void init();
|
||||
|
||||
void created(IAccessibility* parent, IAccessibility* item) override;
|
||||
void destroyed(IAccessibility* item) override;
|
||||
// IAccessibilityController
|
||||
const IAccessibility* rootItem() const override;
|
||||
|
||||
void reg(IAccessibility* item) override;
|
||||
void unreg(IAccessibility* item) override;
|
||||
|
||||
void actived(IAccessibility* item, bool isActive) override;
|
||||
void focused(IAccessibility* item) override;
|
||||
// -----
|
||||
|
||||
// IAccessibility
|
||||
IAccessibility* accessibleParent() const override;
|
||||
async::Notification accessibleParentChanged() const override;
|
||||
|
||||
size_t accessibleChildCount() const override;
|
||||
IAccessibility* accessibleChild(size_t i) const override;
|
||||
|
||||
Role accessibleRole() const override;
|
||||
QString accessibleName() const override;
|
||||
bool accessibleState(State st) const override;
|
||||
// -----
|
||||
|
||||
QAccessibleInterface* parentIface(const IAccessibility* item) const;
|
||||
int childCount(const IAccessibility* item) const;
|
||||
QAccessibleInterface* child(const IAccessibility* item, int i) const;
|
||||
int indexOfChild(const IAccessibility* item, const QAccessibleInterface* iface) const;
|
||||
|
@ -56,7 +75,6 @@ private:
|
|||
|
||||
struct Item
|
||||
{
|
||||
IAccessibility* parent = nullptr;
|
||||
IAccessibility* item = nullptr;
|
||||
AccessibleObject* object = nullptr;
|
||||
QAccessibleInterface* iface = nullptr;
|
||||
|
@ -64,12 +82,13 @@ private:
|
|||
bool isValid() const { return item != nullptr; }
|
||||
};
|
||||
|
||||
const Item& findItem(IAccessibility* aitem) const;
|
||||
int indexBy(IAccessibility* aitem) const;
|
||||
const Item& findItem(const IAccessibility* aitem) const;
|
||||
|
||||
void sendEvent(QAccessibleEvent* ev);
|
||||
|
||||
QList<Item> m_items;
|
||||
QHash<const IAccessibility*, Item> m_allItems;
|
||||
|
||||
QList<IAccessibility*> m_children;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
* MuseScore-CLA-applies
|
||||
*
|
||||
* MuseScore
|
||||
* Music Composition & Notation
|
||||
*
|
||||
* Copyright (C) 2021 MuseScore BVBA and others
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "accessiblecontrollerinterface.h"
|
||||
|
||||
#include "accessibilitycontroller.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
using namespace mu::accessibility;
|
||||
|
||||
AccessibleControllerInterface::AccessibleControllerInterface(QObject* o)
|
||||
{
|
||||
m_controller = qobject_cast<AccessibilityController*>(o);
|
||||
}
|
||||
|
||||
bool AccessibleControllerInterface::isValid() const
|
||||
{
|
||||
return m_controller != nullptr;
|
||||
}
|
||||
|
||||
QObject* AccessibleControllerInterface::object() const
|
||||
{
|
||||
return m_controller;
|
||||
}
|
||||
|
||||
QWindow* AccessibleControllerInterface::window() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QRect AccessibleControllerInterface::rect() const
|
||||
{
|
||||
return QRect();
|
||||
}
|
||||
|
||||
QAccessibleInterface* AccessibleControllerInterface::parent() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int AccessibleControllerInterface::childCount() const
|
||||
{
|
||||
return m_controller->childCount(nullptr);
|
||||
}
|
||||
|
||||
QAccessibleInterface* AccessibleControllerInterface::child(int i) const
|
||||
{
|
||||
return m_controller->child(nullptr, i);
|
||||
}
|
||||
|
||||
QAccessibleInterface* AccessibleControllerInterface::childAt(int, int) const
|
||||
{
|
||||
NOT_IMPLEMENTED;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int AccessibleControllerInterface::indexOfChild(const QAccessibleInterface* iface) const
|
||||
{
|
||||
return m_controller->indexOfChild(nullptr, iface);
|
||||
}
|
||||
|
||||
QAccessible::Role AccessibleControllerInterface::role() const
|
||||
{
|
||||
return QAccessible::Application;
|
||||
}
|
||||
|
||||
QAccessible::State AccessibleControllerInterface::state() const
|
||||
{
|
||||
QAccessible::State state;
|
||||
state.active = 1;
|
||||
return state;
|
||||
}
|
||||
|
||||
QString AccessibleControllerInterface::text(QAccessible::Text) const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
void AccessibleControllerInterface::setText(QAccessible::Text, const QString&)
|
||||
{
|
||||
NOT_IMPLEMENTED;
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
* MuseScore-CLA-applies
|
||||
*
|
||||
* MuseScore
|
||||
* Music Composition & Notation
|
||||
*
|
||||
* Copyright (C) 2021 MuseScore BVBA and others
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLERACCESSIBLEINTERFACE_H
|
||||
#define CONTROLLERACCESSIBLEINTERFACE_H
|
||||
|
||||
#include <QAccessibleInterface>
|
||||
|
||||
namespace mu::accessibility {
|
||||
class AccessibilityController;
|
||||
class AccessibleControllerInterface : public QAccessibleInterface
|
||||
{
|
||||
public:
|
||||
AccessibleControllerInterface(QObject* o);
|
||||
|
||||
bool isValid() const override;
|
||||
QObject* object() const override;
|
||||
QWindow* window() const override;
|
||||
QRect rect() const override;
|
||||
|
||||
QAccessibleInterface* parent() const override;
|
||||
int childCount() const override;
|
||||
QAccessibleInterface* child(int i) const override;
|
||||
QAccessibleInterface* childAt(int x, int y) const override;
|
||||
int indexOfChild(const QAccessibleInterface* iface) const override;
|
||||
|
||||
QAccessible::Role role() const override;
|
||||
QAccessible::State state() const override;
|
||||
|
||||
QString text(QAccessible::Text) const override;
|
||||
void setText(QAccessible::Text t, const QString& text) override;
|
||||
|
||||
private:
|
||||
|
||||
AccessibilityController* m_controller = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CONTROLLERACCESSIBLEINTERFACE_H
|
|
@ -29,9 +29,9 @@
|
|||
|
||||
using namespace mu::accessibility;
|
||||
|
||||
AccessibleItemInterface::AccessibleItemInterface(QObject* object)
|
||||
AccessibleItemInterface::AccessibleItemInterface(AccessibleObject* object)
|
||||
{
|
||||
m_object = qobject_cast<AccessibleObject*>(object);
|
||||
m_object = object;
|
||||
}
|
||||
|
||||
bool AccessibleItemInterface::isValid() const
|
||||
|
@ -58,22 +58,30 @@ QRect AccessibleItemInterface::rect() const
|
|||
|
||||
QAccessibleInterface* AccessibleItemInterface::parent() const
|
||||
{
|
||||
return QAccessible::queryAccessibleInterface(m_object->parent());
|
||||
QAccessibleInterface* iface = m_object->controller()->parentIface(m_object->item());
|
||||
LOGI() << "item: " << m_object->item()->accessibleName() << ", parent: " << (iface ? iface->text(QAccessible::Name) : "null");
|
||||
return iface;
|
||||
}
|
||||
|
||||
int AccessibleItemInterface::childCount() const
|
||||
{
|
||||
return m_object->controller()->childCount(m_object->item());
|
||||
int count = m_object->controller()->childCount(m_object->item());
|
||||
LOGI() << "item: " << m_object->item()->accessibleName() << ", childCount: " << count;
|
||||
return count;
|
||||
}
|
||||
|
||||
QAccessibleInterface* AccessibleItemInterface::child(int index) const
|
||||
{
|
||||
return m_object->controller()->child(m_object->item(), index);
|
||||
QAccessibleInterface* iface = m_object->controller()->child(m_object->item(), index);
|
||||
LOGI() << "item: " << m_object->item()->accessibleName() << ", child: " << index << " " << iface->text(QAccessible::Name);
|
||||
return iface;
|
||||
}
|
||||
|
||||
int AccessibleItemInterface::indexOfChild(const QAccessibleInterface* iface) const
|
||||
{
|
||||
return m_object->controller()->indexOfChild(m_object->item(), iface);
|
||||
int idx = m_object->controller()->indexOfChild(m_object->item(), iface);
|
||||
LOGI() << "item: " << m_object->item()->accessibleName() << ", indexOfChild: " << iface->text(QAccessible::Name) << " = " << idx;
|
||||
return idx;
|
||||
}
|
||||
|
||||
QAccessibleInterface* AccessibleItemInterface::childAt(int, int) const
|
||||
|
@ -99,6 +107,9 @@ QAccessible::State AccessibleItemInterface::state() const
|
|||
IAccessibility::Role r = m_object->item()->accessibleRole();
|
||||
switch (r) {
|
||||
case IAccessibility::Role::NoRole: break;
|
||||
case IAccessibility::Role::Application: {
|
||||
state.active = item->accessibleState(IAccessibility::State::Active);
|
||||
} break;
|
||||
case IAccessibility::Role::Panel: {
|
||||
state.active = item->accessibleState(IAccessibility::State::Active);
|
||||
} break;
|
||||
|
@ -116,6 +127,7 @@ QAccessible::Role AccessibleItemInterface::role() const
|
|||
IAccessibility::Role r = m_object->item()->accessibleRole();
|
||||
switch (r) {
|
||||
case IAccessibility::Role::NoRole: return QAccessible::NoRole;
|
||||
case IAccessibility::Role::Application: return QAccessible::Application;
|
||||
case IAccessibility::Role::Panel: return QAccessible::Pane;
|
||||
case IAccessibility::Role::Button: return QAccessible::Button;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ class AccessibleItemInterface : public QAccessibleInterface
|
|||
INJECT(accessibility, ui::IMainWindow, mainWindow)
|
||||
|
||||
public:
|
||||
AccessibleItemInterface(QObject* object);
|
||||
AccessibleItemInterface(AccessibleObject* object);
|
||||
|
||||
bool isValid() const override;
|
||||
QObject* object() const override;
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
using namespace mu::accessibility;
|
||||
|
||||
AccessibleObject::AccessibleObject(IAccessibility* item, QObject* parent)
|
||||
: QObject(parent)
|
||||
AccessibleObject::AccessibleObject(IAccessibility* item)
|
||||
: QObject()
|
||||
{
|
||||
setObjectName("AccessibleObject");
|
||||
m_item = item;
|
||||
|
|
|
@ -31,7 +31,7 @@ class AccessibleObject : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AccessibleObject(IAccessibility* item, QObject* parent);
|
||||
explicit AccessibleObject(IAccessibility* item);
|
||||
|
||||
void setController(std::shared_ptr<AccessibilityController> controller);
|
||||
const std::shared_ptr<AccessibilityController>& controller() const;
|
||||
|
|
|
@ -34,16 +34,16 @@ NavigationControl::NavigationControl(QObject* parent)
|
|||
|
||||
NavigationControl::~NavigationControl()
|
||||
{
|
||||
accessibilityController()->unreg(this);
|
||||
if (m_panel) {
|
||||
m_panel->removeControl(this);
|
||||
}
|
||||
accessibilityController()->destroyed(this);
|
||||
}
|
||||
|
||||
void NavigationControl::componentComplete()
|
||||
{
|
||||
AbstractNavigation::componentComplete();
|
||||
accessibilityController()->created(m_panel, this);
|
||||
accessibilityController()->reg(this);
|
||||
}
|
||||
|
||||
QString NavigationControl::name() const
|
||||
|
@ -129,6 +129,7 @@ void NavigationControl::setPanel(NavigationPanel* panel)
|
|||
}
|
||||
|
||||
emit panelChanged(m_panel);
|
||||
m_accessibleParentChanged.notify();
|
||||
}
|
||||
|
||||
void NavigationControl::onPanelDestroyed()
|
||||
|
@ -146,6 +147,26 @@ INavigationPanel* NavigationControl::panel() const
|
|||
return m_panel;
|
||||
}
|
||||
|
||||
const IAccessibility* NavigationControl::accessibleParent() const
|
||||
{
|
||||
return m_panel;
|
||||
}
|
||||
|
||||
mu::async::Notification NavigationControl::accessibleParentChanged() const
|
||||
{
|
||||
return m_accessibleParentChanged;
|
||||
}
|
||||
|
||||
size_t NavigationControl::accessibleChildCount() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const IAccessibility* NavigationControl::accessibleChild(size_t) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IAccessibility::Role NavigationControl::accessibleRole() const
|
||||
{
|
||||
return IAccessibility::Role::Button;
|
||||
|
|
|
@ -69,9 +69,16 @@ public:
|
|||
void componentComplete() override;
|
||||
|
||||
// IAccessibility
|
||||
const IAccessibility* accessibleParent() const override;
|
||||
async::Notification accessibleParentChanged() const override;
|
||||
|
||||
size_t accessibleChildCount() const override;
|
||||
const IAccessibility* accessibleChild(size_t i) const override;
|
||||
|
||||
IAccessibility::Role accessibleRole() const override;
|
||||
QString accessibleName() const override;
|
||||
bool accessibleState(State st) const override;
|
||||
// -----
|
||||
|
||||
public slots:
|
||||
void setPanel(NavigationPanel* panel);
|
||||
|
@ -87,6 +94,8 @@ private:
|
|||
|
||||
NavigationPanel* m_panel = nullptr;
|
||||
async::Channel<INavigationControl*> m_forceActiveRequested;
|
||||
|
||||
async::Notification m_accessibleParentChanged;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -36,11 +36,10 @@ NavigationPanel::NavigationPanel(QObject* parent)
|
|||
|
||||
NavigationPanel::~NavigationPanel()
|
||||
{
|
||||
accessibilityController()->unreg(this);
|
||||
if (m_section) {
|
||||
m_section->removePanel(this);
|
||||
}
|
||||
|
||||
accessibilityController()->destroyed(this);
|
||||
}
|
||||
|
||||
QString NavigationPanel::name() const
|
||||
|
@ -179,7 +178,7 @@ void NavigationPanel::onSectionDestroyed()
|
|||
|
||||
void NavigationPanel::componentComplete()
|
||||
{
|
||||
accessibilityController()->created(nullptr, this);
|
||||
accessibilityController()->reg(this);
|
||||
}
|
||||
|
||||
void NavigationPanel::addControl(NavigationControl* control)
|
||||
|
@ -198,6 +197,9 @@ void NavigationPanel::addControl(NavigationControl* control)
|
|||
if (m_controlsListChanged.isConnected()) {
|
||||
m_controlsListChanged.notify();
|
||||
}
|
||||
|
||||
//! TODO Maybe need sorting
|
||||
m_accessibleControls.push_back(control);
|
||||
}
|
||||
|
||||
void NavigationPanel::removeControl(NavigationControl* control)
|
||||
|
@ -213,6 +215,32 @@ void NavigationPanel::removeControl(NavigationControl* control)
|
|||
if (m_controlsListChanged.isConnected()) {
|
||||
m_controlsListChanged.notify();
|
||||
}
|
||||
|
||||
m_accessibleControls.erase(std::remove(m_accessibleControls.begin(), m_accessibleControls.end(), control), m_accessibleControls.end());
|
||||
}
|
||||
|
||||
const IAccessibility* NavigationPanel::accessibleParent() const
|
||||
{
|
||||
return accessibilityController()->rootItem();
|
||||
}
|
||||
|
||||
mu::async::Notification NavigationPanel::accessibleParentChanged() const
|
||||
{
|
||||
static async::Notification notification;
|
||||
return notification;
|
||||
}
|
||||
|
||||
size_t NavigationPanel::accessibleChildCount() const
|
||||
{
|
||||
return m_accessibleControls.size();
|
||||
}
|
||||
|
||||
const IAccessibility* NavigationPanel::accessibleChild(size_t i) const
|
||||
{
|
||||
IF_ASSERT_FAILED(i < m_accessibleControls.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_accessibleControls.at(i);
|
||||
}
|
||||
|
||||
IAccessibility::Role NavigationPanel::accessibleRole() const
|
||||
|
@ -222,7 +250,17 @@ IAccessibility::Role NavigationPanel::accessibleRole() const
|
|||
|
||||
QString NavigationPanel::accessibleName() const
|
||||
{
|
||||
return name();
|
||||
QString dirc;
|
||||
switch (m_direction) {
|
||||
case Horizontal: dirc = "Horizontal";
|
||||
break;
|
||||
case Vertical: dirc = "Vertical";
|
||||
break;
|
||||
case Both: dirc = "Both";
|
||||
break;
|
||||
}
|
||||
|
||||
return name() + " direction " + dirc;
|
||||
}
|
||||
|
||||
bool NavigationPanel::accessibleState(State st) const
|
||||
|
|
|
@ -86,9 +86,16 @@ public:
|
|||
void removeControl(NavigationControl* control);
|
||||
|
||||
// IAccessibility
|
||||
const IAccessibility* accessibleParent() const override;
|
||||
async::Notification accessibleParentChanged() const override;
|
||||
|
||||
size_t accessibleChildCount() const override;
|
||||
const IAccessibility* accessibleChild(size_t i) const override;
|
||||
|
||||
Role accessibleRole() const override;
|
||||
QString accessibleName() const override;
|
||||
bool accessibleState(State st) const override;
|
||||
// -----
|
||||
|
||||
public slots:
|
||||
void setSection_property(NavigationSection* section);
|
||||
|
@ -108,6 +115,8 @@ private:
|
|||
async::Notification m_controlsListChanged;
|
||||
async::Channel<PanelControl> m_forceActiveRequested;
|
||||
QmlDirection m_direction = QmlDirection::Horizontal;
|
||||
|
||||
std::vector<NavigationControl*> m_accessibleControls;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue