From b2ec0da95641d9cec006fa9699e6d082ad35db0b Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 3 Jan 2013 17:18:40 +0100 Subject: Cache QAccessibleInterfaces. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since there already is a one-to-one relationship between QObject and QAccessibleInterface it makes little sense to create and destroy the interfaces on each call to queryAccessibleInterface. Add a cache and keep created interfaces around for the lifetime of the corresponding QObject. This changes the memory management rules: accessible interfaces must no longer be deleted. If you get an QAccessibleIntrface pointer that pointer will stay valid as long as the corresponding QObject is not deleted. This also re-enables accessibility for Mac. We limit the range of the IDs so that they are useable for Windows directly. That means we can get rid of the event cache there. This is based on: Iebf2f374916fc70a9dd29e95f45a6444b85f6cee Change-Id: I9fe6531812c0dbc5b41101ac05830a6dd75e13a3 Reviewed-by: Morten Johan Sørvig --- src/plugins/accessible/widgets/complexwidgets.cpp | 12 +- src/plugins/accessible/widgets/complexwidgets.h | 3 + src/plugins/accessible/widgets/itemviews.cpp | 309 +++++++++++++++------ src/plugins/accessible/widgets/itemviews.h | 23 +- src/plugins/accessible/widgets/main.cpp | 8 - src/plugins/accessible/widgets/qaccessiblemenu.cpp | 24 +- .../accessible/widgets/qaccessiblewidgets.cpp | 1 - 7 files changed, 269 insertions(+), 111 deletions(-) (limited to 'src/plugins/accessible') diff --git a/src/plugins/accessible/widgets/complexwidgets.cpp b/src/plugins/accessible/widgets/complexwidgets.cpp index b805e8c967..9dbf7d7e0f 100644 --- a/src/plugins/accessible/widgets/complexwidgets.cpp +++ b/src/plugins/accessible/widgets/complexwidgets.cpp @@ -96,7 +96,6 @@ public: QAccessible::State state() const { QAccessibleInterface *parentInterface = parent(); QAccessible::State state = parentInterface->state(); - delete parentInterface; return state; } QRect rect() const { @@ -153,6 +152,12 @@ QAccessibleTabBar::QAccessibleTabBar(QWidget *w) Q_ASSERT(tabBar()); } +QAccessibleTabBar::~QAccessibleTabBar() +{ + foreach (QAccessible::Id id, m_childInterfaces.values()) + QAccessible::deleteAccessibleInterface(id); +} + /*! Returns the QTabBar. */ QTabBar *QAccessibleTabBar::tabBar() const { @@ -161,9 +166,14 @@ QTabBar *QAccessibleTabBar::tabBar() const QAccessibleInterface* QAccessibleTabBar::child(int index) const { + if (QAccessible::Id id = m_childInterfaces.value(index)) + return QAccessible::accessibleInterface(id); + // first the tabs, then 2 buttons if (index < tabBar()->count()) { QAccessibleTabButton *button = new QAccessibleTabButton(tabBar(), index); + QAccessible::registerAccessibleInterface(button); + m_childInterfaces.insert(index, QAccessible::uniqueId(button)); return button; } else if (index >= tabBar()->count()) { // left button diff --git a/src/plugins/accessible/widgets/complexwidgets.h b/src/plugins/accessible/widgets/complexwidgets.h index 32f67c9c69..306eae4a72 100644 --- a/src/plugins/accessible/widgets/complexwidgets.h +++ b/src/plugins/accessible/widgets/complexwidgets.h @@ -47,6 +47,7 @@ #include #include + QT_BEGIN_NAMESPACE #ifndef QT_NO_ACCESSIBILITY @@ -101,6 +102,7 @@ class QAccessibleTabBar : public QAccessibleWidget { public: explicit QAccessibleTabBar(QWidget *w); + ~QAccessibleTabBar(); int childCount() const; QString text(QAccessible::Text t) const; @@ -113,6 +115,7 @@ public: protected: QTabBar *tabBar() const; + mutable QHash m_childInterfaces; }; #endif // QT_NO_TABBAR diff --git a/src/plugins/accessible/widgets/itemviews.cpp b/src/plugins/accessible/widgets/itemviews.cpp index 822d9d8c77..4ddd39f7ea 100644 --- a/src/plugins/accessible/widgets/itemviews.cpp +++ b/src/plugins/accessible/widgets/itemviews.cpp @@ -47,7 +47,6 @@ #include #include #include -#include #ifndef QT_NO_ACCESSIBILITY @@ -82,43 +81,6 @@ int QAccessibleTable::logicalIndex(const QModelIndex &index) const return (index.row() + hHeader)*(index.model()->columnCount() + vHeader) + (index.column() + vHeader); } -QAccessibleInterface *QAccessibleTable::childFromLogical(int logicalIndex) const -{ - if (!view()->model()) - return 0; - - int vHeader = verticalHeader() ? 1 : 0; - int hHeader = horizontalHeader() ? 1 : 0; - - int columns = view()->model()->columnCount() + vHeader; - - int row = logicalIndex / columns; - int column = logicalIndex % columns; - - if (vHeader) { - if (column == 0) { - if (row == 0) { - return new QAccessibleTableCornerButton(view()); - } - return new QAccessibleTableHeaderCell(view(), row-1, Qt::Vertical); - } - --column; - } - if (hHeader) { - if (row == 0) { - return new QAccessibleTableHeaderCell(view(), column, Qt::Horizontal); - } - --row; - } - - QModelIndex index = view()->model()->index(row, column, view()->rootIndex()); - if (!index.isValid()) { - qWarning() << "QAccessibleTable::childFromLogical: Invalid index at: " << row << column; - return 0; - } - return new QAccessibleTableCell(view(), index, cellRole()); -} - QAccessibleTable::QAccessibleTable(QWidget *w) : QAccessibleObject(w) { @@ -143,6 +105,8 @@ bool QAccessibleTable::isValid() const QAccessibleTable::~QAccessibleTable() { + Q_FOREACH (QAccessible::Id id, childToId.values()) + QAccessible::deleteAccessibleInterface(id); } QHeaderView *QAccessibleTable::horizontalHeader() const @@ -173,13 +137,6 @@ QHeaderView *QAccessibleTable::verticalHeader() const return header; } -QAccessibleTableCell *QAccessibleTable::cell(const QModelIndex &index) const -{ - if (index.isValid()) - return new QAccessibleTableCell(view(), index, cellRole()); - return 0; -} - QAccessibleInterface *QAccessibleTable::cellAt(int row, int column) const { if (!view()->model()) @@ -190,7 +147,7 @@ QAccessibleInterface *QAccessibleTable::cellAt(int row, int column) const qWarning() << "QAccessibleTable::cellAt: invalid index: " << index << " for " << view(); return 0; } - return cell(index); + return child(logicalIndex(index)); } QAccessibleInterface *QAccessibleTable::caption() const @@ -252,9 +209,8 @@ QList QAccessibleTable::selectedCells() const QList cells; if (!view()->selectionModel()) return cells; - Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedIndexes()) { - cells.append(cell(index)); - } + Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedIndexes()) + cells.append(child(logicalIndex(index))); return cells; } @@ -447,7 +403,7 @@ QAccessibleInterface *QAccessibleTable::childAt(int x, int y) const QModelIndex index = view()->indexAt(indexPosition); if (index.isValid()) { - return childFromLogical(logicalIndex(index)); + return child(logicalIndex(index)); } return 0; } @@ -465,7 +421,7 @@ int QAccessibleTable::indexOfChild(const QAccessibleInterface *iface) const { if (!view()->model()) return -1; - QSharedPointer parent(iface->parent()); + QAccessibleInterface *parent = iface->parent(); if (parent->object() != view()) return -1; @@ -478,7 +434,7 @@ int QAccessibleTable::indexOfChild(const QAccessibleInterface *iface) const return cell->index + (verticalHeader() ? 1 : 0); } else if (iface->role() == QAccessible::RowHeader){ const QAccessibleTableHeaderCell* cell = static_cast(iface); - return (cell->index + 1) * (view()->model()->rowCount() + 1); + return (cell->index + 1) * (view()->model()->columnCount() + 1); } else if (iface->role() == QAccessible::Pane) { return 0; // corner button } else { @@ -515,9 +471,55 @@ QAccessibleInterface *QAccessibleTable::parent() const return 0; } -QAccessibleInterface *QAccessibleTable::child(int index) const +QAccessibleInterface *QAccessibleTable::child(int logicalIndex) const { - return childFromLogical(index); + if (!view()->model()) + return 0; + + if (childToId.contains(logicalIndex)) { + QAccessible::Id id = childToId.value(logicalIndex); + return QAccessible::accessibleInterface(id); + } + + int vHeader = verticalHeader() ? 1 : 0; + int hHeader = horizontalHeader() ? 1 : 0; + + int columns = view()->model()->columnCount() + vHeader; + + int row = logicalIndex / columns; + int column = logicalIndex % columns; + + QAccessibleInterface *iface = 0; + + if (vHeader) { + if (column == 0) { + if (hHeader && row == 0) { + iface = new QAccessibleTableCornerButton(view()); + } else { + iface = new QAccessibleTableHeaderCell(view(), row - hHeader, Qt::Vertical); + } + } + --column; + } + if (!iface && hHeader) { + if (row == 0) { + iface = new QAccessibleTableHeaderCell(view(), column, Qt::Horizontal); + } + --row; + } + + if (!iface) { + QModelIndex index = view()->model()->index(row, column, view()->rootIndex()); + if (!index.isValid()) { + qWarning() << "QAccessibleTable::child: Invalid index at: " << row << column; + return 0; + } + iface = new QAccessibleTableCell(view(), index, cellRole()); + } + + QAccessible::registerAccessibleInterface(iface); + childToId.insert(logicalIndex, QAccessible::uniqueId(iface)); + return iface; } void *QAccessibleTable::interface_cast(QAccessible::InterfaceType t) @@ -527,6 +529,140 @@ void *QAccessibleTable::interface_cast(QAccessible::InterfaceType t) return 0; } +void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event) +{ + // if there is no cache yet, we don't update anything + if (childToId.isEmpty()) + return; + + switch (event->modelChangeType()) { + case QAccessibleTableModelChangeEvent::ModelReset: + Q_FOREACH (QAccessible::Id id, childToId.values()) + QAccessible::deleteAccessibleInterface(id); + childToId.clear(); + break; + + // rows are inserted: move every row after that + case QAccessibleTableModelChangeEvent::RowsInserted: + case QAccessibleTableModelChangeEvent::ColumnsInserted: { + int newRows = event->lastRow() - event->firstRow() + 1; + int newColumns = event->lastColumn() - event->firstColumn() + 1; + + ChildCache newCache; + ChildCache::ConstIterator iter = childToId.constBegin(); + + while (iter != childToId.constEnd()) { + QAccessible::Id id = iter.value(); + QAccessibleInterface *iface = QAccessible::accessibleInterface(id); + Q_ASSERT(iface); + if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) { + Q_ASSERT(iface->tableCellInterface()); + QAccessibleTableCell *cell = static_cast(iface->tableCellInterface()); + if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted + && cell->m_index.row() >= event->firstRow()) { + int newRow = cell->m_index.row() + newRows; + cell->m_index = cell->m_index.sibling(newRow, cell->m_index.column()); + } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted + && cell->m_index.column() >= event->firstColumn()) { + int newColumn = cell->m_index.column() + newColumns; + cell->m_index = cell->m_index.sibling(cell->m_index.row(), newColumn); + } + } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted + && iface->role() == QAccessible::RowHeader) { + QAccessibleTableHeaderCell *cell = static_cast(iface); + if (cell->index >= event->firstRow()) { + cell->index += newRows; + } + } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted + && iface->role() == QAccessible::ColumnHeader) { + QAccessibleTableHeaderCell *cell = static_cast(iface); + if (cell->index >= event->firstColumn()) { + cell->index += newColumns; + } + } + if (indexOfChild(iface) >= 0) { + newCache.insert(indexOfChild(iface), id); + } else { + // ### This should really not happen, + // but it might if the view has a root index set. + // This needs to be fixed. + QAccessible::deleteAccessibleInterface(id); + } + ++iter; + } + childToId = newCache; + break; + } + + case QAccessibleTableModelChangeEvent::ColumnsRemoved: + case QAccessibleTableModelChangeEvent::RowsRemoved: { + int deletedColumns = event->lastColumn() - event->firstColumn() + 1; + int deletedRows = event->lastRow() - event->firstRow() + 1; + ChildCache newCache; + ChildCache::ConstIterator iter = childToId.constBegin(); + while (iter != childToId.constEnd()) { + QAccessible::Id id = iter.value(); + QAccessibleInterface *iface = QAccessible::accessibleInterface(id); + Q_ASSERT(iface); + if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) { + Q_ASSERT(iface->tableCellInterface()); + QAccessibleTableCell *cell = static_cast(iface->tableCellInterface()); + if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved) { + if (cell->m_index.row() < event->firstRow()) { + newCache.insert(indexOfChild(cell), id); + } else if (cell->m_index.row() > event->lastRow()) { + int newRow = cell->m_index.row() - deletedRows; + cell->m_index = cell->m_index.sibling(newRow, cell->m_index.column()); + newCache.insert(indexOfChild(cell), id); + } else { + QAccessible::deleteAccessibleInterface(id); + } + } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved) { + if (cell->m_index.column() < event->firstColumn()) { + newCache.insert(indexOfChild(cell), id); + } else if (cell->m_index.column() > event->lastColumn()) { + int newColumn = cell->m_index.column() - deletedColumns; + cell->m_index = cell->m_index.sibling(cell->m_index.row(), newColumn); + newCache.insert(indexOfChild(cell), id); + } else { + QAccessible::deleteAccessibleInterface(id); + } + } + } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved + && iface->role() == QAccessible::RowHeader) { + QAccessibleTableHeaderCell *cell = static_cast(iface); + if (cell->index < event->firstRow()) { + newCache.insert(indexOfChild(cell), id); + } else if (cell->index > event->lastRow()) { + cell->index -= deletedRows; + newCache.insert(indexOfChild(cell), id); + } else { + QAccessible::deleteAccessibleInterface(id); + } + } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved + && iface->role() == QAccessible::ColumnHeader) { + QAccessibleTableHeaderCell *cell = static_cast(iface); + if (cell->index < event->firstColumn()) { + newCache.insert(indexOfChild(cell), id); + } else if (cell->index > event->lastColumn()) { + cell->index -= deletedColumns; + newCache.insert(indexOfChild(cell), id); + } else { + QAccessible::deleteAccessibleInterface(id); + } + } + ++iter; + } + childToId = newCache; + break; + } + + case QAccessibleTableModelChangeEvent::DataChanged: + // nothing to do in this case + break; + } +} + // TREE VIEW QModelIndex QAccessibleTree::indexFromLogical(int row, int column) const @@ -578,27 +714,33 @@ int QAccessibleTree::childCount() const } -QAccessibleInterface *QAccessibleTree::child(int index) const +QAccessibleInterface *QAccessibleTree::child(int logicalIndex) const { - if (index < 0 || !view()->model() || !view()->model()->columnCount()) + if (logicalIndex < 0 || !view()->model() || !view()->model()->columnCount()) return 0; - int hHeader = horizontalHeader() ? 1 : 0; - if (hHeader) { + QAccessibleInterface *iface = 0; + int index = logicalIndex; + + if (horizontalHeader()) { if (index < view()->model()->columnCount()) { - return new QAccessibleTableHeaderCell(view(), index, Qt::Horizontal); + iface = new QAccessibleTableHeaderCell(view(), index, Qt::Horizontal); } else { index -= view()->model()->columnCount(); } } - int row = index / view()->model()->columnCount(); - int column = index % view()->model()->columnCount(); - QModelIndex modelIndex = indexFromLogical(row, column); - if (modelIndex.isValid()) { - return cell(modelIndex); + if (!iface) { + int row = index / view()->model()->columnCount(); + int column = index % view()->model()->columnCount(); + QModelIndex modelIndex = indexFromLogical(row, column); + if (!modelIndex.isValid()) + return 0; + iface = new QAccessibleTableCell(view(), modelIndex, cellRole()); } - return 0; + QAccessible::registerAccessibleInterface(iface); + // ### FIXME: get interfaces from the cache instead of re-creating them + return iface; } int QAccessibleTree::rowCount() const @@ -612,7 +754,7 @@ int QAccessibleTree::indexOfChild(const QAccessibleInterface *iface) const { if (!view()->model()) return -1; - QSharedPointer parent(iface->parent()); + QAccessibleInterface *parent = iface->parent(); if (parent->object() != view()) return -1; @@ -624,12 +766,10 @@ int QAccessibleTree::indexOfChild(const QAccessibleInterface *iface) const int column = cell->m_index.column(); int index = row * view()->model()->columnCount() + column; - //qDebug() << "QAccessibleTree::indexOfChild r " << row << " c " << column << "index " << index; Q_ASSERT(index >= treeView->model()->columnCount()); return index; } else if (iface->role() == QAccessible::ColumnHeader){ const QAccessibleTableHeaderCell* cell = static_cast(iface); - //qDebug() << "QAccessibleTree::indexOfChild header " << cell->index; return cell->index; } else { qWarning() << "WARNING QAccessibleTable::indexOfChild invalid child" @@ -646,7 +786,11 @@ QAccessibleInterface *QAccessibleTree::cellAt(int row, int column) const qWarning() << "Requested invalid tree cell: " << row << column; return 0; } - return new QAccessibleTableCell(view(), index, cellRole()); + const QTreeView *treeView = qobject_cast(view()); + Q_ASSERT(treeView); + int logicalIndex = treeView->d_func()->accessibleTable2Index(index); + + return child(logicalIndex); // FIXME ### new QAccessibleTableCell(view(), index, cellRole()); } QString QAccessibleTree::rowDescription(int) const @@ -717,6 +861,7 @@ QList QAccessibleTableCell::rowHeaderCells() const { QList headerCell; if (verticalHeader()) { + // FIXME headerCell.append(new QAccessibleTableHeaderCell(view, m_index.row(), Qt::Vertical)); } return headerCell; @@ -726,6 +871,7 @@ QList QAccessibleTableCell::columnHeaderCells() const { QList headerCell; if (horizontalHeader()) { + // FIXME headerCell.append(new QAccessibleTableHeaderCell(view, m_index.column(), Qt::Horizontal)); } return headerCell; @@ -808,18 +954,18 @@ void QAccessibleTableCell::selectCell() QAbstractItemView::SelectionMode selectionMode = view->selectionMode(); if (!m_index.isValid() || (selectionMode == QAbstractItemView::NoSelection)) return; - - QSharedPointer cellTable(table()->tableInterface()); + Q_ASSERT(table()); + QAccessibleTableInterface *cellTable = table()->tableInterface(); switch (view->selectionBehavior()) { case QAbstractItemView::SelectItems: break; case QAbstractItemView::SelectColumns: - if (cellTable.data()) + if (cellTable) cellTable->selectColumn(m_index.column()); return; case QAbstractItemView::SelectRows: - if (cellTable.data()) + if (cellTable) cellTable->selectRow(m_index.row()); return; } @@ -838,17 +984,17 @@ void QAccessibleTableCell::unselectCell() if (!m_index.isValid() || (selectionMode & QAbstractItemView::NoSelection)) return; - QSharedPointer cellTable(table()->tableInterface()); + QAccessibleTableInterface *cellTable = table()->tableInterface(); switch (view->selectionBehavior()) { case QAbstractItemView::SelectItems: break; case QAbstractItemView::SelectColumns: - if (cellTable.data()) + if (cellTable) cellTable->unselectColumn(m_index.column()); return; case QAbstractItemView::SelectRows: - if (cellTable.data()) + if (cellTable) cellTable->unselectRow(m_index.row()); return; } @@ -962,10 +1108,7 @@ bool QAccessibleTableCell::isValid() const QAccessibleInterface *QAccessibleTableCell::parent() const { - if (m_role == QAccessible::TreeItem) - return new QAccessibleTree(view); - - return new QAccessibleTable(view); + return QAccessible::queryAccessibleInterface(view); } QAccessibleInterface *QAccessibleTableCell::child(int) const @@ -1051,11 +1194,7 @@ bool QAccessibleTableHeaderCell::isValid() const QAccessibleInterface *QAccessibleTableHeaderCell::parent() const { -#ifndef QT_NO_TREEVIEW - if (qobject_cast(view)) - return new QAccessibleTree(view); -#endif - return new QAccessibleTable(view); + return QAccessible::queryAccessibleInterface(view); } QAccessibleInterface *QAccessibleTableHeaderCell::child(int) const diff --git a/src/plugins/accessible/widgets/itemviews.h b/src/plugins/accessible/widgets/itemviews.h index af885fe6c1..09dacde7a2 100644 --- a/src/plugins/accessible/widgets/itemviews.h +++ b/src/plugins/accessible/widgets/itemviews.h @@ -65,8 +65,6 @@ public: explicit QAccessibleTable(QWidget *w); bool isValid() const; - virtual ~QAccessibleTable(); - QAccessible::Role role() const; QAccessible::State state() const; QString text(QAccessible::Text t) const; @@ -106,9 +104,9 @@ public: QAbstractItemView *view() const; -protected: - inline QAccessibleTableCell *cell(const QModelIndex &index) const; + void modelChange(QAccessibleTableModelChangeEvent *event); +protected: inline QAccessible::Role cellRole() const { switch (m_role) { case QAccessible::List: @@ -125,11 +123,16 @@ protected: QHeaderView *horizontalHeader() const; QHeaderView *verticalHeader() const; + + // maybe vector + typedef QHash ChildCache; + mutable ChildCache childToId; + + virtual ~QAccessibleTable(); + private: // the child index for a model index inline int logicalIndex(const QModelIndex &index) const; - // the model index from the child index - QAccessibleInterface *childFromLogical(int logicalIndex) const; QAccessible::Role m_role; }; @@ -140,7 +143,6 @@ public: : QAccessibleTable(w) {} - virtual ~QAccessibleTree() {} QAccessibleInterface *childAt(int x, int y) const; int childCount() const; @@ -158,6 +160,8 @@ public: private: QModelIndex indexFromLogical(int row, int column = 0) const; + + inline int logicalIndex(const QModelIndex &index) const; }; class QAccessibleTableCell: public QAccessibleInterface, public QAccessibleTableCellInterface, public QAccessibleActionInterface @@ -236,7 +240,7 @@ public: QAccessibleInterface *child(int index) const; private: - QAbstractItemView *view; + QPointer view; int index; Qt::Orientation orientation; @@ -273,8 +277,9 @@ public: QAccessibleInterface *child(int) const { return 0; } + private: - QAbstractItemView *view; + QPointer view; }; diff --git a/src/plugins/accessible/widgets/main.cpp b/src/plugins/accessible/widgets/main.cpp index ade4979256..686a90ca96 100644 --- a/src/plugins/accessible/widgets/main.cpp +++ b/src/plugins/accessible/widgets/main.cpp @@ -177,14 +177,6 @@ QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObjec } else if (classname == QLatin1String("QTableView") || classname == QLatin1String("QListView")) { iface = new QAccessibleTable(widget); // ### This should be cleaned up. We return the parent for the scrollarea to hide it. - } else if (classname == QLatin1String("QWidget") - && widget->objectName() == QLatin1String("qt_scrollarea_viewport") - && qobject_cast(widget->parentWidget())) { - if (qobject_cast(widget->parentWidget())) { - iface = new QAccessibleTree(widget->parentWidget()); - } else { - iface = new QAccessibleTable(widget->parentWidget()); - } #endif // QT_NO_ITEMVIEWS #ifndef QT_NO_TABBAR } else if (classname == QLatin1String("QTabBar")) { diff --git a/src/plugins/accessible/widgets/qaccessiblemenu.cpp b/src/plugins/accessible/widgets/qaccessiblemenu.cpp index e467ef50bd..f248e6d05e 100644 --- a/src/plugins/accessible/widgets/qaccessiblemenu.cpp +++ b/src/plugins/accessible/widgets/qaccessiblemenu.cpp @@ -55,6 +55,16 @@ QT_BEGIN_NAMESPACE QString Q_GUI_EXPORT qt_accStripAmp(const QString &text); QString Q_GUI_EXPORT qt_accHotKey(const QString &text); +QAccessibleInterface *getOrCreateMenu(QWidget *menu, QAction *action) +{ + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(action); + if (!iface) { + iface = new QAccessibleMenuItem(menu, action); + QAccessible::registerAccessibleInterface(iface); + } + return iface; +} + QAccessibleMenu::QAccessibleMenu(QWidget *w) : QAccessibleWidget(w) { @@ -76,7 +86,7 @@ QAccessibleInterface *QAccessibleMenu::childAt(int x, int y) const QAction *act = menu()->actionAt(menu()->mapFromGlobal(QPoint(x,y))); if(act && act->isSeparator()) act = 0; - return act ? new QAccessibleMenuItem(menu(), act) : 0; + return act ? getOrCreateMenu(menu(), act) : 0; } QString QAccessibleMenu::text(QAccessible::Text t) const @@ -98,7 +108,7 @@ QAccessible::Role QAccessibleMenu::role() const QAccessibleInterface *QAccessibleMenu::child(int index) const { if (index < childCount()) - return new QAccessibleMenuItem(menu(), menu()->actions().at(index)); + return getOrCreateMenu(menu(), menu()->actions().at(index)); return 0; } @@ -111,7 +121,7 @@ QAccessibleInterface *QAccessibleMenu::parent() const foreach (QWidget *w, parentCandidates) { if (qobject_cast(w) || qobject_cast(w)) { if (w->actions().indexOf(menuAction) != -1) - return new QAccessibleMenuItem(w, menuAction); + return getOrCreateMenu(w, menuAction); } } } @@ -146,8 +156,9 @@ int QAccessibleMenuBar::childCount() const QAccessibleInterface *QAccessibleMenuBar::child(int index) const { - if (index < childCount()) - return new QAccessibleMenuItem(menuBar(), menuBar()->actions().at(index)); + if (index < childCount()) { + return getOrCreateMenu(menuBar(), menuBar()->actions().at(index)); + } return 0; } @@ -177,7 +188,6 @@ QAccessibleInterface *QAccessibleMenuItem::childAt(int x, int y ) const if (childInterface->rect().contains(x,y)) { return childInterface; } - delete childInterface; } return 0; } @@ -207,7 +217,7 @@ QAccessibleInterface *QAccessibleMenuItem::parent() const QAccessibleInterface *QAccessibleMenuItem::child(int index) const { if (index == 0 && action()->menu()) - return new QAccessibleMenu(action()->menu()); + return QAccessible::queryAccessibleInterface(action()->menu()); return 0; } diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp index b5ee4a6046..751a722bb8 100644 --- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp +++ b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp @@ -718,7 +718,6 @@ QAccessibleInterface *QAccessibleTitleBar::childAt(int x, int y) const if (childIface->rect().contains(x,y)) { return childIface; } - delete childIface; } return 0; } -- cgit v1.2.3