yak
yak

Reputation: 3930

Add my own object to QComboBox, Q_DECLARE_METATYPE, incomplete type 'QStaticAssertFailure<false>'

I need to add my own objects to QComboBox instead of just QStrings. Here's my own class, I need to add its objects to combo box:

#ifndef SERVICE_H
#define SERVICE_H

#include <QString>
#include <QMetaType>
#include <QVariant>
#include <QObject>

class Service : public QObject
{

    Q_OBJECT

public:
    Service(QString name, double price);
    Service(){ name = ""; price = 0;}

    QString getServiceName() const;
    void setServiceName(const QString &value);

    double getServicePrice() const;
    void setServicePrice(double value);

private:

    QString name;
    double price;
};

Q_DECLARE_METATYPE(Service)

#endif // SERVICE_H

#include "service.h"

Service::Service(QString name, double price)
{
    this->name = name;
    this->price = price;
}

QString Service::getServiceName() const
{
    return name;
}

void Service::setServiceName(const QString &value)
{
    name = value;
}

double Service::getServicePrice() const
{
    return price;
}

void Service::setServicePrice(double value)
{
    price = value;
}

And here's the piece of code, which sets up the combo box:

QVector<Service> services;
services.push_back(Service("Service 1", 100));
services.push_back(Service("Service 2", 150));

servicesComboBox = new QComboBox;
servicesComboBox->addItem("Service 1", QVariant::fromValue(services[0]));
servicesComboBox->addItem("Service 2", QVariant::fromValue(services[1]));
QObject::connect(servicesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(chooseService(int)));

Then, I have a slot, in which I would like to get the selected object, and let's say, save in database:

void ClientTab::chooseService(int index)
{
    QVariant v = servicesComboBox->itemData(index);
    Service *s = v.value<Service *>();
}

And the errors:

g++ -c -pipe -O2 -Wall -W -D_REENTRANT -fPIC -DQT_NO_DEBUG
-DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_SQL_LIB -DQT_CORE_LIB -I../TestApp -I. -I/opt/Qt/5.5/gcc_64/include -I/opt/Qt/5.5/gcc_64/include/QtWidgets -I/opt/Qt/5.5/gcc_64/include/QtGui -I/opt/Qt/5.5/gcc_64/include/QtSql -I/opt/Qt/5.5/gcc_64/include/QtCore -I. -I. -I/opt/Qt/5.5/gcc_64/mkspecs/linux-g++ -o clienttab.o ../TestApp/clienttab.cpp ../TestApp/clienttab.cpp: In member function 'void ClientTab::chooseService(int)': ../TestApp/clienttab.cpp:48:14: warning: unused variable 's' [-Wunused-variable]
     Service *s = v.value<Service *>();
              ^ In file included from /opt/Qt/5.5/gcc_64/include/QtGui/qwindowdefs.h:37:0,
                 from /opt/Qt/5.5/gcc_64/include/QtWidgets/qwidget.h:37,
                 from /opt/Qt/5.5/gcc_64/include/QtWidgets/QWidget:1,
                 from ../TestApp/clienttab.h:4,
                 from ../TestApp/clienttab.cpp:1: ../TestApp/service.h: In instantiation of 'void QVector<T>::append(const T&) [with T = Service]': /opt/Qt/5.5/gcc_64/include/QtCore/qvector.h:225:49:   required from 'void QVector<T>::push_back(const T&) [with T = Service]' ../TestApp/clienttab.cpp:22:65:   required from here /opt/Qt/5.5/gcc_64/include/QtCore/qobject.h:461:20: error: 'QObject::QObject(const QObject&)' is private
     Q_DISABLE_COPY(QObject)
                    ^ /opt/Qt/5.5/gcc_64/include/QtCore/qglobal.h:1042:5: note: in definition of macro 'Q_DISABLE_COPY'
     Class(const Class &) Q_DECL_EQ_DELETE;\
     ^ In file included from ../TestApp/clienttab.cpp:2:0: ../TestApp/service.h:9:7: error: within this context  class Service : public QObject
       ^ In file included from /opt/Qt/5.5/gcc_64/include/QtGui/qbrush.h:39:0,
                 from /opt/Qt/5.5/gcc_64/include/QtGui/qpalette.h:39,
                 from /opt/Qt/5.5/gcc_64/include/QtWidgets/qwidget.h:41,
                 from /opt/Qt/5.5/gcc_64/include/QtWidgets/QWidget:1,
                 from ../TestApp/clienttab.h:4,
                 from ../TestApp/clienttab.cpp:1: /opt/Qt/5.5/gcc_64/include/QtCore/qvector.h:605:23: note: synthesized method 'Service::Service(const Service&)' first required here 
         const T copy(t);
                       ^ In file included from /opt/Qt/5.5/gcc_64/include/QtGui/qwindowdefs.h:37:0,
                 from /opt/Qt/5.5/gcc_64/include/QtWidgets/qwidget.h:37,
                 from /opt/Qt/5.5/gcc_64/include/QtWidgets/QWidget:1,
                 from ../TestApp/clienttab.h:4,
                 from ../TestApp/clienttab.cpp:1: /opt/Qt/5.5/gcc_64/include/QtCore/qglobal.h:1043:12: error: 'QObject& QObject::operator=(const QObject&)' is private
     Class &operator=(const Class &) Q_DECL_EQ_DELETE;
            ^ /opt/Qt/5.5/gcc_64/include/QtCore/qobject.h:461:5: note: in expansion of macro 'Q_DISABLE_COPY'
     Q_DISABLE_COPY(QObject)
     ^ In file included from ../TestApp/clienttab.cpp:2:0: ../TestApp/service.h:9:7: error: within this context  class Service : public QObject
       ^ In file included from /opt/Qt/5.5/gcc_64/include/QtGui/qbrush.h:39:0,
                 from /opt/Qt/5.5/gcc_64/include/QtGui/qpalette.h:39,
                 from /opt/Qt/5.5/gcc_64/include/QtWidgets/qwidget.h:41,
                 from /opt/Qt/5.5/gcc_64/include/QtWidgets/QWidget:1,
                 from ../TestApp/clienttab.h:4,
                 from ../TestApp/clienttab.cpp:1: /opt/Qt/5.5/gcc_64/include/QtCore/qvector.h:612:23: note: synthesized method 'Service& Service::operator=(const Service&)' first required here 
             *d->end() = copy;
                       ^ make: *** [clienttab.o] Error 1

I'm using Qt 5.5 on Kubuntu 14.04 LTS.

Upvotes: 3

Views: 680

Answers (1)

Georgy Pashkov
Georgy Pashkov

Reputation: 1304

You are storing the items by value, but in the slot you are retrieving pointers to them. That's why it crashes. Also the Service class does not have a copy constructor (so I'm not sure why the Q_DECLARE_METATYPE even compiles). Copy constructor of QObject is private, so the default copy constructor for Service will not be generated by the compiler.

Changing initialisation code like this should work:

QVector<Service*> services;
services.push_back(new Service("Service 1", 100));
services.push_back(new Service("Service 2", 150));

Side note: you will also have to take care of deleting the instances of Service when you no longer need them. Since Serive derives from QObject, consider doing it via the parent-child relationship.

EDIT Also change the meta type declaration to use the pointer:

Q_DECLARE_METATYPE(Service*)

Upvotes: 2

Related Questions