PDA

View Full Version : refresh Qtreeview after removing row



doublelune
12th March 2008, 19:11
Hi,
I use Qt 4.3.3 on Windows and I have started to make the "simple Dom Model" from Qt examples and Demo editable. So I have a QTreeView based on a DomModel who inherits from QAbstractItemModel. The Data is an XML File.
I try to remove rows. No problem for datas, after deleting the data and resave it to a new XML file, the data corresponding to the rows has vanished. But the View deletes always the last row of the same parent Index, so Model and View are not in the same state anymore! Here is my code:


void DomModel::deleteNode(QModelIndex& rCurrentIndex)
{
emit layoutAboutToBeChanged();
beginRemoveRows(rCurrentIndex.parent(), rCurrentIndex.row(), rCurrentIndex.row());
removeRow(rCurrentIndex.row(),rCurrentIndex.parent ());
endRemoveRows();
emit layoutChanged();
}
...
bool DomModel::removeRow(int BeginRow,const QModelIndex& rParentIndex)
{
QModelIndex TypeIndex = rParentIndex.child(BeginRow, TYPE_ARGUMENT);
QModelIndex AttrIndex = rParentIndex.child(BeginRow, ATTRIBUTES_ARGUMENT);
DomItem* pItem = static_cast<DomItem*>(TypeIndex.internalPointer());
QDomNode Node = pItem->node();
QDomNode ParentNode = Node.parentNode();
ParentNode.removeChild(Node);
return true;
}
Any ideas?
Thanks

wysota
12th March 2008, 19:14
You need to use QAbstractItemModel::beginRemoveRows() and QAbstractItemModel::endRemoveRows()

BTW. The parent can be an empty model index thus QModelIndex::child() will return an empty model index as well. Instead you should write:

QModelIndex childIndex = index(row, column, parent);

Edit: I just noticed you are using begin/endRemoveRows, I'm not sure if it's in proper context though... What does your QAbstractItemModel::removeRows() look like?

Edit2: Don't emit those two signals you emit, begin/endRemoveRows will take care of that.

doublelune
12th March 2008, 20:09
I have made the change for having the index with child(row,column,parent) to ensure I have a parent.

Edit: I just noticed you are using begin/endRemoveRows, I'm not sure if it's in proper context though... What does your QAbstractItemModel::removeRows() look like?

It was a mistake... It is removeRow(), the next method in my code


Edit2: Don't emit those two signals you emit, begin/endRemoveRows will take care of that.
Ok, but anyway, same problem...

wysota
12th March 2008, 20:27
Well... removeRow() is not virtual so reimplementing it doesn't make much sense. You should reimplement removeRows(). removeRow() calls removeRows(), so it will work corectly. Then your deleteNode() method will not be needed anymore (it's not needed now too).

removeRows should look more or less like this:

bool DomModel::removeRows(int row,int count, const QModelIndex &parent) {
DomItem* pItem = parent.isValid() ? static_cast<DomItem*>(parent.internalPointer()) : rootItem;
QDomNode Node = pItem->node();
beginRemoveRows(parent, row, row+count-1);
while(count--){
Node.removeChild(pItem->child(row+count)->node());
}
endRemoveRows();
return true;
}

This will probably not work, becasue DomItem is not prepared for recalculating its children, so you'll have to correct it as well.

doublelune
13th March 2008, 18:52
Hello,
I call removeRows() now and reimplement it as you show, thanks. But I think you pointed the real problem, my DomItem is not prepared to recalculate itself. As I understand, I have to "refresh" my model after removing the data from him (a QDomNode). But I can you be more precise about it, please? As I start from the Qt example, I have in my DomItem object a pointer to his parent Item, a QHash of child items (m_pChildItemHash) and a member "rowNumber". As I see in debug, the child(int Index) method is called several times and I guess I mix a little bit data (QDomNode) and Item structure

Node.removeChild(pItem->child(row+count)->node());
that erase the data Node and is ok. I clear now the DomItem from the its ParentItem child's list with:


DomItem* pParentItem = pItem->parent();
pParentItem->removeChild(BeginRow);
...
void DomItem::removeChild(int Index)
{
m_pChildItemHash.remove(Index);
}

but it is not enough. Where did I miss something?
Thanks