Error: 'qt_metatype_id' is not a member of 'QMetaTypeId<PlaylistModel>'



  • I subclassed QAbstractListModel and wanted to use an instance of the subclass in a qml-file.
    However I get the error:

    @error: 'qt_metatype_id' is not a member of 'QMetaTypeId<PlaylistModel>'@

    These are the headers of my subclass:

    @class PlaylistModel : public QAbstractListModel {
    Q_OBJECT
    public:
    enum PlaylistRoles {
    TrackRole = Qt::UserRole
    };

    PlaylistModel(QObject *parent = 0);
    
        void addTrack(const QString &trackName);
        int rowCount(const QModelIndex & parent = QModelIndex()) const;
        QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
    
    private:
         QStringList m_playlist;
    

    };
    @

    This is the source:

    @PlaylistModel::PlaylistModel(QObject *parent)
    : QAbstractListModel(parent)
    {
    QHash<int, QByteArray> roles;
    roles[TrackRole] = "track";
    setRoleNames(roles);
    }

    int PlaylistModel::rowCount(const QModelIndex & parent) const {
    return this->m_playlist.count();
    }

    QVariant PlaylistModel::data(const QModelIndex & index, int role) const {
    if (index.row() < 0 || index.row() > this->m_playlist.count())
    return QVariant();

    const QString &track = this->m_playlist[index.row()];
        return track;
    
    return QVariant();
    

    }

    void PlaylistModel::addTrack(const QString &trackName)
    {
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    //m_playlist.append(trackname);
    m_playlist << trackName;
    endInsertRows();
    }@

    and this the part where I instantiate it and set the context property for use in the qml-file:

    @ PlaylistModel playlistModel;
    playlistModel.addTrack("Item 1");
    playlistModel.addTrack("Item 2");

    context->setContextProperty("myModel", QVariant::fromValue(playlistModel));@
    

    What am I doing wrong?



  • Do you mean in a QML file rather than XML file? If so you need to add:

    @
    qmlRegisterType<PlaylistModel>( "MyComponents", 1, 0, "PlaylistModel" );
    @

    before you try to set the "myModel" context property. This just registers your custom type with the QML backend.

    You also need to add:

    @
    import MyComponents 1.0
    @

    to the QML file where you use it.



  • Yeah, I meant qml instead of xml.

    I added what you said but the error remains.

    I am using the model like this in my qml-file:

    @ TableView{

                            HeaderSection {
                                property: "track"
                                caption: "Track"
                                width: 200
    
                            }
    
                            model: myModel
                            width: 200
                            height: 100
    
                            itemDelegate: Rectangle {
                                     height: 25
                                     width: 100
                                     Text { text: track }
                                 }
                        }@
    

    This is a screenshot of the whole output of the error:
    http://img843.imageshack.us/img843/2239/qterror2.png



  • Ah sorry I missed a step. You also need to add:

    @
    Q_DECLARE_METATYPE( PlaylistModel* )
    @

    at the end of your model's header file which will let the metatype system know about pointers to your model.

    Then I just noticed that you expose the model incorrectly. Your code should look like this instead:

    @
    context->setContextProperty("myModel", &playListModel );
    @

    Although beware, your model is created on the stack and so wil be deleted when it goes out of scope at the end of that function. It would be better to add

    @
    PlayListModel* m_playListModel;
    @

    as a member of whatever class it is that exposes it to the qml side of things.



  • It compile now but the qml-part complains that:

    @qrc:/desktop-components/components/TableView.qml:278: TypeError: Result of expression 'root.model.get' [undefined] is not a function.@

    I set the context in the main-function so I should be alright but thanks for the tip.

    Here is the source of TableView.qml if it's needed:
    http://qt.gitorious.org/qt-components/desktop/blobs/master/components/TableView.qml

    EDIT: It works with a ListView, so I must be doing something wrong with the TableView:

    @ ListView{
    model: myModel
    width: 200
    height: 100
    delegate: Rectangle {
    height: 25
    width: 100
    Text { text: track }
    }
    }@



  • OK. I have never used TableView so I can't really help you with that. Maybe someone else here has experience with it? Does TableView ship with a demo that shows it's usage?



  • Here's the example which comes shipped with it:
    http://qt.gitorious.org/qt-components/desktop/blobs/master/examples/ModelView.qml

    The part which shows it's usage is this:

    @XmlListModel {
    id: flickerModel
    source: "http://api.flickr.com/services/feeds/photos_public.gne?format=rss2&tags=" + "Qt"
    query: "/rss/channel/item"
    namespaceDeclarations: "declare namespace media="http://search.yahoo.com/mrss/";"
    XmlRole { name: "title"; query: "title/string()" }
    XmlRole { name: "imagesource"; query: "media:thumbnail/@url/string()" }
    XmlRole { name: "credit"; query: "media:credit/string()" }
    }

    TableView{
        model: flickerModel
        anchors.fill: parent
    
        HeaderSection {
            property: "title"
            caption: "Title"
            width: 120
        }
        HeaderSection {
            property: "credit"
            caption: "Credit"
            width: 120
        }
        HeaderSection {
            property: "imagesource"
            caption: "Image source"
            width: 200
            visible: true
        }
     
    }
    

    @



  • The TableView is a completely new design I haven't actually tried it out on much code yet so I am eager to get feedback on it. Just providing a StringList is not enough since you have to tell the TableView what information to put in each column. The treeview in the example can also be populated like this:

    ListModel {
    ListElement{title:"a title" ; imageSource: "some source" ; caption: "a caption"
    ListElement{title:"a title" ; imageSource: "some source" ; caption: "a caption"
    }
    }

    But as you see, it is important that you provide the proper named property and assign a HeaderSection to show it in a column. If you have a c++ model you need to map this yourself. I believe you can look at the dirmodel used by the qmlviewer source code itself as an example. Note that I still have some performance issues when scrolling on large lists, so it doesn't scale too well at the moment. But I will work on this. Emphasis has been functionality and styling so far.



  • Thanks for jumping in on the discussion, Jens.

    The approach you've shown (via ListModel) works but how do I map any data-structures to create List-elements?

    I thought subclassing QAbstractListModel should work.



  • I googled a bit and found this blog. It seems to explain what you want:
    http://cdumez.blogspot.com/2010/11/how-to-use-c-list-model-in-qml.html


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.