0

I created a ListView and I want to use it with a custom DataModel. However, I have a problem: at the moment the view gets created, I don't have the data loaded into the model. The model data is set after the view is created and when I set the data onto the model, the view doesn't update and doesn't read again the model data. This is my ListView:

ListViewCountainer.qml

Container {
    // countryModelData is set after ListViewCountainer gets created 
    // when countryModelData gets set, the model is populated with data
    property variant countryModelData

    leftPadding: 20.0
    rightPadding: 20.0
    topPadding: 20.0
    bottomPadding: 20.0

    CountryDetailsListView {
        id: countryDetailsListView

        dataModel: CountryDataModel {
            countryData: countryModelData
        }
    }
}

And here is my model:

countrydatamodel.h

#ifndef COUNTRYDATAMODEL_H_
#define COUNTRYDATAMODEL_H_

#include <QtCore/QAbstractListModel>
#include <QtCore/QList>
#include <QObject>
#include <QtCore/QVariant>

#include <bb/cascades/DataModel>
#include <bb/data/JsonDataAccess>

class CountryDataModel : public bb::cascades::DataModel
{
    Q_OBJECT

    Q_PROPERTY(QVariant countryData READ getCountryData WRITE setCountryData)

public:
    CountryDataModel(QObject* parent = 0);
    virtual ~CountryDataModel();

    Q_INVOKABLE int childCount(const QVariantList& indexPath);
    Q_INVOKABLE QVariant data(const QVariantList& indexPath);
    Q_INVOKABLE bool hasChildren(const QVariantList& indexPath);
    Q_INVOKABLE QString itemType(const QVariantList& indexPath);
    Q_INVOKABLE void removeItem(const QVariantList& indexPath);

    Q_INVOKABLE QVariant getCountryData();
    Q_INVOKABLE void setCountryData(QVariant data);

private:
    QVariantList m_elements;
};

#endif /* COUNTRYDATAMODEL_H_ */

countrydatamodel.cpp

#include <src/countrydatamodel.h>

#include <QtCore/QtAlgorithms>
#include <QtCore/QDebug>

#include <bb/cascades/DataModel>
#include <bb/data/JsonDataAccess>

CountryDataModel::CountryDataModel(QObject* parent) : bb::cascades::DataModel(parent)
{
}

CountryDataModel::~CountryDataModel()
{
}

bool CountryDataModel::hasChildren(const QVariantList &indexPath)
{
    qDebug() << "==== CountryDataModel::hasChildren" << indexPath;

    if ((indexPath.size() == 0))
    {
        return true;
    }
    else
    {
        return false;
    }
}

int CountryDataModel::childCount(const QVariantList &indexPath)
{
    qDebug() << "==== CountryDataModel::childCount" << indexPath;

    if (indexPath.size() == 0)
    {
        qDebug() << "CountryDataModel::childCount" << m_elements.size();

        return m_elements.size();
    }

    qDebug() << "==== CountryDataModel::childCount" << 0;

    return 0;
}

QVariant CountryDataModel::data(const QVariantList &indexPath)
{
    qDebug() << "==== CountryDataModel::data" << indexPath;

    if (indexPath.size() == 1) {

        return m_elements.at(indexPath.at(0).toInt());
    }

    QVariant v;
    return v;
}

QString CountryDataModel::itemType(const QVariantList &indexPath)
{
    Q_UNUSED(indexPath);

    return "";
}

void CountryDataModel::removeItem(const QVariantList& indexPath)
{
    if(indexPath.size() == 1) {
        m_elements.removeAt(indexPath.at(0).toInt());
    }

    emit itemRemoved(indexPath);
}

QVariant CountryDataModel::getCountryData()
{
    return QVariant(m_elements);
}

void CountryDataModel::setCountryData(QVariant data)
{
    m_elements = data.toList();

    qDebug() << "================== CountryDataModel: " << m_elements;
}

I put some debug messages in the childCount function for example and it gets called only once, which means that the ListView asks the model for the data just once, when the model is created.

Is it possible to force ListView to read again the data from the model after the model gets populated with data? Or how could I make this approach work and load the data in the view?

Thanks!

Jacob Krieg
  • 2,834
  • 15
  • 68
  • 140

2 Answers2

1

In order for the model to be updated, the setCountryData member function needs to be updated like so:

void CountryDataModel::setCountryData(QVariant data)
{
    m_elements = data.toList();

    emit itemsChanged(bb::cascades::DataModelChangeType::AddRemove, QSharedPointer< bb::cascades::DataModel::IndexMapper >(0));
}

FML...

Jacob Krieg
  • 2,834
  • 15
  • 68
  • 140
-2

You need to declare a signal for the property you want to update in backend.

Q_PROPERTY(QVariant countryData READ getCountryData WRITE setCountryData NOTIFY contryDataChanged)

add its declaration as well.

Then you say -

emit contryDataChanged();

wherever you feel like list should re-read contents. (normally setter methods).

essbeev
  • 255
  • 2
  • 7