PDA

View Full Version : QAbstractListModel problem



UltimatePace
24th September 2008, 13:02
Just starting out with Qt Jambi 4.4 (2 days experience) but would consider myself an experienced C# programmer.

Trying to create an implementation of QAbstractListModel and display it in a QListView. After a search it appears I'm having similar problems to zlosynus (http://www.qtcentre.org/forum/f-qt-programming-2/t-something-fishy-about-model-data-doesnt-show-up-15211.html/?highlight=QAbstractListModel) and azdruid (http://www.qtcentre.org/forum/f-newbie-4/t-i-beg-your-assistance-qlistview-does-not-work-11181.html/?highlight=QAbstractListModel).

I've found that the model will display quite happily when used with setModel() on a QTableView but doing the same thing with a QListView.

Below is the implementation of the model, if anyone has any idea as to what the difference is between QListView and QTableView or if they can see any glaring problems with my code then that'd be great. I want to love Qt Jambi but can't quite yet while I see stuff like this!


public class FooListModel extends QAbstractListModel
{
private List<Foo> _data = new Vector<Foo>();

public FooListModel(List<Foo> data)
{
if (data == null)
{
return;
}

for (Foo foo : data)
{
_data.add(foo);
}

reset();
}

public Object data(QModelIndex index, int role)
{
if (index.row() < 0 || index.row() >= _data.size())
{
return new QVariant();
}

Foo foo = _data.get(index.row());

if (foo == null)
{
return new QVariant();
}

return foo;
}

public int rowCount(QModelIndex parent)
{
return _data.size();
}
}

An example of how I use the code:


Foo foo = new Foo();
foo.setName("Foo!");

List<Foo> data = new Vector<Foo>();
data.add(foo);

FooListModel fooListModel = new FooListModel(data);
fooListView.setModel(fooListModel);
fooTableView.setModel(fooListModel);

Thanks for your time...

caduel
24th September 2008, 13:58
handle the other roles in data(), too.
(i.e. return "new QVariant()" role != Qt::DisplayRole)

HTH

UltimatePace
24th September 2008, 15:20
Do you mean like this, or have I misunderstood something?


public Object data(QModelIndex index, int role)
{
if (role != Qt.ItemDataRole.DisplayRole)
{
return new QVariant();
}

if (index.row() < 0 || index.row() >= _data.size())
{
return new QVariant();
}

Foo foo = _data.get(index.row());

if (foo == null)
{
return new QVariant();
}

return foo.getName();
}

When I run with this code for the data method I only ever receive calls where role == 13 (which I make out to be Qt.ItemDataRole.SizeHintRole (http://doc.trolltech.com/qtjambi-4.4/html/constant-values.html#com.trolltech.qt.core.Qt.ItemDataRole. DisplayRole)).

Would you expect me to be receiving calls with a role value of 0? If so the fact that I'm not getting any may be pointing to a bigger problem...

caduel
24th September 2008, 15:35
Yes. (I don't have hands-on exp. with Jambi, so I can only guess at some details from a Qt/C++ perspective.)

Are you sure you don't have to return "new Object()"s instead of "new QVariant()"? (Just a guess.)

HTH

UltimatePace
24th September 2008, 15:55
The documentation (http://doc.trolltech.com/qtjambi-4.4/html/com/trolltech/qt/core/QAbstractItemModel.html#data(com.trolltech.qt.core .QModelIndex)) specifically mentions returning an empty QVariant rather than returning 0 so I'd hope it wouldn't be that.

Running the same code but using a QTableView instead calls with role values of 6, 7, 9, 10, 1, 0 and 8. I reckon it might actually be something weird going on with the QListView. I wonder if maybe the Jambi implementation requires me to trigger something that the QTableView doesn't?

Thanks for your help with this. I think it might be worth seeing whether I can contact the Qt developers and logging a bug report or something. I've managed to find myself a work-around for now, it's not ideal but it's not too clunky and just avoids the QListView control.

l8night
27th September 2009, 10:51
I had a very similar issue with QAbstractListModel in C++ (the code I tried was the same (but in C++)) I found a solution by looking at the source of QStringListModel.
my working C++ test class looks like:


class MyModel : public QAbstractListModel
{
public:
MyModel( QObject * parent ) : QAbstractListModel(parent) {}
int rowCount( const QModelIndex & parent ) const
{
// we are a list, so if there is a parent return 0 (see the Qt source of QStringListModel)
if (parent.isValid())
return 0;
return 4; // we have 4 rows
}

QVariant data( const QModelIndex & index, int role /* = Qt::DisplayRole*/ ) const
{
// if an invalid row, return empty QVariant
if (index.row() < 0 || index.row() >= 4)
return QVariant();

switch( role )
{
case Qt::DisplayRole:
case Qt::EditRole:
{
QString s;
s = QString("row [%1]").arg( index.row() );
return QVariant(s);
}
default:
return QVariant();
}
}
};

I believe that it is the 0 returned if the parent is valid from `rowCount` is what you need to do, if I just returned 4 in all cases I get no list displayed.
Hope this solves your issue.