PDA

View Full Version : Need help with QTreeView/QAbstractItemModel



Valheru
28th August 2006, 08:49
I'm developing an binary news reader. In the end I'm using an sqlite database to store the data in, but I'm first trying to get to grips with the model/view structure by using a simple QStringList to hold the data.
I'm subclassing the QAbstractItemModel to achieve all this, but I'm a bit lost. I did this once before in Java for a school assignment, but I can't remember much of it. At any rate, Qt's way of doing it has got me stumped.
I don't really understand what I'm doing, despite having read the relavent documentation and looking at the examples. What I have achieved works, except anything added to the string list doesn't show up in the tree view. It is added to the array, as you can see in the code I checked that using a QMessageBox.


/************************************************** *************************
* Copyright (C) 2006 by Lawrence Lee *
* valheru@facticius.net *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
************************************************** *************************/
#include <QHeaderView>
#include <QMessageBox>
#include "serverListModel.h"

serverListModel::serverListModel( QObject *parent )
{
p = parent;
}

serverListModel::~serverListModel()
{
}

QModelIndex serverListModel::index( int row, int column, const QModelIndex &parent ) const
{
return QModelIndex();
}

QModelIndex serverListModel::parent( const QModelIndex &index ) const
{
return QModelIndex();
}

int serverListModel::rowCount( const QModelIndex &parent ) const
{
return list.count();
}

int serverListModel::columnCount( const QModelIndex &parent ) const
{
if( p->objectName() == "serverTreeList" ){
return 1;
}
if( p->objectName() == "articleTreeList" ){
return 3;
}
}

QVariant serverListModel::data( const QModelIndex &index, int role ) const
{
return list.at( index.row() );
}

QVariant serverListModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
if( role != Qt::DisplayRole ){
return QVariant();
}else{
if( p->objectName() == "serverTreeList" ){
return QString( "Server List" );
}
if( p->objectName() == "articleTreeList" ){
return QString( "Article List" );
}
}
}

Qt::ItemFlags serverListModel::flags( const QModelIndex &index ) const
{
return Qt::ItemIsEnabled;
}


bool serverListModel::setData( const QModelIndex &index, const QVariant &value, int role )
{
list.replace(index.row(), value.toString());
emit dataChanged(index, index);
return true;
}

bool serverListModel::insertRows( int position, int rows, const QModelIndex &parent )
{
beginInsertRows( QModelIndex(), position, position + rows - 1 );
for( int row = 0; row < rows; ++row ){
list.insert(position, "");
}
endInsertRows();
return true;
}

bool serverListModel::removeRows( int position, int rows, const QModelIndex &parent )
{
beginRemoveRows( QModelIndex(), position, position + rows - 1 );
for( int row = 0; row < rows; ++row ){
list.removeAt(position);
}
endRemoveRows();
return true;
}

void serverListModel::addItem( const QString& item )
{
QModelIndex index;
beginInsertRows( index, 1, 1 );
list.insert(list.size(), item);
endInsertRows();
for( int i = 0; i < list.size(); i++ ){
QMessageBox *msg = new QMessageBox( "list", "list[" + QString::number(i) + "] = " + list[i],
QMessageBox::Information, QMessageBox::Ok, 0, 0 );
msg->exec();
}
}

If someone could take the time to explain how the whole model/view thing works wtih regards to the QModelIndex that passed to all the functions you have to reimplement I'd be much obliged, but I'd settle for knowing why my tree view doesn't reflect the changes made to the string list :)

wysota
28th August 2006, 09:47
You are doing many major errors here. I even started going through them explaining but then my browser crashed and I don't want to write that all again.

In short words:


you can't rely on the view in the model, the model is just a data representation, it shouldn't be tied to a view
if you want two different sets of data with different column count, use two separate instances of the model and make it possible for the model to operate on different number of columns
subclass a proper model, in your situation using QAbstractTableModel would be much better
you can't return invalid indexes only from the index() method as the whole model-view architecture relies on it, you should use createIndex() to return proper indexes
take a look at model examples provided with Qt, maybe it will put some more light on the subject
why don't you just use QStringListModel or QStandardItemModel instead of making an own model class? They exactly fit your needs.
the view doesn't show any changes probably because you forgot to emit proper signals (layoutChanged and dataChanged in proper places)

Valheru
28th August 2006, 10:30
I can't just use QStringListModel, since as I said I'm going to use a database to extract the information from. The QStringList is just a placeholder until I get to grasps with the Model/View structure.
Where should I emit the dataChanged() signal from?

wysota
28th August 2006, 12:48
You should emit dataChanged whenever the data of existing items change and layoutChanged whenever you add or remove items (or reorder them).

Valheru
28th August 2006, 14:46
Bah, I've been trying for a while now, and I can't figure out how to get the index() and parent() functions to work. Basically all I'm doing is reading a qstring returned from a qdailog and adding it to a qstringlist. How do I connect this to the QAbstractItemModel?

wysota
28th August 2006, 15:09
IMO your index() should look like so:


QModelIndex serverListModel::index( int row, int column, const QModelIndex &parent ) const {
return createIndex(row, column);
}

For parent and a "flat" (tabular) model you can always return QModelIndex() as all items have an invalid parent.