How to define a custom object as a role in QAbstractListModel?

Viewed 1528

My question is, that how can I specify a custom object as a role in a model derived from QAbstractListModel so when visualizing it within a ListView I can access its member variables. To have an example here is some simple code example:

This is my class representing my custom object:

class MyCustomObject {
  public:
    MyCustomObject(Qstring name, Qstring type);
    QString getName();
    QString getType();

  private:
    QString name;
    QString type;
};

This is how the overridden data() function looks like now (but it is not working) of my MyModel derived from QAbsractListModel:

QVariant MyModel::data(const QModelIndex &index, int role) const {
    if (index.row() < 0 || index.row() > m_atoms.count()) {
    //if (!index.isValid()) {
        return QVariant();
    }

    const MyData &data = m_data[index.row()];
    if(role == SomeRole) {
        return data.someString()
    }
    else if (role == MyCustomRole) {
        return data.myCustomObject; // How can I do this?
    }

    return QVariant();
}

Here I specify the role names in MyModel:

QHash<int, QByteArray> AtomModel::roleNames() const {
    QHash<int, QByteArray> roles;
    roles[SomeRole] = "someRole";
    roles[MyCustomRole] = "myCustomRole";

    return roles;
}

and this is how my ListView looks like in QML code with an example how I would like to access MyCustomObject member variables in the delegate:

ListView {
        width: 400
        height: 400

        model: myModel
        delegate: Text {
            text: "Type: " + myCustomRole.getType() + ", Name: " + myCustomRole.getName() + ", some string: " someRole

        }
    }

EDIT1: => fix needed copy constructor

When I am adding Q_DECLARE_METATYPE under my MyCustomObject I receive the following error:

call to implicitly-deleted copy constructor of `MyCustomObject`
in instantiation of member function 'QtMetaTypePrivate::QMetaTypeFunctionHelper<MyCustomObject, true>::Construct' requested here
in instantiation of function template specialization 'qRegisterNormalizedMetaType<MyCustomObject>' requested here QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Construct,
    return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy, defined);
in instantiation of function template specialization 'qRegisterMetaType<MyCustomObject>' requested here
Q_DECLARE_METATYPE(MyCustomObject)
expanded from macro 'Q_DECLARE_METATYPE'
#define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE)
expanded from macro 'Q_DECLARE_METATYPE_IMPL' 
      const int newId = qRegisterMetaType< TYPE >(#TYPE,
copy constructor of 'MyCustomObject' is implicitly deleted because base class 'QObject' has a deleted copy constructor
class MyCustomObject : public QObject
'QObject' has been explicitly marked deleted here Q_DISABLE_COPY(QObject)
expanded from macro 'Q_DISABLE_COPY'
       Class(const Class &) Q_DECL_EQ_DELETE;\

EDIT2:

So I have added all the necessary functions what @Evgeny has suggested. My code now compiles without errors, but I get a qml error on run time saying: TypeError: Property 'getType' of object QVariant(MyCustomObject) is not a function

I have added Q_INVOKABLE in front of the getType() method and I also deriving MyCustomObject class from public QObject. I have added Q_DECLARE_METATYPE at the bottom of my MyCustomObject header file. In the constructor of MyCustomObject I call qRegisterMetaType<MyCustomObject>("MyCustomObject") and in my main I register the class also like this qmlRegisterType<MyCustomObject>("com.test.mycustomobject", 1, 0, "MyCustomObject")

This is how MyCustomObject class looks like now:

class MyCustomObject : public QObject {
  public:
    MyCustomObject();
    MyCustomObject(Qstring name, Qstring type);
    MyCustomObject(const MyCustomObject& obj);
    ~MyCustomObject();
    Q_INVOKABLE QString getName();
    Q_INVOKABLE QString getType();

  private:
    QString name;
    QString type;
};
Q_DECLARE_METATYPE(MyCustomObject)

This is how the overridden data() function looks like now of my MyModel derived from QAbsractListModel:

QVariant MyModel::data(const QModelIndex &index, int role) const {
        if (index.row() < 0 || index.row() > m_atoms.count()) {
        //if (!index.isValid()) {
            return QVariant();
        }

        const MyData &data = m_data[index.row()];
        if(role == SomeRole) {
            return data.someString()
        }
        else if (role == MyCustomRole) {
            QVariant var; // this is the part, which has changed
            var.setValue(data.myCustomObject);
            return var;
        }

        return QVariant();
    }

All other functions which I have posted originally are the same.

1 Answers
Related