Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-105231

reusing editor by reimplementing QAbstractItemDelegate::destroyEditor causes crashing

    XMLWordPrintable

Details

    • macOS, Windows
    • 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:

      1. Run this program.
      2. Just close it. Or switch to other windows.
      3. 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.
          */
      
      }
      

       

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            vhilshei Volker Hilsheimer
            namniav vainman H
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes