3

I am having trouble with showing items from a model defined in c++ in a SelectionDialog in qml. I'm trying to make an application for the Meego operating system.

If I display the items in a ListView, everything works as expected and the items are shown. However, if I try to show them in a SelectionDialog I get an empty list.

Here is some code:

languagemodel.h:

#ifndef LANGUAGEMODEL_H
#define LANGUAGEMODEL_H

#include <baza/language.h>
#include <QObject>
#include <QAbstractListModel>

class LanguageModel: public QAbstractListModel
{
    Q_OBJECT
public:
    enum LanguageRoles  {
        RoleLanguageName = Qt::DisplayRole,
        RoleLanguageCode = Qt::UserRole,
        RoleId = Qt::UserRole+1,
        RoleChosen = Qt::UserRole+2
    };

    LanguageModel(QObject *parent = 0);

    void addLanguge(const Language &language);
    void clear();

    int rowCount(const QModelIndex & parent = QModelIndex()) const;

    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;

private:
    QList<Language> m_languages;
};

#endif // LANGUAGEMODEL_H

languagemodel.cpp:

#include "languagemodel.h"
#include <QDebug>

LanguageModel::LanguageModel(QObject *parent)
    : QAbstractListModel(parent)
{
    QHash<int, QByteArray> roles;

    roles[RoleLanguageName]="name";
    roles[RoleLanguageCode]="code";
    roles[RoleId]="id";
    roles[RoleChosen]="chosen";

    setRoleNames(roles);
}

void LanguageModel::addLanguge(const Language &language){
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    m_languages << language;
    endInsertRows();
}

int LanguageModel::rowCount(const QModelIndex & parent) const  {
    return m_languages.count();
}

void LanguageModel::clear(){
    for (int i=0; i<m_languages.count(); i++)
    {
        beginRemoveRows(QModelIndex(), 0, 0);
        m_languages.removeAt(0);
        endRemoveRows();
    }
}

QVariant LanguageModel::data(const QModelIndex & index, int role) const  {
    if (index.row() < 0 || index.row() > m_languages.count())
        return QVariant();

    const Language &language = m_languages[index.row()];
    if (role == RoleLanguageName)
        return language.getName();
    else if (role == RoleLanguageCode)
        return language.getCode();
    else if (role == RoleChosen)
        return language.isChosen();
    else if (role == RoleId)
        return language.getId();

    return QVariant();
}

adding languages in done from handler.cpp like:

//(...)
for(unsigned int i = 0; i < listLanguages.size(); i++)
{
    Language language = listLanguages.at(i);

    modelLanguages.addLanguge(language);
}
//(...)
ctxt->setContextProperty("modelLanguages", &modelLanguages);

where modelLanguages is a LanguageModel.

And I would like to display the list in Settings.qml:

//(...)
SelectionDialog {
    id: dialogLanguages

    titleText: qsTr("Select language")
    model: modelLanguages
    delegate: Text  { text: name}
}

When I open the dialogLanguages, I can only see the title "Select language" without any of the items from the model.

If I use this as a model, it works fine:

model: ListModel {
    ListElement { name: "ListElement #1" }
    ListElement { name: "ListElement #2" }
    ListElement { name: "ListElement #3" }
}

Also, as I have already mentioned, if I set modelLanguages as a model in a ListView, al the items are displayed correctly.

can anyone help and tell me what am I doing wrong here and what do I have to change to get it working.

Any help is appreciated!

Thank you!

Bart
  • 19,692
  • 7
  • 68
  • 77
ppalasek
  • 372
  • 2
  • 12

1 Answers1

4

OK, I managed to solve it! I found a hint for the soultion here in the comments: https://qt.gitorious.org/qt-components/qt-components/merge_requests/887#

I needed to add a count property to my model inheriting QAbstractListModel.

My LanguageModel.h now looks something like this:

class LanguageModel: public QAbstractListModel
{
    Q_OBJECT

    Q_PROPERTY(int count READ count NOTIFY countChanged)

    //(...)
public:
    //(...)
    int count();
    //(...)
signals:
    void countChanged(int newCount);
    //(...)

I added the needed method in LanguageModel.cpp:

//(...)
int LanguageModel::count(){
    return m_languages.count();
}
//(...)

I also emitted a signal when the count changes (when adding languages and clearing the model) with:

 emit countChanged(m_languages.count());

And now it's working. :)

I hope this helps someone.

Bye!

ppalasek
  • 372
  • 2
  • 12
  • Just to mention, this worked correctly on the simulator. When I tried to run it on a real device (Nokia N9) I got an empty list. This is probably because the SelectionDialog.qml on the device is still buggy. To fix this, I made a MySelectionDialog.qml with the contents of the fixed SelectionDialog.qml which can be found here: [SelectionDialog.qml](https://qt.gitorious.org/qt-components/qt-components/blobs/87d135fa275415708be9d30f130ba26d9deb49b7/src/meego/SelectionDialog.qml). – ppalasek Dec 18 '11 at 11:25