2

I'm creating a QList<> in C++ using a QML ListView to display it. The application runs without errors but the ListView stubbornly remains empty.

The QML will show a rectangle for the presence of each list item. I checked the UI code by creating a list in QML. It displays correctly for the QML created list.

Here's my QML:

import Processes 1.0
...
ListView {
    id: qInterfaceList
    height: parent.height;
    width: parent.width;
    model: myModel
    orientation: ListView.Vertical
    delegate:
        Rectangle {
            height: 30;
            width: 120;
            border.color: "red"
            border.width: 3
        }

The C++ code that creates and registers the list object:

// Register C++ classes as a QML type named Processes (version 1.0)
qmlRegisterType<Process>("Processes", 1, 0, "Process");

QQmlApplicationEngine engine;

// read the configuration file
Config conf;
if ( conf.read() )
{
    QQmlContext* ctxt = engine.rootContext();
    if ( ctxt )
    {
        qDebug()
            << "--- conf.Interfaces: "
            << conf.Interfaces.length()
            ;
        ConfigInterface c;
        QVariant v = QVariant::fromValue( conf.Interfaces );
        qDebug()
            << "--- ConfigInterface: "
            << v
            << "--- typeName: "
            << v.typeName()
            ;
        ctxt->setContextProperty("myModel", QVariant::fromValue( conf.Interfaces ));
    }
}

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

To debug I output information about list from C++ and QML: In C++ the count of list items is correct. In C++ the conversion to QVariant is working. In QML it sees the defined list.

The debugging output:

Debugging starts
--- conf.Interfaces:  65
--- ConfigInterface:  QVariant(QList<ConfigInterface*>, ) --- typeName:  QList<ConfigInterface*>
qml: myModel: QVariant(QList<ConfigInterface*>)
Debugging has finished

Any ideas what's wrong or how to debug this?

Thanks

EDIT: Here's the class being used as a list item

Class declaration:

class ConfigInterface : public QObject
{
    Q_OBJECT

    Q_PROPERTY(QString sql READ getTag WRITE setTag NOTIFY tagChanged)
    Q_PROPERTY(QString description READ getDescription WRITE setDescription NOTIFY descriptionChanged)
public:
    /*explicit*/ ConfigInterface();
    /*explicit*/ ConfigInterface(QObject *parent);
    ~ConfigInterface();

    // Copy constructor needed because these are copied when added to a QList
    ConfigInterface(const ConfigInterface &p2) {_tag = p2._tag; _description = p2._description; }

    QString getDescription() const;
    void setDescription(QString&);

    QString getTag() const;
    void setTag(QString&);

signals:
    void tagChanged(QString);
    void descriptionChanged(QString);

public:
    QString _tag;
    QString _description;
    QString QueryTemplate;
    QString ConnectString;
    QString MinimumId;
};

Q_DECLARE_METATYPE(ConfigInterface*)

C++ code:

ConfigInterface::ConfigInterface()
    : QObject( nullptr )
{
}

ConfigInterface::ConfigInterface(QObject* parent)
    : QObject(parent)
{
}

ConfigInterface::~ConfigInterface()
{
}

QString ConfigInterface::getTag() const
{
    return _tag;
}
void ConfigInterface::setTag(QString& str)
{
    _tag = str;
    emit tagChanged(_tag);
}
4
  • ConfigInterface is a class that inherits from QObject? Commented Jan 20, 2018 at 0:23
  • It is derived from QObject Commented Jan 20, 2018 at 5:22
  • You could show the ConfigInterface class. Commented Jan 20, 2018 at 8:12
  • Edited. The class code is shown at the bottom of the post. Thanks for helping :) Commented Jan 20, 2018 at 20:03

1 Answer 1

1

The main problem is caused because it has a list of ConfigInterface *, according to the examples provided in the documentation should be a list of QObject *:

class Config{
    [...]
public:
    QList<QObject *> Interfaces;
    [...]
};

In addition to this you should get the following warning:

/..../configinterface.h:17: warning: base class ‘class QObject’ should be explicitly initialized in the copy constructor [-Wextra]
     ConfigInterface(const ConfigInterface &p2) {_tag = p2._tag; _description = p2._description; }
     ^~~~~~~~~~~~~~~

This is caused because QObject and its derived classes must not have a copy constructor or assignment operator, For more information read the following:

Another improvement is that both constructors can be united in only one, in the end their class could have the following structure:

configinterface.h

#ifndef CONFIGINTERFACE_H
#define CONFIGINTERFACE_H

#include <QObject>

class ConfigInterface : public QObject
{
    Q_OBJECT

    Q_PROPERTY(QString sql READ getTag WRITE setTag NOTIFY tagChanged)
    Q_PROPERTY(QString description READ getDescription WRITE setDescription NOTIFY descriptionChanged)
public:
    ConfigInterface(QObject *parent=Q_NULLPTR);
    ~ConfigInterface();

    QString getTag() const;
    void setTag(const QString &tag);
    QString getDescription() const;
    void setDescription(const QString &description);

signals:
    void tagChanged(QString);
    void descriptionChanged(QString);

private:
    QString _tag;
    QString _description;
    QString QueryTemplate;
    QString ConnectString;
    QString MinimumId;
};

#endif // CONFIGINTERFACE_H

configinterface.cpp

#include "configinterface.h"

ConfigInterface::ConfigInterface(QObject* parent)
    : QObject(parent)
{
}

ConfigInterface::~ConfigInterface()
{
}

QString ConfigInterface::getDescription() const
{
    return _description;
}

void ConfigInterface::setDescription(const QString &description)
{
    if(_description == description)
        return;
    emit descriptionChanged(description);
    _description = description;
}

QString ConfigInterface::getTag() const
{
    return _tag;
}

void ConfigInterface::setTag(const QString &tag)
{
    if(tag == _tag)
        return;
    emit tagChanged(tag);
    _tag = tag;
}
Sign up to request clarification or add additional context in comments.

4 Comments

My class is derived from QObject. The Qt examples show a QList of derived objects being used as a QML model. The docs for Q_DECLARE_METATYPE say "Any class or struct that has a public default constructor, a public copy constructor, and a public destructor can be registered". That conflicts with your statement I shouldn't have a copy constructor. I'm dubious but I'll certainly try your code.
@Jay If the class inherits from QObject it is not necessary to use Q_DECLARE_METATYPE, also check this question stackoverflow.com/questions/47803531/…
@Jay The complete example of my test can be found in github.com/eyllanesc/stackoverflow/tree/master/48349672
Woot! Thank you for all the effort. I'd give you two upvotes if I could

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.