Starting work with QTreeView, QAbstractItemModel
-
Hello.
I am having problems with forcing QAbstractItemModel to work with QTreeView. I am aiming to create a simple contact list, and to do it I try to implement a very basic functionalities and then to extend it - but I'm struggling even with it. The code is compiling but nothing shows up in the widget.
As a startpoint I chose Simple Tree example from "here":http://qt-project.org/doc/qt-4.8/itemviews-simpletreemodel.html .
I have changed the Item to contain only QString, but after adding items, nothing is presented - as if QTreeView didn't read any data from model.the code is as follows:
main.cpp
@#include <QtGui/QApplication>
#include <QTreeView>
#include <QDebug>
#include "rostermodel.h"
#include "rosteritem.h"int main(int argc, char *argv[])
{
QApplication a(argc, argv);QTreeView *view = new QTreeView; RosterItem *it = new RosterItem(QString("Kris")); RosterModel *model = new RosterModel(); model->addItem(it); it = new RosterItem(QString("Adam")); model->addItem(it); it = new RosterItem(QString("Sylvia")); model->addItem(it); view->setModel(model); view->show(); return a.exec();
}@
rosteritem.h
@class RosterItem
{
public:
RosterItem(QString name, RosterItem *parent=0);
~RosterItem();void appendChild(RosterItem *cont); RosterItem *child(int row); int childCount() const; int columnCount() const; QVariant data() const; int row() const; RosterItem *parent();
private:
QList<RosterItem*> childItems;
QString name;
RosterItem *parentItem;};@
rosteritem.cpp
@#include "rosteritem.h"RosterItem::RosterItem(QString nam, RosterItem *parent):
name(nam),parentItem(parent)
{
}RosterItem::~RosterItem()
{
qDeleteAll(childItems);
}void RosterItem::appendChild(RosterItem *cont)
{
childItems.append(cont);
}RosterItem* RosterItem::child(int row)
{
return childItems.value(row);
}int RosterItem::childCount() const
{
return childItems.size();
}int RosterItem::columnCount() const
{
return 1;
}QVariant RosterItem::data() const
{
return name;
}RosterItem* RosterItem::parent()
{
return parentItem;
}int RosterItem::row() const
{
if(parentItem)
{
return parentItem->childItems.indexOf(const_cast<RosterItem*>(this));
}
return 0;
}@rostermodel.h
@#include <QAbstractItemModel>
#include <QModelIndex>
#include "rosteritem.h"class RosterModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit RosterModel(QObject parent = 0);
~RosterModel();
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant data(const QModelIndex &index, int role) const;
void addItem(RosterItem item);
QModelIndex parent(const QModelIndex &child) const;
QModelIndex index(int row, int column, const QModelIndex &parent) const;
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant headerData(int section, Qt::Orientation orientation,
int role) const;private:
RosterItem *root;
};@rostermodel.cpp
@#include "rostermodel.h"RosterModel::RosterModel(QObject *parent) :
QAbstractItemModel(parent)
{
root=new RosterItem(QString("ROSTER"));
}RosterModel::~RosterModel()
{
delete root;
}Qt::ItemFlags RosterModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
QVariant RosterModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();if (role != Qt::DisplayRole) return QVariant(); RosterItem *item = static_cast<RosterItem*>(index.internalPointer()); return item->data();
}
void RosterModel::addItem(RosterItem *item)
{
root->appendChild(item);
}QVariant RosterModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
return root->data();
}QModelIndex RosterModel::parent(const QModelIndex &child) const
{
if (!child.isValid())return QModelIndex();RosterItem *childItem = static_cast<RosterItem*>(child.internalPointer()); RosterItem *parentItem = childItem->parent(); if (parentItem == root) return QModelIndex(); return createIndex(parentItem->row(), 0, parentItem);
}
QModelIndex RosterModel::index(int row, int column, const QModelIndex &parent)
const
{
if (!hasIndex(row, column, parent))
return QModelIndex();RosterItem *parentItem; if (!parent.isValid()) parentItem = root; else parentItem = static_cast<RosterItem*>(parent.internalPointer()); RosterItem *childItem = parentItem->child(row); if (childItem) return createIndex( row, column, childItem); else return QModelIndex();
}
int RosterModel::columnCount(const QModelIndex &parent) const
{
if(parent.isValid())return 1;
else return 0;
}int RosterModel::rowCount(const QModelIndex &parent) const
{
RosterItem *parentItem;
if (parent.column() > 0)
return 0;if (!parent.isValid()) parentItem = root; else parentItem = static_cast<RosterItem*>(parent.internalPointer()); return parentItem->childCount();
}
@Thanks in advance for any advices.
-
Hi lauku,
There were a few issues with your code:
-
Your columnCount() was always returning 0 (i.e. no columns) because you required a valid parent to return 1 and "root" has no valid parents...
-
None of your RosterItem's had a parent which meant that in your parent() function, when you call createIndex(), the first argument was invalid.
-
Your headerData() function didn't check the role for which data was requested so you would never have had a visible header:
I've corrected all these errors as shown below (see lines 8-10, 47-48 and 85-86 in rostermodel.cpp):
main.cpp
@
#include <QtGui/QApplication>
#include <QTreeView>
#include <QDebug>
#include "rostermodel.h"
#include "rosteritem.h"int main(int argc, char *argv[])
{
QApplication a(argc, argv);QTreeView *view = new QTreeView; RosterModel *model = new RosterModel(); view->setModel(model); view->show(); return a.exec();
}
@rostermodel.cpp
@
#include "rostermodel.h"RosterModel::RosterModel(QObject *parent) :
QAbstractItemModel(parent)
{
root=new RosterItem(QString("ROSTER"));root->appendChild(new RosterItem(QString("Kris"), root)); root->appendChild(new RosterItem(QString("Adam"), root)); root->appendChild(new RosterItem(QString("Sylvia"), root));
}
RosterModel::~RosterModel()
{
delete root;
}Qt::ItemFlags RosterModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
QVariant RosterModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();if (role != Qt::DisplayRole) return QVariant(); RosterItem *item = static_cast<RosterItem*>(index.internalPointer()); return item->data();
}
void RosterModel::addItem(RosterItem *item)
{
root->appendChild(item);
}QVariant RosterModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
if(orientation==Qt::Horizontal && role==Qt::DisplayRole) return root->data();
return QVariant();
}QModelIndex RosterModel::parent(const QModelIndex &child) const
{
if (!child.isValid())return QModelIndex();RosterItem *childItem = static_cast<RosterItem*>(child.internalPointer()); RosterItem *parentItem = childItem->parent(); if (parentItem == root) return QModelIndex(); return createIndex(parentItem->row(), 0, parentItem);
}
QModelIndex RosterModel::index(int row, int column, const QModelIndex &parent)
const
{
if (!hasIndex(row, column, parent))
return QModelIndex();RosterItem *parentItem; if (!parent.isValid()) parentItem = root; else parentItem = static_cast<RosterItem*>(parent.internalPointer()); RosterItem *childItem = parentItem->child(row); if (childItem) return createIndex( row, column, childItem); else return QModelIndex();
}
int RosterModel::columnCount(const QModelIndex &parent) const
{
if(parent.isValid()) return static_cast<RosterItem*>(parent.internalPointer())->columnCount();
return root->columnCount();
}int RosterModel::rowCount(const QModelIndex &parent) const
{
RosterItem *parentItem;
if (parent.column() > 0)
return 0;if (!parent.isValid()) parentItem = root; else parentItem = static_cast<RosterItem*>(parent.internalPointer()); return parentItem->childCount();
}
@Hope this helps ;o)
-