Reputation: 1462
I have created a custom QAbstractItemModel-derived model that contains a set of XML data in a tree hierarchical fashion that will display in a QTreeView as shown in this image:
http://imageshack.us/photo/my-images/840/xmltreeview.png
This model has successfully pass the ModelTest and some basic editing tests. However, I have run into some problems when trying to do some filtering on this model so that I can split the model into a few different views. I have tried QSortFilterProxyModel and it crashes alot. After some fixing, it still crashes after attempting to remove a row from the model.
Console Application shows these messages when crash occurs:
ratbr QModelIndex(0,0,0xd162000,CGHXmlModel(0xb197e68) ) 0 0
rr QModelIndex(0,0,0xd162000,CGHXmlModel(0xb197e68) ) 0 0
and this is the callstack when crash happened:
0 QSortFilterProxyModelPrivate::index_to_iterator qsortfilterproxymodel.cpp 193 0x0134714b
1 QSortFilterProxyModel::parent qsortfilterproxymodel.cpp 1654 0x0111a677
2 QModelIndex::parent qabstractitemmodel.h 389 0x6a2ad95e
3 QPersistentModelIndex::parent qabstractitemmodel.cpp 347 0x6a1f7320
4 QItemSelectionRange::isValid qitemselectionmodel.h 108 0x01341ea4
5 QItemSelectionModel::isSelected qitemselectionmodel.cpp 1187 0x010f0b58
6 QTreeView::drawRow qtreeview.cpp 1602 0x010db133
7 QTreeView::drawTree qtreeview.cpp 1441 0x010da4f4
8 QTreeView::paintEvent qtreeview.cpp 1274 0x010d9bed
9 QWidget::event qwidget.cpp 8333 0x00c1492d
10 QFrame::event qframe.cpp 557 0x00f8e6bc
11 QAbstractScrollArea::viewportEvent qabstractscrollarea.cpp 1043 0x0101bf0f
12 QAbstractItemView::viewportEvent qabstractitemview.cpp 1619 0x010a5785
13 QTreeView::viewportEvent qtreeview.cpp 1256 0x010d9aa3
14 QAbstractScrollAreaPrivate::viewportEvent qabstractscrollarea_p.h 100 0x01276a13
15 QAbstractScrollAreaFilter::eventFilter qabstractscrollarea_p.h 116 0x0127506c
16 QCoreApplicationPrivate::sendThroughObjectEventFilters qcoreapplication.cpp 847 0x6a1ffc73
17 QApplicationPrivate::notify_helper qapplication.cpp 4392 0x00bc96e5
18 QApplication::notify qapplication.cpp 4361 0x00bc9586
19 QCoreApplication::notifyInternal qcoreapplication.cpp 732 0x6a1ff9dc
20 QCoreApplication::sendSpontaneousEvent qcoreapplication.h 218 0x0123d53e
I'm still quite new to Qt Model/View programming and this error has really been daunting and left me scratching my head for days. I hope someone here can help me out here before I lose all my hair! Thanks!
EDIT: Update to include some source codes
My test project has two dialog windows, with one QTreeView each. One is the main window containing the QAbstractItemModel-derived class member and the other is a child window contain the QSortFilterProxyModel-derived class member. The child window also has a QAbstractItemModel pointer to the actual model.
Main window:
class CGHXMLModelDialog : public QDialog
{
Q_OBJECT
...
private:
Ui::CGHXMLModelDialog *ui;
CGHXmlModel* m_mainModel;
CGHXMLParameterDialog* m_ParamDialog;
...
}
Child window:
class CGHXMLParameterDialog : public QDialog
{
Q_OBJECT
...
private:
void setupProxyModel();
Ui::CGHXMLParameterDialog* ui;
QAbstractItemModel* m_coreModel;//A CGHXMLModel
CGHXMLSortFilterProxyModel* m_ParamModel;
...
}
In CGHXMLModelDialog constructor:
m_mainModel = new CGHXmlModel(theDomDocument, this);
ui->CGHXMLTreeView->setModel(m_mainModel);
//Create sub-dialog window containing proxy filter model
m_ParamDialog = new CGHXMLParameterDialog(m_mainModel, this);
which then calls the setupProxyModel() method:
CGHXMLParameterDialog::CGHXMLParameterDialog(QAbstractItemModel* coreModel, QWidget *parent) :
QDialog(parent),
ui(new Ui::CGHXMLParameterDialog),
m_coreModel(coreModel)
{
ui->setupUi(this);
setupProxyModel();
}
void CGHXMLParameterDialog::setupProxyModel()
{
m_ParamModel = new CGHXMLSortFilterProxyModel(this);
m_ParamModel->setSourceModel(m_coreModel);
m_ParamModel->setFilterRegExp(QRegExp("Parameter"));
m_ParamModel->setFilterKeyColumn(0);
m_ParamModel->setDynamicSortFilter(true);
ui->CGHXMLParamView->setModel(m_ParamModel);
}
I have tested insert rows, edit row content, insert XML attribute via column editing (custom column manipulating; I won't elaborate) etc on the source model directly and it worked both with and without the presence of the Sort-Filter model. The problem occurs when I try to delete a "row", which is an XML element for my model, when there is a Sort-Filter model attached to it.
Here is my code for removeRows:
bool CGHXmlModel::removeRows(int rowposition, int rows, const QModelIndex &parent)
{
CGHXMLTreeItem *parentItem = getItem(parent);
bool success = false;
beginRemoveRows(parent, rowposition, rowposition + rows - 1);
success = parentItem->removeChildren(rowposition, rows);
endRemoveRows();
if(success)//Works!
{
emit layoutChanged();
}
return success;
}
which is called by a button event handler in the main window:
void CGHXMLModelDialog::on_deleteRowButton_clicked()
{
QModelIndex currIndex = ui->CGHXMLTreeView->selectionModel()->currentIndex();
if(!m_mainModel->removeRow(currIndex.row(), currIndex.parent()))
{
qDebug() << "Fail to remove row from Model.";
return;
}
}
//Program crashes after this function returns.
Update: Is it wrong to emit layoutChanged() without emitting layoutAboutToBeChanged()?
Upvotes: 5
Views: 3996
Reputation: 1462
I have solved this problem by commenting the line "emit layoutChanged()" for my insertRows, removeRows methods. Originally the code did not have this line but an updating problem with QTreeView forced me to include it, without including "emit layoutAboutToChanged()". It seems the updating problem has disappeared for some reason.
Anyway thanks to those who tried to help. I will surely need more in the near future.
Upvotes: 2
Reputation: 672
Are you aware that indexes from QAbstractItemModel and QSortFilterProxyModel cannot be mixed?
If you have a QModelIndex from your filterProxy model, then you need to convert it to a QModelIndex from the item model using QAbstractProxyModel::mapToSource().
Upvotes: 1