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.

Qt Code:
  1. #include <QtGui>
  2.  
  3. class TestModel : public QAbstractTableModel {
  4. Q_OBJECT
  5. public:
  6. TestModel(QObject *parent);
  7. ~TestModel();
  8.  
  9. QVariant data(const QModelIndex &index, int role) const;
  10. bool setData(const QModelIndex &index, const QVariant &value,
  11. int role = Qt::EditRole);
  12. Qt::ItemFlags flags(const QModelIndex &index) const;
  13. int rowCount(const QModelIndex &parent = QModelIndex()) const;
  14. int columnCount(const QModelIndex &parent = QModelIndex()) const;
  15.  
  16. private:
  17. QStringList items;
  18. };
  19.  
  20. class TestDelegate : public QItemDelegate
  21. {
  22. Q_OBJECT
  23. public:
  24. TestDelegate(QObject *parent = 0);
  25. ~TestDelegate();
  26.  
  27. QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
  28. const QModelIndex &index) const;
  29. void setEditorData(QWidget *editor, const QModelIndex &index) const;
  30. void setModelData(QWidget *editor, QAbstractItemModel *model,
  31. const QModelIndex &index) const;
  32. void updateEditorGeometry(QWidget *editor,
  33. const QStyleOptionViewItem &option,
  34. const QModelIndex &index) const;
  35. };
To copy to clipboard, switch view to plain text mode 

Qt Code:
  1. #include <QtGui>
  2. #include "model.h"
  3.  
  4. TestModel::TestModel(QObject *parent) : QAbstractTableModel(parent)
  5. {
  6. items << "one" << "two" << "three" << "four";
  7. }
  8.  
  9. TestModel::~TestModel() {}
  10.  
  11. QVariant TestModel::data(const QModelIndex &index, int role) const
  12. {
  13. if (!index.isValid()) return QVariant();
  14. if (index.row() >= items.count()) return QVariant();
  15.  
  16. if ((role == Qt::DisplayRole) || (role == Qt::EditRole)) {
  17. return items[index.row()];
  18. } else {
  19. return QVariant();
  20. }
  21. }
  22.  
  23. bool TestModel::setData(const QModelIndex &index,
  24. const QVariant &value, int role)
  25. {
  26. if (!index.isValid()) return false;
  27. if (index.row() >= items.count()) return false;
  28. if (role != Qt::EditRole) return false;
  29.  
  30. QMessageBox::information(0, "Test", "This is a test");
  31.  
  32. items[index.row()] = value.toString();
  33.  
  34. emit dataChanged(index, index);
  35. return true;
  36. }
  37.  
  38. Qt::ItemFlags TestModel::flags(const QModelIndex &index) const
  39. {
  40. if (!index.isValid()) return Qt::ItemIsEnabled;
  41. return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
  42. }
  43.  
  44. int TestModel::rowCount(const QModelIndex &) const
  45. {
  46. return items.count();
  47. }
  48.  
  49. int TestModel::columnCount(const QModelIndex &) const
  50. {
  51. return 1;
  52. }
  53.  
  54. TestDelegate::TestDelegate(QObject *parent) : QItemDelegate(parent) {}
  55.  
  56. TestDelegate::~TestDelegate() {}
  57.  
  58. QWidget *TestDelegate::createEditor(QWidget *parent,
  59. const QStyleOptionViewItem &/*option*/,
  60. const QModelIndex &index) const
  61. {
  62. QStringList items;
  63. items << "one" <<"two" <<"three" <<"four";
  64.  
  65. QLineEdit *edit = new QLineEdit(parent);
  66. edit->installEventFilter(const_cast<TestDelegate*>(this));
  67. return edit;
  68. }
  69.  
  70. void TestDelegate::setEditorData(QWidget *editor,
  71. const QModelIndex &index) const
  72. {
  73. QVariant value = index.model()->data(index, Qt::EditRole);
  74.  
  75. QLineEdit *edit =static_cast<QLineEdit*>(editor);
  76. if (!edit) return;
  77. edit->setText(value.toString());
  78. }
  79.  
  80. void TestDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
  81. const QModelIndex &index) const
  82. {
  83. QLineEdit *edit = static_cast<QLineEdit*>(editor);
  84. if (!edit) return;
  85. QVariant value = edit->text();
  86. model->setData(index, value);
  87.  
  88. }
  89.  
  90. void TestDelegate::updateEditorGeometry(QWidget *editor,
  91. const QStyleOptionViewItem &option,
  92. const QModelIndex &/*index*/) const
  93. {
  94. if (editor) editor->setGeometry(option.rect);
  95. }
To copy to clipboard, switch view to plain text mode 

Qt Code:
  1. #include <QtGui>
  2. #include "model.h"
  3.  
  4. int main(int argc, char *argv[])
  5. {
  6. QApplication app(argc, argv);
  7.  
  8. TestModel model(0);
  9.  
  10. QTableView view;
  11. view.setModel(&model);
  12.  
  13. TestDelegate delegate;
  14. view.setItemDelegate(&delegate);
  15.  
  16. view.show();
  17. return app.exec();
  18. }
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.