[Interest] Double free in QItemDelegate editor
Kyle Edwards
kyle.edwards at kitware.com
Fri Sep 4 21:20:13 CEST 2020
On 9/4/20 2:40 PM, Kyle Edwards wrote:
> After some more investigation, I've learned more about the nature of
> the problem.
>
> The createEditor() override returns a button which, when clicked,
> opens a file dialog (through QFileDialog::getOpenFileName() - this
> will be important in a bit). The opening of this dialog causes the
> editor to lose focus, which result in QAbstractItemDelegate emitting
> its closeEditor() signal, which in turn destroys the editor. The
> destroying of the editor also attempts to delete the file dialog,
> since it's a child of the editor. However, the file dialog was
> allocated on the stack by QFileDialog::getOpenFileName(). So,
> attempting to delete the stack-allocated dialog results in a crash.
>
> So I guess the question is, how do I prevent QAbstractItemDelegate
> from emitting closeEditor() when the file dialog opens? Either that or
> prevent closeEditor() from actually closing the editor... I see
> something in QAbstractItemView::closeEditor() about an editor being
> "persistent", does that have anything to do with this?
I now have a minimum working test case:
// BEGIN
#include<QItemDelegate>
#include<QApplication>
#include<QFileDialog>
#include<QLineEdit>
#include<QResizeEvent>
#include<QStandardItemModel>
#include<QToolButton>
#include<QTreeView>
#include<QWidget>
classTestEdit: publicQLineEdit
{
Q_OBJECT
public:
TestEdit(QWidget*parent= nullptr);
voidresizeEvent(QResizeEvent*e) override;
public slots:
voidchooseFile();
private:
QToolButton* toolButton;
};
TestEdit::TestEdit(QWidget*parent)
: QLineEdit(parent)
{
this->toolButton= newQToolButton(this);
this->toolButton->setText("...");
QObject::connect(this->toolButton, SIGNAL(clicked(bool)), this,
SLOT(chooseFile()));
}
voidTestEdit::resizeEvent(QResizeEvent*e)
{
// make the tool button fit on the right side
inth= e->size().height();
// move the line edit to make room for the tool button
this->setContentsMargins(0, 0, h, 0);
// put the tool button in its place
this->toolButton->resize(h, h);
this->toolButton->move(this->width() - h, 0);
}
voidTestEdit::chooseFile()
{
autopath= QFileDialog::getOpenFileName(this, "title", QString(), QString(),
nullptr, QFileDialog::DontResolveSymlinks);
if(!path.isEmpty()) {
this->setText(path);
}
}
classTestItemDelegate: publicQItemDelegate
{
Q_OBJECT
public:
QWidget*createEditor(QWidget*parent, constQStyleOptionViewItem&option,
constQModelIndex&index) constoverride;
};
QWidget*TestItemDelegate::createEditor(QWidget*parent,
constQStyleOptionViewItem&option, constQModelIndex&index) const
{
returnnewTestEdit(parent);
}
intmain(intargc, char**argv)
{
QApplicationapp(argc, argv);
QWidgetwindow;
QTreeViewview(&window);
auto* model= newQStandardItemModel;
view.setModel(model);
model->insertRow(0);
model->insertColumn(0);
model->setData(model->index(0, 0), "Hello");
view.setItemDelegate(newTestItemDelegate);
window.show();
returnapp.exec();
}
#include"qttest.moc"
// END
Run the program, double click the "Hello" item, a line editor will
appear, click the button on the right to open the dialog, and then the
invalid delete happens.
Kyle
More information about the Interest
mailing list