Как правильно создать модель Qt

419
14 июня 2017, 02:49

В данном вопросе речь пойдет о QAbstractListModel, а точнее, о проблеме возникшей при использовании данного класса в MapItemView. Сразу перейдем к коду:

currentphotopointer.h

#include <QObject>
#include <QAbstractListModel>
class CurrentPoint
{
public:
    CurrentPoint(int track_id, double lat, double lon);
    int track_id() const;
    double lat() const;
    double lon() const;
    void track_id(int id);
    void lat(double lat);
    void lon(double lon);
private:
    int m_track_id;
    double m_lat;
    double m_lon;
};

class CurrentPhotoPointer : public QAbstractListModel
{
    Q_OBJECT
public:
    enum PointRoles {
        IdRole = Qt::UserRole + 1,
        LatRole,
        LonRole
    };
    CurrentPhotoPointer(QObject *parent = 0);

    Q_INVOKABLE void addPointer(int track_id, double lat, double lon);
    int rowCount(const QModelIndex & parent = QModelIndex()) const;
    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
protected:
    QHash<int, QByteArray> roleNames() const;
private:
    QList<CurrentPoint> m_points;
};

currentphotopointer.cpp

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

CurrentPoint::CurrentPoint(int track_id, double lat, double lon)
    : m_track_id(track_id), m_lat(lat), m_lon(lon)
{
}
int CurrentPoint::track_id() const
{
    return m_track_id;
}
double CurrentPoint::lat() const
{
    return m_lat;
}
double CurrentPoint::lon() const
{
    return m_lon;
}
void CurrentPoint::track_id(int id)
{
    this->m_track_id = id;
}
void CurrentPoint::lat(double lat)
{
    this->m_lat = lat;
}
void CurrentPoint::lon(double lon)
{
    this->m_lon = lon;
}
CurrentPhotoPointer::CurrentPhotoPointer(QObject *parent)
    : QAbstractListModel(parent)
{
}
void CurrentPhotoPointer::addPointer(int track_id, double lat, double lon)
{
    CurrentPoint * pointer = new CurrentPoint(track_id, lat, lon);


    bool isChange = false;
    for (int i = 0; i< m_points.size(); i++)
    {
        bool isExist = m_points.at(i).track_id() == track_id;
        if (isExist)
        {
            m_points[i].track_id(track_id);
            m_points[i].lat(lat);
            m_points[i].lon(lon);
            isChange = true;
            emit dataChanged(index(0, 0), index(rowCount(), 0));
            qDebug() << rowCount();
            qDebug() << "Изменен указатель. Трек: " << track_id << " Широта: " << lat << " " << m_points.size();
            QModelIndex index = createIndex(0, 0, static_cast<void *>(0));
            QModelIndex index2 = createIndex(rowCount(), 0, static_cast<void *>(0));
            emit dataChanged(index, index2);
            break;
        }
    }
    if(!isChange)
    {
        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        m_points << *pointer;
        endInsertRows();
        qDebug() << "Новый указатель. Трек: " << track_id << " Широта: " << lat << " " << m_points.size();
    }
}
int CurrentPhotoPointer::rowCount(const QModelIndex & parent) const {
    Q_UNUSED(parent);
    return m_points.count();
}
QVariant CurrentPhotoPointer::data(const QModelIndex & index, int role) const {
    qDebug() << index.row() << " " << index.column() << " " << role;
    if (index.row() < 0 || index.row() >= m_points.count())
        return QVariant();
    const CurrentPoint &point = m_points[index.row()];
    if (role == IdRole)
        return point.track_id();
    else if (role == LatRole)
        return point.lat();
    else if (role == LonRole)
        return point.lon();
    return QVariant();
}
QHash<int, QByteArray> CurrentPhotoPointer::roleNames() const {
    QHash<int, QByteArray> roles;
    roles[IdRole] = "track_id";
    roles[LatRole] = "lat";
    roles[LonRole] = "lon";
    return roles;
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "currentphotopointer.h"
int main(int argc, char *argv[])
{

    QGuiApplication app(argc, argv);
    CurrentPhotoPointer photoPointer;
    photoPointer.addPointer(0, 55.7463816, 37.55232);
    QQmlApplicationEngine engine;
    QQmlContext* ctx = engine.rootContext();
    ctx->setContextProperty("photoPointer", &photoPointer);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
    return app.exec();
}

main.qml

import QtQuick 2.6
import QtQuick.Window 2.2
import QtLocation 5.5
import QtPositioning 5.3
Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    Plugin {
        id: mapPlugin
        name: "osm"
    }
    Map {
        anchors.fill: parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(55, 45)
        zoomLevel: 5
        MapItemView {
            model: photoPointer
            MapQuickItem{
                coordinate {
                    latitude: 55
                    longitude: 45
                }
                anchorPoint.x: dronePointer.width / 2;
                anchorPoint.y: dronePointer.height / 2;
                sourceItem:
                    Column{
                        Image {id: dronePointer; source: "qrc:/plane.png"}
                    }
                MouseArea{
                    anchors.fill: parent
                    onClicked: {
                        photoPointer.addPointer(1, 55, 45)
                        console.log("Готово!")
                        //console.log("setPointer: " + "id: " + track_id + "lat: " + lat + "lon: " + lon )
                    }
                }
            }
        }
    }
}

Готовый проект для теста можно взять по ссылке

Дело вот в чем. Если попытаться скомпилировать проект, то мы получим ошибку

qrc:/main.qml:25 Cannot assign to non-existent default property

С другой стороны в официальной документации указано, что

This property holds the model that provides data used for creating the map items defined by the delegate. Only QAbstractItemModel based models are supported.

Не могу понять, что я делаю не так. Очевидно, что неверна реализация модели, но что пытается сделать MapQuickItem?

Примечательно то, что ListView и repeater отображают данный список!

READ ALSO
Ошибка компиляции в codeblocks

Ошибка компиляции в codeblocks

g++/Code::Blocks/Ubuntu Gnome При попытке компиляции из codeblocks указанного ниже кода вылетает ошибкаНо любопытен тот факт, что выполнение тех же команд...

325
Приоритет перегрузки операторов

Приоритет перегрузки операторов

Почему перегрузка операторов через методы класса приоритетней чем через функции?

202
Виртуальная статическая функция

Виртуальная статическая функция

Почему статическая функция не может быть виртуальной?

354