Why doesn't QVariant work in this tree model's setData()?
-
I am using Qt 5.9 on linux. I have the Simple Tree Model Example running in my app, but now I'd like to add child nodes to the TreeView after the initial model has already been constructed. The only thing I've changed from the example is that the data is supplied by an external source rather than how it does it internally.
I have a tree model that inherits QAbstractItemMode ...
class MyTreeModel : public QAbstractItemModel { ... bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; ... }
and my problem is calling the setData function like so ...
QVector<QVariant> new_data; new_data << name << ""; const QModelIndex parent = tree_model->index(0, 0); tree_model->insertRow(0, parent); tree_model->setData(tree_model->index(0, 0, parent), QVariant(new_data));
I get the following error ...
error: no matching function for call to ‘QVariant::QVariant(QVector<QVariant>&)’ tree_model->setData(tree_model->index(0, 0, parent), QVariant(new_data));
If I change it to ...
tree_model->setData(tree_model->index(0, 0, parent), QStringLiteral("test"));
Then it all works ok but I don't understand why the QVariant doesn't work as in my method signature. I do it this way because eventually I want to add checkboxes to these items.
Thanks,
-
@SRaD
Hi
Can you try QVariant::fromValue(new_data);- eventually I want to add checkboxes to these items.
Just so you are aware, items can already be Checked
(like listbox)
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const { if (!index.isValid()) return 0; Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; if ( index.column() == 0 ) // or where ever you want it flags |= Qt::ItemIsUserCheckable; return flags; }
- eventually I want to add checkboxes to these items.
-
I was able to eventually get QStrings to appear in the TreeView, so now I've changed QString to a MyTreeItem, just like in the Simple Tree Model examples. And I'm having the same issue.
QVector<QVariant> part_data; new_data << name << ""; const QModelIndex parent = tree_model->index(0, 0); MyTreeItem *new_part = new MyTreeItem(new_data, QVariant::fromValue(parent)); // parent); tree_model->insertRow(0, parent); tree_model->setData(tree_model->index(0, 0, parent), QVariant::fromValue(new_part)); //new_part));
I can see that the constructor to MyTreeItem doesn't match, but just now sure how this should be called.
MyTreeItem(const QVector<QVariant> &data, MyTreeItem *parent = 0);
Here's the error ...
error: no matching function for call to ‘MyTreeItem::MyTreeItem(QVector<QVariant>&, const QModelIndex&)’ parent);
Any help much appreciated.
@mrjj thanks for the checkbox info, i tried it, but it didn't work, but you've given me something to look at.
-
Hi
something like
TreeItem *new_part = new MyTreeItem(new_datapart_data,nullptr);
if the signature really is
MyTreeItem(const QVector<QVariant> &data, MyTreeItem *parent = 0);
then it wont take index but pointer to other MyTreeItem -
Here's what I've got so far ...
QVector<QVariant> new_data; new_data << name << ""; const QModelIndex parent = tree_model->index(0, 0); MyTreeItem *new_item = new MyTreeItem(new_data, parent_item); tree_model->insertRow(0, parent); tree_model->setData(tree_model->index(0, 0, parent), QVariant(*new_item));
But I still can't get past this error ...
error: no matching function for call to ‘QVariant::QVariant(MyTreeItem&)’ tree_model->setData(tree_model->index(0, 0, parent), QVariant(*new_item)); ^
-
@SRaD
Hi
Well you tried to use QVector<QVariant> new_data;
but it takes
TreeItem::TreeItem(const QList<QVariant> &data, TreeItem *parent)also, i had to surface rootItem to allow adding new items. Else only
void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent)
seems the only way.anyway, i did
QList<QVariant> new_data; new_data << "test" << "test2"; TreeItem *new_item = new TreeItem(new_data, model.rootItem); model.rootItem->appendChild(new_item);
-
@SRaD said in Why doesn't QVariant work in this tree model's setData()?:
tree_model->insertRow(0, parent);
This does nothing for the
QAbstractItemModel
, so if you haven't you need to implement it.tree_model->setData(tree_model->index(0, 0, parent), QVariant(*new_item));
This should rather be:
int row = 0; // This is the index of the newly inserted row in the parent's table. It may differ from 0 for (int i = 0, size = new_data.size(); i < size; i++) tree_model->setData(tree_model->index(row, i, parent), new_data[i]);
-
@kshegunov
Just to be clear
The poster should implement setData and in there use RootItem
to add new TreeItem in there? -
No, the OP should already have either a pointer or an ID to the parent object which is stored in the model index. Whenever [s]he needs to add a new node that's what should be used as a parent. The model index itself is just an identifier to the data.
setData
you implement to drumroll ... set the data. If the data is coming from outside the model, then you just notify the connected proxy models and/or view by emitting the relevant signals - that is you callbeginInsertRows
/beginInsertColumns
anendInsertRows
/endInsertColumns
in the appropriate places. -
@kshegunov
Ok, but i don't see how the model will let you know the existing TreeItem you want to¨
append the new node to. (from outside)
Something like ?const QModelIndex parent = model.index(0, 0); TreeItem *itemParent = static_cast<TreeItem *>(parent.internalPointer());
-
@mrjj said in Why doesn't QVariant work in this tree model's setData()?:
Something like ?
Exactly like. However you already get the parent index from the Qt runtime, you don't create it with
QAbstractItemModel::index
. -
ok super.
So basically the poster would have more fun using the model
from
https://doc.qt.io/qt-5/qtwidgets-itemviews-editabletreemodel-example.html
as it already implemented setData and support for altering the data.