Thursday 9 January 2014

Load data from C++ module in extensionplugin and show it on Qt ListView

This time the loaded data will be from C++ dynamic library instead of another qml file. It's more complex than previous article:
http://csfreebird.blogspot.com/2014/01/load-data-from-another-qml-file-and.html

My project folder tree looks as following:
/listview2$ tree
.
├── imports
│   └── mylist
│       ├── libmylist.so
│       └── qmldir
├── list2.pro
├── plugin.cpp
├── run.sh
└── test.qml
 The list2.pro file content is:
TEMPLATE = lib
CONFIG += plugin
QT += qml
DESTDIR = imports/mylist
TARGET  = mylist
SOURCES += plugin.cpp
qml.files = test.qml
qml.path += ./
pluginfiles.files += imports/mylist/qmldir
pluginfiles.path += imports/mylist
target.path += imports/mylist
INSTALLS += target qml pluginfiles
qmldir in module folder mylist is changed:
module mylist
plugin mylist
As a matter of convenience, I implement all C++ codes in one cpp file called plugin.cpp.
#include <QtQml/QQmlExtensionPlugin>
#include <QtQml/qqml.h>
#include <qdebug.h>
#include <qdatetime.h>
#include <qbasictimer.h>
#include <qcoreapplication.h>
#include <QAbstractItemModel>
#include <QStringList>
class People {
public:
  People(QString const & name, QString const & number)
    : name_(name), number_(number) {
  }
  QString name() const {
    return name_;
  }
  QString number() const {
    return number_;
  }
private:
  QString name_;
  QString number_;
};
class PeopleListModel : public QAbstractListModel {
  Q_OBJECT
public:
  enum PeopleRoles {
    NameRole = Qt::UserRole + 1,
    NumberRole
  };
  PeopleListModel(QObject * parent = 0)
    : QAbstractListModel(parent) {
    People p1("Dean", "186***");
    addPeople(p1);
    People p2("Crystal", "186***");
    addPeople(p2);
  }
  void addPeople(People const & p) {
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    values_ << p;
    endInsertRows();
  }
  int rowCount(QModelIndex const & parent = QModelIndex()) const {
    return values_.count();
  }
  QVariant data(QModelIndex const & index, int role = Qt::DisplayRole) const {
    if (index.row() < 0 || index.row() >= values_.count())
      return QVariant();
    People const & p = values_[index.row()];
    if (role == NameRole)
      return p.name();
    else if (role == NumberRole)
      return p.number();
    return QVariant();
  }
protected:
  QHash<int, QByteArray> roleNames() const {
    QHash<int, QByteArray> roles;
    roles[NameRole] = "name";
    roles[NumberRole] = "number";
    return roles;
  }
private:
  QList<People> values_;
};
class QExampleQmlPlugin : public QQmlExtensionPlugin {
  Q_OBJECT
  Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtension.PeopleListModel")
  public:
  void registerTypes(char const * uri) {
    qmlRegisterType<PeopleListModel>(uri, 1, 0, "PeopleListModel");
  }
};
#include "plugin.moc"
The People class is simple, just hold two properties: name and number.
The PeopleListModel class inherits from QAbstractListModel, it provides the data needed by ListView on Qml view.
The QExampleQmlPlugin is the plugin class, registers the exposed PeopleListModle class in it.
Pay attention to three methods from PeopleListModel: rowCount, data and roleNames. They are required by ListView.

To understand the Model-View architecture, please start with the following article:
http://doc-snapshot.qt-project.org/qdoc/model-view-programming.html#introduction-to-model-view-programming


No comments:

Followers

Contributors