I am getting some strange behavior that has me stumped. An otherwise working model/view/delegate program will crash if a static dialog is used within the Method::setData() or Delegate::setModelData() methods. The program will pop up two dialogs, then segfault when both are closed.
I am trying to use a QMessageBox::warning() when the user enters invalid data. This is something the program needs to do. I get the same behavior with other static dialogs (QColorDialog, etc). It happens with both QTableView and QListView. The double dialog and crash happens when the user presses the enter or tab keys when finished editing in the delegate. It does NOT happen if the user clicks elsewhere in the view to finish editing.
I have created a tiny sample program to demonstrate. It's as short as I can get it with both a model and delegate. Remove the QMessageBox dialog and the program works. Keep it in and watch the strangeness when you edit a value.
#include <QtGui>
Q_OBJECT
public:
~TestModel();
int role = Qt::EditRole);
private:
};
{
Q_OBJECT
public:
~TestDelegate();
void updateEditorGeometry
(QWidget *editor,
};
#include <QtGui>
class TestModel : public QAbstractTableModel {
Q_OBJECT
public:
TestModel(QObject *parent);
~TestModel();
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole);
Qt::ItemFlags flags(const QModelIndex &index) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
private:
QStringList items;
};
class TestDelegate : public QItemDelegate
{
Q_OBJECT
public:
TestDelegate(QObject *parent = 0);
~TestDelegate();
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const;
void updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
};
To copy to clipboard, switch view to plain text mode
#include <QtGui>
#include "model.h"
{
items << "one" << "two" << "three" << "four";
}
TestModel::~TestModel() {}
{
if (!index.
isValid()) return QVariant();
if (index.
row() >
= items.
count()) return QVariant();
if ((role == Qt::DisplayRole) || (role == Qt::EditRole)) {
return items[index.row()];
} else {
}
}
{
if (!index.isValid()) return false;
if (index.row() >= items.count()) return false;
if (role != Qt::EditRole) return false;
items[index.row()] = value.toString();
emit dataChanged(index, index);
return true;
}
Qt
::ItemFlags TestModel
::flags(const QModelIndex &index
) const{
if (!index.isValid()) return Qt::ItemIsEnabled;
}
{
return items.count();
}
{
return 1;
}
TestDelegate::~TestDelegate() {}
{
items << "one" <<"two" <<"three" <<"four";
edit->installEventFilter(const_cast<TestDelegate*>(this));
return edit;
}
void TestDelegate
::setEditorData(QWidget *editor,
{
QVariant value
= index.
model()->data
(index, Qt
::EditRole);
QLineEdit *edit
=static_cast<QLineEdit
*>
(editor
);
if (!edit) return;
edit->setText(value.toString());
}
{
QLineEdit *edit
= static_cast<QLineEdit
*>
(editor
);
if (!edit) return;
model->setData(index, value);
}
void TestDelegate
::updateEditorGeometry(QWidget *editor,
{
if (editor) editor->setGeometry(option.rect);
}
#include <QtGui>
#include "model.h"
TestModel::TestModel(QObject *parent) : QAbstractTableModel(parent)
{
items << "one" << "two" << "three" << "four";
}
TestModel::~TestModel() {}
QVariant TestModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) return QVariant();
if (index.row() >= items.count()) return QVariant();
if ((role == Qt::DisplayRole) || (role == Qt::EditRole)) {
return items[index.row()];
} else {
return QVariant();
}
}
bool TestModel::setData(const QModelIndex &index,
const QVariant &value, int role)
{
if (!index.isValid()) return false;
if (index.row() >= items.count()) return false;
if (role != Qt::EditRole) return false;
QMessageBox::information(0, "Test", "This is a test");
items[index.row()] = value.toString();
emit dataChanged(index, index);
return true;
}
Qt::ItemFlags TestModel::flags(const QModelIndex &index) const
{
if (!index.isValid()) return Qt::ItemIsEnabled;
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
}
int TestModel::rowCount(const QModelIndex &) const
{
return items.count();
}
int TestModel::columnCount(const QModelIndex &) const
{
return 1;
}
TestDelegate::TestDelegate(QObject *parent) : QItemDelegate(parent) {}
TestDelegate::~TestDelegate() {}
QWidget *TestDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &/*option*/,
const QModelIndex &index) const
{
QStringList items;
items << "one" <<"two" <<"three" <<"four";
QLineEdit *edit = new QLineEdit(parent);
edit->installEventFilter(const_cast<TestDelegate*>(this));
return edit;
}
void TestDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
QVariant value = index.model()->data(index, Qt::EditRole);
QLineEdit *edit =static_cast<QLineEdit*>(editor);
if (!edit) return;
edit->setText(value.toString());
}
void TestDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
QLineEdit *edit = static_cast<QLineEdit*>(editor);
if (!edit) return;
QVariant value = edit->text();
model->setData(index, value);
}
void TestDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &/*index*/) const
{
if (editor) editor->setGeometry(option.rect);
}
To copy to clipboard, switch view to plain text mode
#include <QtGui>
#include "model.h"
int main(int argc, char *argv[])
{
TestModel model(0);
view.setModel(&model);
TestDelegate delegate;
view.setItemDelegate(&delegate);
view.show();
return app.exec();
}
#include <QtGui>
#include "model.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
TestModel model(0);
QTableView view;
view.setModel(&model);
TestDelegate delegate;
view.setItemDelegate(&delegate);
view.show();
return app.exec();
}
To copy to clipboard, switch view to plain text mode
I am using qt-4.1.2 on FreeBSD 6.0. I am going to submit this a bug to Trolltech as well, as I've not found anything similar in their tracker.
Bookmarks