1

I have following class:

#ifndef UEPEOPLEMODEL_H
#define UEPEOPLEMODEL_H

#include <QImage>
#include <QVariant>
#include <QStringList>
#include <QDebug>
#include <QHash>
#include <QByteArray>
#include <QtSql/QSqlError>
#include <QtSql/QSqlQueryModel>
#include <QtSql/QSqlRecord>
#include <QModelIndex>
#include <QQuickImageProvider>
#include <QHash>
#include <QByteArray>

#include "../settings/uedefaults.h"

class UePeopleModel : public QSqlQueryModel, QQuickImageProvider
{
    Q_OBJECT

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

    QVariant data(const QModelIndex &index,
                  int role) const Q_DECL_OVERRIDE;
    QImage image(const QString &id) const;
    QImage requestImage(const QString &id,
                        QSize *size,
                        const QSize &requestedSize);
    QHash<int, QByteArray> roleNames() const;

public:
    static const int UePersonNameRole=Qt::UserRole+1;
    static const int UePersonImageRole=UePersonNameRole+1;
};

#endif // UEPEOPLEMODEL_H

and its implementation:

#include "uepeoplemodel.h"

UePeopleModel::UePeopleModel(QObject* parent)
    : QSqlQueryModel(parent),
      QQuickImageProvider(QQmlImageProviderBase::Image,
                          QQmlImageProviderBase::ForceAsynchronousImageLoading)
{
    QSqlDatabase db;

    if(!QSqlDatabase::connectionNames().contains(UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE,
                                                 Qt::CaseInsensitive))
    {
            db=QSqlDatabase::addDatabase(UePosDatabase::DATABASE_DRIVER,
                                         UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE);
    }   // if

    db.setHostName(/*this->uePosSettings()->ueDbHostname()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_HOSTNAME);
    db.setDatabaseName(/*this->uePosSettings()->ueDbName()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_NAME);
    db.setUserName(/*this->uePosSettings()->ueDbUser()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_USERNAME);
    db.setPassword(/*this->uePosSettings()->ueDbPassword()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_PASSWORD);

    if(db.open())
    {
        this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE,
                       db);
    }
    else
    {
        qDebug() << db.lastError().text();
    }
}   // default constructor

UePeopleModel::~UePeopleModel()
{
}   // default destructor

QVariant UePeopleModel::data(const QModelIndex &index,
                             int role) const
{
    QVariant value=QSqlQueryModel::data(index,
                                        role);
    if(value.isValid())
    {
        switch(role)
        {
            case UePeopleModel::UePersonNameRole:
            {
                return value.toString();
            }   // case

            case UePeopleModel::UePersonImageRole:
            {
                return QString::number(index.row());
            }   // case

            default:
                value=QVariant();
        }   // switch
    }   // if

    return value;
}   // data

QImage UePeopleModel::image(const QString &id) const
{
    int iRow=id.toInt();
}   // image

QImage UePeopleModel::requestImage(const QString &id,
                                   QSize *size,
                                   const QSize &requestedSize)
{
    QImage image=this->image(id);

    *size = image.size();

    return image;
}   // requestImage

QHash<int, QByteArray> UePeopleModel::roleNames() const
{
    QHash<int, QByteArray> roles;

    roles.clear();
    roles.insert(UePeopleModel::UePersonNameRole,
                 "UePeopleModel::UePersonNameRole");
    roles.insert(UePeopleModel::UePersonImageRole,
                 "UePeopleModel::UePersonNameRole");

    return roles;
}   // roleNames

Now, If I try to build project, I get following error:

uepeoplemodel.o: In function UePeopleModel::roleNames() const': /home/markofr/projects/build-ueBlagajnaClient-Desktop_Qt_5_5_0_GCC_64bit-Debug/../ueBlagajnaClient/database/uepeoplemodel.cpp:86: undefined reference toUePeopleModel::UePersonNameRole' /home/markofr/projects/build-ueBlagajnaClient-Desktop_Qt_5_5_0_GCC_64bit-Debug/../ueBlagajnaClient/database/uepeoplemodel.cpp:88: undefined reference to `UePeopleModel::UePersonImageRole' Makefile:234: recipe for target 'ueBlagajnaClient' failed collect2: error: ld returned 1 exit status make: *** [ueBlagajnaClient] Error 1 10:22:57: The process "/usr/bin/make" exited with code 2. Error while building/deploying project ueBlagajnaClient (kit: Desktop Qt 5.5.0 GCC 64bit)

UePeopleModel::UePersonNameRole and UePeopleModel::UePersonImageRole are declared in header as public static int. Why am I getting this error? The error pops up introles.insert()statements insideroleNames()` method.

KernelPanic
  • 2,328
  • 7
  • 47
  • 90
  • 1
    Why don't you use an (possibly anonymous) enumeration for `UePersonNameRole` and `UePersonImageRole`? – Some programmer dude Aug 18 '15 at 08:32
  • 1
    Change ``UePeopleModel::UePersonNameRole`` to ``UePersonNameRole`` within your c++ file. Since its a static const member of your class you can access it without classname. For ''static const int'' an initialization in .h is fine – Sebastian Lange Aug 18 '15 at 08:37
  • @SebastianLange I did, same error! – KernelPanic Aug 18 '15 at 08:38
  • @SebastianLange Stil doesn't do anything about the declaration vs. definition problem the OP have. – Some programmer dude Aug 18 '15 at 08:43
  • 1
    The problem may be related to the second initialization having ``UePersonNameRole+1`` as initialization. You could try set it to ``Qt::UserRole + 2``. You can also spare the ``roles.clear()``. Since roleNames is not a static function the address for the static int's must already have been reserved (will be done latest on class instance if not defined out of class-definition). Remember to ``clean``,``qmake`` and (re)build. Sometimes you still keep a cache of previous compilations. – Sebastian Lange Aug 18 '15 at 08:45
  • @JoachimPileborg We use this static notation quite often. We only ran into problems (even with out of class definition) when having multiple static const* initializations within multiple file and crossreference (Static Initialization Order Idiom). – Sebastian Lange Aug 18 '15 at 08:48
  • @SebastianLange And that can be solved by having a single fixed *definition* in a source file. – Some programmer dude Aug 18 '15 at 08:50
  • @SebastianLange hmm, it does not work, I use `gcc (Ubuntu 4.9.2-10ubuntu13) 4.9.2` under Kubuntu. Are maybe some compiler parameters to add at build time, since according to C++ book I am looking into, this should work? – KernelPanic Aug 18 '15 at 08:52
  • @JoachimPileborg This current problem may be solved through this. The 4.9.2 @ kubuntu (ELF) probably behaves different than in MinGW 4.9.2, since this is where these kind of statements run just fine. The Static Initialization Order Idiom could not be solved even using that out of class definition. We had to fall back to a static function which would implement an on-demand allocation and return the values. – Sebastian Lange Aug 18 '15 at 09:02
  • @SebastianLange I've found out that there is not problem in `static const int` member declaration, but in function `roleNames()`, inside which I am inserting roles as: `UeTypeRoles UePeopleModel::roleNames() const { UeTypeRoles roles; roles.insert(UePeopleModel::ueRoleName, "UePersonNameRole"); roles.insert(UePeopleModel::ueRoleName, "UePersonImageRole"); return roles; } // roleNames` because function `insert` requests reference, not value itself. – KernelPanic Aug 20 '15 at 05:53

0 Answers0