Создание своей модели данных на основе QAbstractListModel
(релиз Qt SDK на момент написания данной статьи - 1.2.0)Предположим что вам необходимо разработать какую-то программу, которая в большинстве своём выводит списочные данные. Это может быть список загрузок, телефонная книга, аська и т. д.
В этой статье я вам расскажу как разработать свою модель данных, которую в другой статье мы сможем портировать в QML.
Будем мы разрабатывать телефонную книгу, в которой из контактов у нас есть имя, телефон и возраст. Ради большего интереса мы будем выводить возраст не числом, а возрастной шкалой (от 0 до 100 лет).
В соответствии с вступлением к книге Страуструпа по С++, представим наш контакт в виде класса:
class Contact { public: Contact(QString _name, QString _phone, uint _age) { name = _name; phone = _phone; age = _age; } void setName (QString _name) { name = _name; } void setPhone (QString _phone) { phone = _phone; } void setAge (uint _age) { age = _age; } QString getName() const { return name; } QString getPhone() const { return phone; } uint getAge() const { return age; } private: QString name; QString phone; uint age; };
т. е. в нашем классе у каждого контакта есть имя, телефон и возраст. Я не буду усложнять себе жизнь проверкой значений, а вы, если хотите, можете конечно же похимичить.
Следующим шагом мы создаём нашу модель на базе QAbstractListModel для которой определим конструктор и функцию добавления контактов в модель. Кроме того нам необходимо определить множество возможных полей модели. Для наглядности я их прокомментирую в коде дополнительно. Заголовочный файл нашей модели выглядит следующим образом:
#ifndef PHONEMODEL_H #define PHONEMODEL_H #include <QAbstractListModel> #include <QList> #include <QVariant> #include <QModelIndex> #include "contact.h" class PhoneModel : public QAbstractListModel { Q_OBJECT public: explicit PhoneModel(QObject *parent = 0); enum contactRolse { // множество возможных значений поля NameRole = Qt::DisplayRole, // заголовок для элемента модели ( для нас это имя контакта) PhoneRole = Qt::UserRole + 1, // номер телефона AgeRole = Qt::UserRole + 2 // возраст }; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; // функция доступа к данным int rowCount(const QModelIndex &parent) const; // количество элементов в модели public slots: void addContact(Contact ct); // добавить контакт в модель private: QList<Contact> contacts; // список контактов QHash<int, QByteArray> roles; // роли };#endif // PHONEMODEL_HОпределение этих методов выглядит следующим образом:
PhoneModel::PhoneModel(QObject *parent) : QAbstractListModel(parent) { roles[NameRole] = "name"; roles[PhoneRole] = "phone"; roles[AgeRole] = "age"; setRoleNames(roles); }
В данном консрукторе мы задаём значения полей для каждой роли.
Далее:
QVariant PhoneModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() > contacts.count()) return QVariant(); const Contact & ct = contacts[index.row()]; if (role == NameRole) return ct.getName(); else if (role == PhoneRole) return ct.getPhone(); else if (role == AgeRole) return ct.getAge(); return QVariant(); }
В данной функции мы возращаем значение выбранного поля по его имени, если такого имени поля нет, возвращаем пустой QVariant.
Функция добавления контакта - всё просто :) :
void PhoneModel::addContact(Contact ct) { contacts << ct; }
Функция возвращения количество строк данных в модели возвращает количество элементов списка:
int PhoneModel::rowCount(const QModelIndex &parent) const { return contacts.size(); }
Модель мы создали, осталось дело за малым: портировать её в QML и красивенько отобразить. Но об этом уже в следующей статье...
В конце конструктора у Вас вызывается метод setRoleNames(roles);
ОтветитьУдалитьЧто это за метод и из какого он класса?
Может позновато... В общем это метод в библиотеке версии 4.8.х, он задавал различные роли для производного классаю В 5.1, если не ошибаюсь, надо переопределить метод roleNames или что-то в этом духе.
ОтветитьУдалить