QML Combobox reports ReferenceError: modelData is

2019-06-06 12:53发布

I have following simple QML Combobox:

import QtQuick 2.0
import QtQuick.Controls 1.4

import si.mikroelektronika 1.0

Item
{
    id: ueStaffSelector

    width: 256
    height: 96

    ComboBox
    {
        model: uePeopleModel

        editable: false

        anchors.fill: parent
    }   // ComboBox
}   // Item

As you can see, I assign uePeopleModel to it, which is working ok already in app. Once the app is executed, I get following QML runtime errors:

file:///opt/QtOpenSource55/5.5/gcc_64/qml/QtQuick/Controls/ComboBox.qml:562: ReferenceError: modelData is not defined file:///opt/QtOpenSource55/5.5/gcc_64/qml/QtQuick/Controls/ComboBox.qml:562: ReferenceError: modelData is not defined file:///opt/QtOpenSource55/5.5/gcc_64/qml/QtQuick/Controls/ComboBox.qml:562: ReferenceError: modelData is not defined file:///opt/QtOpenSource55/5.5/gcc_64/qml/QtQuick/Controls/ComboBox.qml:562: ReferenceError: modelData is not defined file:///opt/QtOpenSource55/5.5/gcc_64/qml/QtQuick/Controls/ComboBox.qml:562: ReferenceError: modelData is not defined

Whole application is constructed in main.cpp:

#include <QtQml>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QTimer>

#include "database/uepeoplemodel.h"
#include "core/ueapplicationstatus.h"
#include "core/uedatabaseconnectionstatus.h"
#include "core/uebluetoothmanager.h"
#include "core/uebluetoothprinterconnectionstatus.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;

    UeApplicationStatus* ueApplicationStatus=new UeApplicationStatus(qApp);
    UePeopleModel* uePeopleModel=new UePeopleModel(qApp);
    UeBluetoothManager* ueBtManager=new UeBluetoothManager(qApp);

    QObject::connect(uePeopleModel,
                     SIGNAL(ueSignalDatabaseConnectionChanged(UeDatabaseConnectionStatus::UeTypeDatabaseConnectionStatus)),
                     ueApplicationStatus,
                     SLOT(ueSlotDatabaseConnectionChanged(UeDatabaseConnectionStatus::UeTypeDatabaseConnectionStatus)));

    QObject::connect(ueBtManager,
                     SIGNAL(ueSignalBtPrinterConnectionChanged(UeBluetoothPrinterConnectionStatus::UeTypeBluetootPrinterConnectionStatus)),
                     ueApplicationStatus,
                     SLOT(ueSlotBtPrinterConnectionChanged(UeBluetoothPrinterConnectionStatus::UeTypeBluetootPrinterConnectionStatus)));

    engine.rootContext()->setContextProperty("uePeopleModel",
                                             uePeopleModel);
    engine.rootContext()->setContextProperty("ueApplicationStatus",
                                             ueApplicationStatus);
    engine.rootContext()->setContextProperty("ueBtManager",
                                             ueBtManager);

    engine.addImageProvider(QLatin1String("uePeopleModel"),
                            uePeopleModel);

    qmlRegisterUncreatableType<UeDatabaseConnectionStatus>("si.mikroelektronika",
                                                           1,
                                                           0,
                                                           "UeTypeDatabaseConnectionStatus",
                                                           "Database Connection Status");

    qmlRegisterUncreatableType<UeBluetoothPrinterConnectionStatus>("si.mikroelektronika",
                                                                   1,
                                                                   0,
                                                                   "UeTypeBluetootPrinterConnectionStatus",
                                                                   "Bluetooth Printer Connection Status");

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    uePeopleModel->ueConnectToDatabase();
    ueBtManager->ueStartPairing();

    //ueApplicationStatus->ueUpdate(uePeopleModel->ueFetchUsers());

    return app.exec();
}

Here is also UePeopleModel header, file UePeopleModel.h:

#ifndef UEPEOPLEMODEL_H
#define UEPEOPLEMODEL_H

#include <QImage>
#include <QVariant>
#include <QStringList>
#include <QHash>
#include <QByteArray>
#include <QSqlError>
#include <QSqlQueryModel>
#include <QSqlRecord>
#include <QModelIndex>
#include <QQuickImageProvider>
#include <QByteArray>
#include <QSqlRecord>
#include <QSqlQuery>

#include "../settings/uedefaults.h"
#include "../core/uedatabaseconnectionstatus.h"
#include "../core/uetypes.h"
#include "../core/ueapplicationstatus.h"
#include "../core/ueuserrecord.h"

class UePeopleModel : public QSqlQueryModel,
                      public QQuickImageProvider
{
    Q_OBJECT

private:
    QSqlDatabase m_ueDb;

private:
    QSqlDatabase ueDatabase() const
        { return this->m_ueDb; }
    void ueSetDatabase(const QSqlDatabase& database)
        { this->m_ueDb=database; }
    QImage ueImage(const QString& id) const;

public:
    UePeopleModel(QObject *parent=0);
    ~UePeopleModel();

    QVariant data(const QModelIndex &index,
                  int role) const Q_DECL_OVERRIDE;
    QImage requestImage(const QString &id,
                        QSize *size,
                        const QSize &requestedSize);
    UeTypeRoles roleNames() const;
    void ueConnectToDatabase();
    UeTypeUsers* ueFetchUsers();

public:
    static const int ueRoleName=Qt::UserRole+1;
    static const int ueRoleImage=Qt::UserRole+2;
    static const int ueRolePassword=Qt::UserRole+3;

signals:
    void ueSignalDatabaseConnectionChanged(const UeDatabaseConnectionStatus::UeTypeDatabaseConnectionStatus& newStatus);
};

