PDA

View Full Version : Custom editor for derived QTreeWidgetItem in a QTreeWidget



olivier1978
27th February 2013, 20:29
Hi all,

I am trying to create an application which displays a scene graph from an OpenSceneGraph file. For now, it works. I started with an already existing project, and have created my own branch to make some tests. The whole code is available on github: QosgSceneEdit (https://github.com/oliviertournaire/QosgSceneEdit).

Now, what I want is to set for each item in the QTreeView a custom editor to change the properties of the associated OSG node. For instance, if my node is a PagedLOD, I would like to be able to change its ranges, taht is to say, the editor has to provide some QLineEdit with QDoubleValidator. I tried, but I cannot manage to find a way to do this. From what I have read, it seems that I have to use a custom class derived from QStyledItemDelegate. However, I cannot figure what should I reimplement in the derived class, and, moreover, how can I attach a dedicated QStyledItemDelegate based on the node type contained in the item (PagedLODDelegate for items containing an osg::PagedLOD, and so on).

Any help would be appreciated. And, if you could provide some code, or a detailled step by step solution, it would be perfect!

Regards,

Olivier

wysota
27th February 2013, 23:27
QAbstractItemDelegate::createEditor()

olivier1978
28th February 2013, 08:08
QAbstractItemDelegate::createEditor()

OK, thanks wysota. However, how can I set a dedicated
QAbstractItemDelegate for each (node) item type. I will have several
QAbstractItemDelegate and need a way to choose the right one based on the osg node contained in the item. Or, I can try to pass the item type to the delegate, but, how can I do this?

Regards

wysota
28th February 2013, 09:58
You don't set different delegates for different node types. When createEditor() is called, you receive the model index which you are about to edit. Based on that determine what node you are dealing with and create a proper editor for it.


...::createEditor(..., ..., index) {
switch(determineTypeFromIndex(index)) {
case someType: return new QLineEdit;
case someOtherType: return new SomeOtherTypeOfWidget;
// ...
}
}

olivier1978
28th February 2013, 11:13
You don't set different delegates for different node types. When createEditor() is called, you receive the model index which you are about to edit. Based on that determine what node you are dealing with and create a proper editor for it.


...::createEditor(..., ..., index) {
switch(determineTypeFromIndex(index)) {
case someType: return new QLineEdit;
case someOtherType: return new SomeOtherTypeOfWidget;
// ...
}
}

OK. But how can I retrieve the right QTreeWidgetItem? I really do not understand why QTreeWidget::itemFromIndex (http://qt-project.org/doc/qt-4.8/qtreewidget.html#itemFromIndex) is protected ... Does a workaround exists?


You don't set different delegates for different node types. When createEditor() is called, you receive the model index which you are about to edit. Based on that determine what node you are dealing with and create a proper editor for it.


...::createEditor(..., ..., index) {
switch(determineTypeFromIndex(index)) {
case someType: return new QLineEdit;
case someOtherType: return new SomeOtherTypeOfWidget;
// ...
}
}

OK. But how can I retrieve the right QTreeWidgetItem? I really do not understand why QTreeWidget::itemFromIndex (http://qt-project.org/doc/qt-4.8/qtreewidget.html#itemFromIndex) is protected ... Does a workaround exists?


You don't set different delegates for different node types. When createEditor() is called, you receive the model index which you are about to edit. Based on that determine what node you are dealing with and create a proper editor for it.


...::createEditor(..., ..., index) {
switch(determineTypeFromIndex(index)) {
case someType: return new QLineEdit;
case someOtherType: return new SomeOtherTypeOfWidget;
// ...
}
}

OK. But how can I retrieve the right QTreeWidgetItem? I really do not understand why QTreeWidget::itemFromIndex (http://qt-project.org/doc/qt-4.8/qtreewidget.html#itemFromIndex) is protected ... Does a workaround exists?


You don't set different delegates for different node types. When createEditor() is called, you receive the model index which you are about to edit. Based on that determine what node you are dealing with and create a proper editor for it.


...::createEditor(..., ..., index) {
switch(determineTypeFromIndex(index)) {
case someType: return new QLineEdit;
case someOtherType: return new SomeOtherTypeOfWidget;
// ...
}
}

OK. But how can I retrieve the right QTreeWidgetItem? I really do not understand why QTreeWidget::itemFromIndex (http://qt-project.org/doc/qt-4.8/qtreewidget.html#itemFromIndex) is protected ... Does a workaround exists?

Added after 6 minutes:


OK. But how can I retrieve the right QTreeWidgetItem? I really do not understand why QTreeWidget::itemFromIndex (http://qt-project.org/doc/qt-4.8/qtreewidget.html#itemFromIndex) is protected ... Does a workaround exists?

Seems that it does the trick:

QTreeWidgetItem *item = (QTreeWidgetItem*)index.internalPointer();
TreeViewItem* treeitem = dynamic_cast<TreeViewItem*>(item);
if (treeitem)
{
// ...
}

wysota
28th February 2013, 12:14
OK. But how can I retrieve the right QTreeWidgetItem?
In theory you shouldn't need to. You should put enough information in the item data to be able to operate on the data (e.g. determine the type) using solely QModelIndex::data(). And if you ask me, you shouldn't be using QTreeWidgetItem in the first place. Since you already have a data structure (OSG tree) you should implement a proper model around this. It will definitely pay back in future.


I really do not understand why QTreeWidget::itemFromIndex (http://qt-project.org/doc/qt-4.8/qtreewidget.html#itemFromIndex) is protected ...
Because there shouldn't be a need to extract the item pointer from an index outside the tree widget. QTreeWidget already provides item-based alternatives for all index-based signals and methods.


Does a workaround exists?
If you really need that, you can subclass the tree widget and create a public method that will call itemFromIndex.