Processing a QAbstractListModel in a QML Plugin



  • I extended QML and created a custom model deriving from QAbstractListModel. I have a few custom roles, ex: 'name'.

    MyModel.h

    @
    class MyModel : public QAbstractListModel
    {
    Q_OBJECT

    public:
    virtual int rowCount(const QModelIndex & parent = QModelIndex()) const;
    virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
    }
    @

    The model works fine when binding to a ListView and/or GridView.

    My Question: How do I create my own consumer of the QAbstractListModel? I want something similar to ListView's model property or GridView's model property. Except in my case, the model is not for Viewing but for back-end processing.

    ListView and GridView accept the model as a QVarient and then cast it to the model for processing. They do this by using private headers.

    Is it possible to consume a 'generic' list model without using private headers?

    I would like it to look something like this:

    Header
    @
    class Processor : public QDeclarativeItem {
    Q_OBJECT
    Q_PROPERTY(QVariant model READ getModel WRITE setModel);

    public:
    void setModel(const QVariant &model);
    QVariant getModel() const;
    @

    Implementation
    @
    ...

    void Processor::setModel(const QVariant &model)
    {

    QObject *object = qvariant_cast<QObject*>(model);
    
    // qDebug of object here is:  QVariant(QObject*, QDeclarativeListModel)
    
    QAbstractListModel *processor = qobject_cast<QAbstractListModel*>(object);
    
    // qDebug of processor here is QObject(0x0)  <-- not sure what I should be casting to
    
    for (int i = 0; i < processor->rowCount(); i++)
    {
        // back-end processing for each row
    }
    

    @



  • Do you want Processor to be able to handle all of the built-in QML model types, or just your own custom model type?

    If it is just your own custom type, you can make the property be of that type directly
    @Q_PROPERTY(MyModel model READ getModel WRITE setModel);@
    and you shouldn't need to deal with any casting.

    Dealing with all models is more difficult, since ListModel and XmlListModel aren't actually derived from QAbstractListModel, but the private QDeclarativeListModel (based on the itemviews-ng work). I can't see any way to work around this in the current release without using private headers; eventually the base model class should be public (we just aren't ready to commit to an API yet).



  • I wanted to be able to handle all model types, but I don't want to over complicate the code. I will use the the custom model and abstract my data binding lower in the software stack.

    Thanks for your quick response!



  • [quote author="mbrasser" date="1285647745"]

    If it is just your own custom type, you can make the property be of that type directly
    @Q_PROPERTY(MyModel model READ getModel WRITE setModel);@
    and you shouldn't need to deal with any casting.

    Dealing with all models is more difficult, since ListModel and XmlListModel aren't actually derived from QAbstractListModel, but the private QDeclarativeListModel (based on the itemviews-ng work). I can't see any way to work around this in the current release without using private headers; eventually the base model class should be public (we just aren't ready to commit to an API yet).

    [/quote]

    Well, I tried this approach with a descendant of QAbstractListModel, only to get the following error:

    qabstractitemmodel.h:361: error: 'QAbstractListModel& QAbstractListModel::operator=(const QAbstractListModel&)' is private

    So I overcame the copy constructor privateness alright by passing references around, but at this point it seems I am not allowed to do the last step, i.e. pass the model on to the QML as a Q_PROPERTY.

    Is there anything else I should be taking into account?
    Many thanks



  • I have the same problem:

    my custom component (a X,Y plotter who fetches the coordinates from a abstractlistmodel)
    @class Plotter : public QDeclarativeItem
    {
    Q_OBJECT
    Q_PROPERTY(DataContainer* coordinates READ getCoordinates WRITE setCoordinates NOTIFY coordinatesChanged)

    public:
    Plotter(QDeclarativeItem *parent=0);
    void paint(QPainter *painter, const QStyleOptionGraphicsItem item, QWidget widget=0);
    void setCoordinates(const DataContainer
    );
    DataContainer
    getCoordinates();
    signals:
    void coordinatesChanged();
    };@

    in main.qml
    @ Plotter{
    coordinates: myList
    }@

    I receive the error: " Unable to assign QObject* to void"

    any ideas?


Log in to reply
 

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