#endif // UEPEOPLEMODEL_H

and its implementation, file UePeopleModel.cpp:

#include "uepeoplemodel.h"

UePeopleModel::UePeopleModel(QObject* parent)
    : QSqlQueryModel(parent),
      QQuickImageProvider(QQmlImageProviderBase::Image,
                          QQmlImageProviderBase::ForceAsynchronousImageLoading)
{
    emit this->ueSignalDatabaseConnectionChanged(UeDatabaseConnectionStatus::NOT_CONNECTED);
}   // default constructor

UePeopleModel::~UePeopleModel()
{
    QString connName=this->ueDatabase().connectionName();

    this->ueDatabase().close();
    this->ueSetDatabase(QSqlDatabase());
    this->ueDatabase().removeDatabase(connName);

    emit this->ueSignalDatabaseConnectionChanged(UeDatabaseConnectionStatus::NOT_CONNECTED);
}   // default destructor

QVariant UePeopleModel::data(const QModelIndex &index,
                             int role) const
{
    switch(role)
    {
        case ueRoleImage:
        {
            return QString::number(index.row());
        } break;    // case

        case ueRoleName:
        {
            return this->record(index.row()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_NAME).toString();
        } break;    // case

        case ueRolePassword:
        {
            return this->record(index.row()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_APPPASSWORD).toString();
        } break;   // case

        default:
        {
            return QSqlQueryModel::data(index,
                                        role);
        } break;    // default
    }   // switch

    return QVariant();
}   // data

QImage UePeopleModel::ueImage(const QString &id) const
{
    return QImage::fromData(this->record(id.toInt()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_IMAGE).toByteArray(),
                            "PNG").scaled(UeDefaults::UeGraphics::PEOPLE_IMAGE_WIDTH,
                                          UeDefaults::UeGraphics::PEOPLE_IMAGE_HEIGHT,
                                          Qt::IgnoreAspectRatio,
                                          Qt::SmoothTransformation);
}   // ueImage

QImage UePeopleModel::requestImage(const QString &id,
                                   QSize *size,
                                   const QSize &requestedSize)
{
    Q_UNUSED(size)
    Q_UNUSED(requestedSize);

//    if(size)
//    {
//        *size=QSize(UeDefaults::UeGraphics::PEOPLE_IMAGE_WIDTH,
//                    UeDefaults::UeGraphics::PEOPLE_IMAGE_HEIGHT);
//    }   // if

    //return this->ueImage(id);

    return QImage::fromData(this->record(id.toInt()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_IMAGE).toByteArray(),
                            "PNG").scaled(UeDefaults::UeGraphics::PEOPLE_IMAGE_WIDTH,
                                          UeDefaults::UeGraphics::PEOPLE_IMAGE_HEIGHT,
                                          Qt::IgnoreAspectRatio,
                                          Qt::SmoothTransformation);
}   // requestImage

UeTypeRoles UePeopleModel::roleNames() const
{
    UeTypeRoles roles;

    const int iRoleName=UePeopleModel::ueRoleName;
    const int iRoleImage=UePeopleModel::ueRoleImage;
    const int iRolePassword=UePeopleModel::ueRolePassword;

    roles.insert(iRoleName,
                 "ueRoleName");
    roles.insert(iRoleImage,
                 "ueRoleImage");
    roles.insert(iRolePassword,
                 "ueRolePassword");

    return roles;
}   // roleNames

void UePeopleModel::ueConnectToDatabase()
{
    if(!QSqlDatabase::connectionNames().contains(UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE,
                                                 Qt::CaseInsensitive))
    {
        this->ueSetDatabase(QSqlDatabase::addDatabase(UePosDatabase::DATABASE_DRIVER,
                                                      UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE));
    }   // if

    this->ueDatabase().setHostName(UePosDatabase::UeDatabaseConnectionParameters::DATABASE_HOSTNAME);
    this->ueDatabase().setDatabaseName(UePosDatabase::UeDatabaseConnectionParameters::DATABASE_NAME);
    this->ueDatabase().setUserName(UePosDatabase::UeDatabaseConnectionParameters::DATABASE_USERNAME);
    this->ueDatabase().setPassword(UePosDatabase::UeDatabaseConnectionParameters::DATABASE_PASSWORD);

    if(this->ueDatabase().open())
    {
        this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE,
                       this->ueDatabase());
        emit this->ueSignalDatabaseConnectionChanged(UeDatabaseConnectionStatus::CONNECTED);
    }
    else
    {
        emit this->ueSignalDatabaseConnectionChanged(UeDatabaseConnectionStatus::NOT_CONNECTED);
    }   // if
}   // ueConnectToDatabase

UeTypeUsers* UePeopleModel::ueFetchUsers()
{
    UeTypeUsers* users=new UeTypeUsers();

    for(int iIndex=0; iIndex<this->record().count(); iIndex++)
    {
        users->append(new UeUserRecord(this,
                                       this->record(iIndex).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_ID).toString(),
                                       this->record(iIndex).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_NAME).toString(),
                                       this->record(iIndex).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_APPPASSWORD).toString()));
    }   // for

    return users;
}   // ueFetchUsers

Why am I getting this error?

1条回答
放我归山
2楼-- · 2019-06-06 13:24

You need to tell the combobox which role to use. Try adding textRole: "ueRoleName" to your ComboBox.

查看更多
登录 后发表回答