Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
6.3.1
-
None
-
Windows 10 21H2
-
-
52f4d0b0d2 (qt/qtbase/dev) 52f4d0b0d2 (qt/tqtc-qtbase/dev) 6dd2dbaef6 (qt/qtbase/6.4) 940e02db54 (qt/qtbase/6.3) 6dd2dbaef6 (qt/tqtc-qtbase/6.4) a09137af8d (qt/tqtc-qtbase/6.2) 940e02db54 (qt/tqtc-qtbase/6.3)
Description
The issue was first posted at https://forum.qt.io/topic/138208/how-to-reuse-editor-widget-for-custom-item-delegate . I think this is possibly a bug of Qt.
The following content is copied from the linked post.
I want to reuse the editor widget for custom item delegate.
void QAbstractItemDelegate::destroyEditor(QWidget *editor, const QModelIndex &index) const
says
Called when the editor is no longer needed for editing the data item with the given index and should be destroyed. The default behavior is a call to deleteLater on the editor. It is possible e.g. to avoid this delete by reimplementing this function.
I subclass from QStyledItemDelegate and reimplement destroyEditor like
editor->setParent(nullptr);
editor->hide();
editor->setEnabled(false);
m_idleEditor = editor;
All works well except that when the editor has focus and I close the window, the app crashes. [Edit: The crashing also happens when the editor has focus and the entire window loses focus.]
What's the problem and how can I completely detach the editor without deleting it?
I am using Qt6.3 on windows 10.
Here's the reduced complete demo to reproduce:
- Run this program.
- Just close it. Or switch to other windows.
- See the crash.
#include <QDebug> #include <QApplication> #include <QWidget> #include <QVBoxLayout> #include <QTreeView> #include <QComboBox> #include <QStandardItem> #include <QStandardItemModel> #include <QStyledItemDelegate> class ComboDelegate: public QStyledItemDelegate { public: ComboDelegate(QObject* parent): QStyledItemDelegate(parent) {} ~ComboDelegate() { qDebug() << "entering " << __func__; idle->deleteLater(); qDebug() << "exiting " << __func__; } QComboBox* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override { qDebug() << "entering " << __func__; auto cb = new QComboBox(parent); cb->addItem("One"); cb->addItem("Two"); cb->setEditable(true); qDebug() << "exiting " << __func__; return cb; } void setEditorData(QWidget* editor, const QModelIndex& index) const override { qDebug() << "entering " << __func__; auto cb = qobject_cast<QComboBox*>(editor); cb->setCurrentText(index.data(Qt::DisplayRole).toString()); qDebug() << "exiting " << __func__; } void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override { qDebug() << "entering " << __func__; auto cb = qobject_cast<QComboBox*>(editor); model->setData(index, cb->currentText(), Qt::DisplayRole); qDebug() << "exiting " << __func__; } void destroyEditor(QWidget* editor, const QModelIndex& index) const override { qDebug() << "entering " << __func__; auto cb = qobject_cast<QComboBox*>(editor); cb->setParent(nullptr); // How to completely detach the editor from treeview ? cb->hide(); cb->setEnabled(false); idle = cb; qDebug() << "exiting " << __func__; } private: mutable QComboBox* idle{nullptr}; }; int main(int argc, char** argv) { QApplication app(argc, argv); QWidget widget; auto box = new QVBoxLayout(&widget); auto model = new QStandardItemModel(&widget); model->appendRow(new QStandardItem("One")); model->appendRow(new QStandardItem("Two")); auto tree = new QTreeView(&widget); box->addWidget(tree); tree->setModel(model); tree->setItemDelegate(new ComboDelegate(&widget)); widget.show(); tree->edit(model->index(0, 0)); return app.exec(); /* Then just close the window, or click other windows to make the application lose focus, then it crashes. If you click on blank to close the combobox before other operations, the application can exit normally. */ }