PDA

View Full Version : Problem with TreeView



init2null
23rd May 2008, 02:18
Hello all,

I've been trying for hours to get this QTreeView / QAbstractItemModel code snippet to work with Qt4.4 and VC++ 2008 Express. When I expand the nested items twice, Qt fails with the assert "ASSERT: "i > -1" in file itemviews\qtreeview.cpp, line 3013". Am I doing something wrong?



#include <QtGui>
class TestModel;

class SceneTest : public QDialog {
public:
SceneTest();
protected:
QTreeView *tree;
TestModel *model;
};

class InternalItem {
public:
InternalItem() {
parent = NULL;
}
~InternalItem() {qDeleteAll(children);}
int row() {
if (parent) {
return parent->children.indexOf(this);
} else {
return 0;
}
}
InternalItem *append(InternalItem *iitem) {children.append(iitem); return (iitem->parent = this);}
InternalItem *parent;
QList < InternalItem * > children;
};

class TestModel : public QAbstractItemModel {
public:
TestModel();
QVariant data(const QModelIndex &index, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &) const;
protected:
InternalItem *root;
};

TestModel::TestModel() {
root = new InternalItem();
root->append(new InternalItem());
root->append(new InternalItem());
root->children[1]->append(new InternalItem());
root->children[1]->children[0]->append(new InternalItem());
root->children[1]->children[0]->children[0]->append(new InternalItem());
}

Qt::ItemFlags TestModel::flags(const QModelIndex &index) const {
return index.isValid() ? (Qt::ItemIsEnabled | Qt::ItemIsSelectable) : 0;
}

QVariant TestModel::data(const QModelIndex &index, int role) const {
if (!index.isValid() || index.column() >= 1)
return QVariant();
if (role == Qt::DisplayRole) {
InternalItem *iitem = static_cast < InternalItem * >(index.internalPointer());
if (index.column() == 0) {
return (long)iitem;
}
}
return QVariant();
}

QModelIndex TestModel::index(int row, int column, const QModelIndex &parent) const {
if (!hasIndex(row, column, parent)) {
return QModelIndex();
}
InternalItem *parentItem = NULL;
if (!parent.isValid()) {
parentItem = root;
} else {
parentItem = static_cast<InternalItem*>(parent.internalPointer());
}
InternalItem *child = parentItem->children[row];
if (child) {
return createIndex(row, column, child);
} else {
return QModelIndex();
}
}

QModelIndex TestModel::parent(const QModelIndex &index) const {
if (!index.isValid()) return QModelIndex();
InternalItem *iindex = static_cast < InternalItem * >(index.internalPointer());
if (!iindex->parent || iindex->parent == root) {
return QModelIndex();
} else {
return createIndex(iindex->row(), 0, iindex->parent);
}
}

QVariant TestModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (section == 0 && role == Qt::DisplayRole) {
return QString("A");
} else {
return QVariant();
}
}

int TestModel::rowCount(const QModelIndex &parent) const {
if (parent.column() > 0) return 0;
if (parent.isValid()) {
return static_cast < InternalItem * >(parent.internalPointer())->children.size();
} else {
return root->children.size();
}
}

int TestModel::columnCount(const QModelIndex &parent) const {
return 1;
}

SceneTest::SceneTest() : QDialog(NULL) {
model = new TestModel();
tree = new QTreeView(this);
tree->setModel(model);
QBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(tree);
}

patrik08
23rd May 2008, 15:24
Have a look on:
http://www.qtcentre.org/forum/f-qt-programming-2/t-modify-model-data-in-qtreeview-4182.html

MarkoSan
23rd May 2008, 15:45
Did you forget to setup Q_OBJECT macro in your classes?

init2null
23rd May 2008, 17:46
Markosan, I guess it's better to use Q_OBJECT on the model, but since I wasn't using signals yet, it wasn't really necessary. In any case, I tried it and received the same result.

init2null
23rd May 2008, 17:59
Hello Patrik, I'm not entirely sure how that post applies, since I really want to use the current design. I'm not really interested in editing either. My design is based on Qt's simpletreemodel example, so I know that I'm not too far away from working code.

patrik08
24th May 2008, 12:57
I dont say to swap design the file
http://ppk.ciz.ch/win_build/tree_cat_memo/Tree_Cat.zip
show only how to build a recursive function on model tree on XML
and other model to make the same on SQL or faster on sqlite3

if you have a recursive build model
you dont need this here ...



root->children[1]->append(new InternalItem());
root->children[1]->children[0]->append(new InternalItem());
root->children[1]->children[0]->children[0]->append(new InternalItem());


sql tree query

#define MINISQL_TREE_NO_LIMIT "SELECT n.*, round((n.rgt-n.lft-1)/2,0) AS childs, count(*)+(n.lft>1) AS level, ((min(p.rgt)-n.rgt-(n.lft>1))/2) > 0 AS lower, (( (n.lft-max(p.lft)>1) )) AS upper FROM catememo n, catememo p WHERE n.lft BETWEEN p.lft AND p.rgt AND (p.root_id = n.root_id) AND (p.id != n.id OR n.lft = 1) GROUP BY n.root_id,n.id ORDER BY n.root_id,n.lft"

structure

query.exec("create table catememo (id INTEGER PRIMARY KEY AUTOINCREMENT,root_id INTEGER,name varchar(110),lft INTEGER,rgt INTEGER,oldid INTEGER,xmlattribute BLOB)");

Or online demo:
http://www.klempert.de/nested_sets/demo/

init2null
25th May 2008, 05:55
I really don't think XML or databases would be useful, since I'm just trying to show the hierarchy of a QGraphicsScene for a fancy scene debugger I'm working on. The code you quoted was just there for debugging purposes, since it shows the bug. The model I wrote (not the test case in this post) can successfully show the hierarchy right now, except it crashes just like this example when it is expanded twice.

jpn
25th May 2008, 09:19
The problem seems to be in TestModel::parent():


return createIndex(iindex->row(), 0, iindex->parent);
// vs.
return createIndex(iindex->parent->row(), 0, iindex->parent);

init2null
25th May 2008, 09:56
That's it. Thank you! If and when my QGraphicsScene visualization tool becomes useful, I'll be sure to post it here.