View Full Version : TreeWidget

17th February 2013, 08:48
Hi all,

I am trying to learn MVC within the Qt framework. So, to test, I am developping a small toy application. The idea is to display an OpenSceneGraph scene graph using a QTreeView. Thus, I have a good starting point using the "Editable Tree Model Example (http://qt-project.org/doc/qt-4.8/itemviews-editabletreemodel.html)". However, after doing a few changes, it appears that my QTreeView is empty. I do not understand why, but I am nearly sure that I am missing the way to insert the root item in the model. Could you please help me?

Basically the item and model are copy / paste of the example. I juste removed the setupModel method from the model and so, do not call it anymore from the constructor.


The visitor for all the nodes contained in the scene graph:


#include <osg/NodeVisitor>
#include <osg/Geode>
#include <osg/Drawable>

#include <string>

class QTreeView;
class q_osg_tree_item;

class osg_graph_info_visitor : public osg::NodeVisitor
osg_graph_info_visitor(QTreeView* view);

std::string spaces() { return std::string(_level*2, ' '); }

virtual void apply( osg::Node& node );
virtual void apply( osg::Geode& geode );

QTreeView* _view;
unsigned int _level;
q_osg_tree_item* _current_parent;


Its implementation:

#include "osg_graph_info_visitor.hpp"

#include <osg/PagedLOD>
#include <osg/Drawable>

#include <QAbstractItemModel>
#include <QTreeView>
#include <QModelIndex>

#include <iostream>

#include "q_osg_tree_item.hpp"
#include "q_osg_tree_model.hpp"

using namespace osg;
using namespace std;


osg_graph_info_visitor::osg_graph_info_visitor(QTr eeView* view) :
_current_parent = ((q_osg_tree_model*)(_view->model()))->root();
setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CH ILDREN);

void osg_graph_info_visitor::apply( Node& node )
cout << spaces() << "[Node - level " << _level << "] " << node.className() << " #parents --> " << node.getNumParents() << endl;

QVector<QVariant> data;
data.push_back( QVariant::fromValue(string(node.className())) );

_current_parent->insertChildren(_current_parent->childCount(), 1, 1 /*TODO*/);
for (int column = 0; column < data.size(); ++column)
cout << "ljifs" << endl;
_current_parent->child(_current_parent->childCount() - 1)->setData(column, data[column]);

traverse( node );

void osg_graph_info_visitor::apply( Geode& geode )
cout << spaces() << "[Geode - level " << _level << "] " << geode.className() << endl;

QVector<QVariant> data;
data.push_back( QVariant::fromValue(string(geode.className())) );

_current_parent->insertChildren(_current_parent->childCount(), 1, 1 /*TODO*/);
for (int column = 0; column < data.size(); ++column)
cout << "ljifsqmslksdmlks" << endl;
_current_parent->child(_current_parent->childCount() - 1)->setData(column, data[column]);

traverse( geode );

And this is from my GUI that I create the model and attache it to the view, and then call the visitor:

q_osg_treeview::q_osg_treeview(QWidget *parent) :
ui(new Ui::qosgtreeview)

QStringList headers;
headers << "Nodes";
_model = new q_osg_tree_model(headers, "");

_view = new QTreeView;


void q_osg_treeview::toolbutton_input_fileSelected(cons t QString& file)
QDir current_dir;
QSettings application_settings;
const QString DEFAULT_INPUT_DIR_KEY("default_input_dir");
application_settings.setValue(DEFAULT_INPUT_DIR_KE Y, current_dir.absoluteFilePath(file));

ref_ptr<Node> input = osgDB::readNodeFile( file.toStdString() );

osg_graph_info_visitor* v= new osg_graph_info_visitor(_view);

cout << ((q_osg_tree_model*)_view->model())->root()->childCount() << endl;

17th February 2013, 19:48
Well, the interesting thing would be the model, after all this is the interface to the data.

Btw, a tree model is the most complicated to implement. Maybe start with a QAbstractListModel as the base class first (just rowCount() and data() to implement), then change to a QAbstractTableModel (additionally requires columnCount()) and only get into a full tree model (by deriving from QAbstractItemModel, requires to also implement index(), parent(), etc) once you've got the two easier ones to work.