PDA

View Full Version : Simple DOM Model - making it editable - inserting rows



Wolf900
29th February 2012, 15:14
I've been messing with the Simple DOM Model Example and I want to make everything editable. I have a problem with adding rows to the model.

Specifically, when I use insertAfter function in QDomNode:: parentNode(), the model gets updated only internally. When I collapse and expand the parent, the added node(s) are copies of the last nodes and are inserted in the end.

The only way I am able to get it right is save XML to QString and load it again into QDomModel and QTreeView. Then everything that has been inserted is where it should be. But then all the expanded states are lost! Not very user-friendly...

I have tried adding rows using insertRows function in QDomModel, however a copy of the entire model gets inserted as a child instead of an empty row!



// Get current index
QModelIndex currentTreeIdx = ui->treeView->selectionModel()->currentIndex();
// Get the node corresponding to that index
DomItem *itemRef = static_cast<DomItem*>(currentTreeIdx.internalPointer());

QDomElement newParentTag;
QDomElement newTextTag;
QDomText newText;
// Create tags
newParentTag = model->domDocument.createElement("Parent");
newTextTag = model->domDocument.createElement("Child");
newText = model->domDocument.createTextNode("Child text data");
newTextTag.appendChild(newText);
newSubtitleTag.appendChild(newTextTag);
// Attempt to insert a new tag after the currently selected item
itemRef->node().parentNode().insertAfter(newParentTag, itemRef->node());

wysota
29th February 2012, 15:42
If you want the model to be updated, you need to add rows through the model API or at least inform the model how you are changing the underlying data structure.

Wolf900
29th February 2012, 15:46
I've tried to inform the model by calling


emit dataChanged(idx, idx);

in DomModel : QAbstractItemModel when QModelIndex idx is updated. It seems it does nothing.

I've even tried to call it for each index in the model.

wysota
29th February 2012, 15:57
dataChanged() is for modifying existing elements, not for adding new ones.

Wolf900
29th February 2012, 16:48
Ok.

Now instead of insertAfter(...), I'm trying this:



model->insertRows(itemRef->row(), 1, currentTreeIdx.parent());


and the function being called is:



bool DomModel::insertRows(int position, int rows, const QModelIndex &parent){

//DomItem *parentItem = getItem(parent);
DomItem *parentItem = static_cast<DomItem*>(parent.internalPointer()); // reference item

bool success;
//emit dataChanged(parent, parent);

beginInsertRows(parent, position, position + rows - 1);
success = parentItem->insertChildren(position, rows, 4);
endInsertRows();

return success;
}

This one should create a row. It does create an invisible parent that I can click on to expand. But this parent now contains a copy of the entire model...

Added after 13 minutes:

Basically, to add to this, what I'm trying to achieve is combine "Editable Tree Model" and "Simple Dom Model" examples. So I'm having the latter as a base and I've copied the edit functions over there, changed the flags, setData, etc.

Wolf900
1st March 2012, 11:18
It seems the culprit is the insertChildren function:



bool DomItem::insertChildren(int position, int count, int columns){
if (position < 0 || position > childItems.size()){
return false;
}

for (int row = 0; row < count; row++){
DomItem *item = new DomItem(*(new QDomNode()), row, this); // this doesn't seem to be correct...
childItems.insert(position, item);
}

return true;
}


What insertRows does now is replace the selected row with an empty row.