Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
None
-
5.3.0 RC1, 5.3.0, 5.6.1
-
MacOS 10.9.2, gcc 4.8.1
Description
My application crashes when I remove a selected row from QAbstractTableModel/QTableView with Accessibility enabled in the MacOS (System Preferences -> Accessibility -> VoiceOver -> Enable VoiceOver). With Accessibility disabled it works fine. So the problem seems to be that in QTableView::selectionChanged(selected, deselected), those deselected indices are not checked for validity.
Application's output before the crash:
selected:(QItemSelectionRange(QModelIndex(0,1,0x0,LayersModel(0x10366da00) ) , QModelIndex(0,3,0x0,LayersModel(0x10366da00) ) ) ) deselected:(QItemSelectionRange(QModelIndex(1,1,0x0,LayersModel(0x10366da00) ) , QModelIndex(1,3,0x0,LayersModel(0x10366da00) ) ) ) rows count:1 QAccessibleTable::child: Invalid index at: 1 1
...and the backtrace:
* thread #1: tid = 0x225b1, 0x00000001023cd18d QtGui`QAccessibleEvent::uniqueId() const + 157, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0) * frame #0: 0x00000001023cd18d QtGui`QAccessibleEvent::uniqueId() const + 157 frame #1: 0x00000001076a604d libqcocoa.dylib`___lldb_unnamed_function766$$libqcocoa.dylib + 29 frame #2: 0x0000000102064b6c QtWidgets`QTableView::selectionChanged(QItemSelection const&, QItemSelection const&) + 764 frame #3: 0x000000010020f9a8 Flame Painter 3 Pro`LayersView::selectionChanged(this=0x000000010a8bb900, selected=0x00007fff5fbeef90, deselected=0x00007fff5fbeef98) + 9860 at layers_view.cpp:166 frame #4: 0x000000010203a010 QtWidgets`___lldb_unnamed_function3663$$QtWidgets + 1120 frame #5: 0x0000000102b06b0f QtCore`QMetaObject::activate(QObject*, int, int, void**) + 1871 frame #6: 0x0000000102a9351d QtCore`QItemSelectionModel::emitSelectionChanged(QItemSelection const&, QItemSelection const&) + 1165 frame #7: 0x0000000102a9301b QtCore`QItemSelectionModel::select(QItemSelection const&, QFlags<QItemSelectionModel::SelectionFlag>) + 731 frame #8: 0x00000001001f81a4 Flame Painter 3 Pro`LayersSelectionModel::select(this=0x000000010bc41dc0, selection=0x00007fff5fbef578, command=QItemSelectionModel::SelectionFlags at 0x00007fff5fbef090) + 4918 at layers_selection_model.cpp:35 frame #9: 0x0000000102a92cfb QtCore`QItemSelectionModel::select(QModelIndex const&, QFlags<QItemSelectionModel::SelectionFlag>) + 59 frame #10: 0x000000010020c439 Flame Painter 3 Pro`LayersView::selectRow(this=0x000000010a8bb900, row=0) + 1317 at layers_view.cpp:138 frame #11: 0x000000010020c9f9 Flame Painter 3 Pro`LayersView::SelectCurrentLayer(this=0x000000010a8bb900) + 1291 at layers_view.cpp:146 frame #12: 0x00000001000888ae Flame Painter 3 Pro`PanelLayers::DeleteSelectedLayers_Process(this=0x000000010a8b5950) + 1614 at panel_layers.cpp:300
...and here is the relevant code:
void LayersView::selectionChanged (const QItemSelection & selected, const QItemSelection & deselected) { QDBGF("selected:" << selected); QDBGF("deselected:" << deselected); QDBGF("rows count:"<<mpModel->rowCount()); QTableView::selectionChanged(selected, deselected); } void LayersSelectionModel::select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) { if (mSelectionLocked) { return; } if (command == NoUpdate) { return; } if (selection.empty()) { return; } // Create a new expanded selection QItemSelection sel; for (const QItemSelectionRange& range : selection) { const QModelIndex& tl = range.topLeft(); const QModelIndex& br = range.bottomRight(); sel.push_back(QItemSelectionRange( mpModel->index(tl.row(), mpModel->SELECTION_START_COLUMN), mpModel->index(br.row(), mpModel->columnCount()-1))); } QItemSelectionModel::select(sel, command); } void LayersView::selectRow(int row) { if (!mpModel) return; const QModelIndex& index = mpModel->index(row, mpModel->SELECTION_START_COLUMN); selectionModel()->select(index, QItemSelectionModel::ClearAndSelect); selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); }
The workaround I use for now is this:
void LayersView::selectionChanged (const QItemSelection & selected, const QItemSelection & deselected) { QItemSelection deselected_ok; if (mpModel) { for (QModelIndex i : deselected.indexes()) { if (i.column() < mpModel->columnCount() && i.row() < mpModel->rowCount()) { deselected_ok.select(i, i); } } } QTableView::selectionChanged(selected, deselected_ok); }
Thanks for all your great work on the Qt!
Attachments
Issue Links
- duplicates
-
QTBUG-57146 crash in QAccessibleEvent::uniqueId() on MacOS 10.12.1
- Closed
- is duplicated by
-
QTBUG-54776 Q_ASSERT hit in QAccessible::registerAccessibleInterface
- Closed
-
QTBUG-56043 When accessibility is in use, setting a QListView's model to null causes a crash
- Closed
-
QTBUG-57146 crash in QAccessibleEvent::uniqueId() on MacOS 10.12.1
- Closed