简体   繁体   中英

How can i use Model c++ class in cascade with 2 other repeater in .qml file

I have followed this tutorial : https://resources.qt.io/resources-by-content-type-videos-demos-tutorials/using-c-models-in-qml-tutorial

This was usefull to create my c++ class to manage my LightModel

Now I want to re-use this tutorial where I have a model inside 2 other repeaters in cascade. The issue is that my qml code instantiate LightModel objects inside repeaters so I don't have access to these instances from main.cpp

I used qmlRegisterType to give qml the ability to create several objects from my LightModel class.

main.cpp

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QApplication app(argc, argv);

    qmlRegisterType<Light>("Light",1,0,"Light");
    qmlRegisterType<LightModel>("Light", 1,0,"LightModel");
    qmlRegisterUncreatableType<Light>("Light", 1, 0, "LightList", QStringLiteral("LightList should not be created in QML"));

    QQmlApplicationEngine engine;

    MainWindow w;

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty())
        return -1;

    w.show();
    return app.exec();
}

light.h

#ifndef LIGHT_H
#define LIGHT_H

#include <QObject>
#include <QVector>


struct LightItem{
    QString description;
    int value;
    int bornInf;
    int bornSup;
    int decimals; //1, 10
    bool enabled;
};

class Light : public QObject
{
    Q_OBJECT
public:
    explicit Light(QObject *parent = nullptr);

    QVector<LightItem> items() const;

    bool setItemAt(int index, const LightItem &item);

signals:
    void preItemAppended();
    void postItemAppended();

    void preItemRemoved(int index);
    void postItemRemoved();


private:
    QVector<LightItem> mItems;
};

#endif // LIGHT_H

lightmodel.h

#ifndef LIGHTMODEL_H
#define LIGHTMODEL_H

#include <QAbstractListModel>

class Light;

class LightModel : public QAbstractListModel
{
    Q_OBJECT
    Q_PROPERTY(Light *list READ list WRITE setList)
    Q_PROPERTY(int ledMode READ getLedMode WRITE setLedMode)


public:
    explicit LightModel(QObject *parent = nullptr);

    enum{
        DescriptionRole = Qt::UserRole,
        ValueRole,
        BornInfRole,
        BornSupRole,
        Decimals,
        EnableRole
    };
    // Basic functionality:
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

    // Editable:
    bool setData(const QModelIndex &index, const QVariant &value,
                 int role = Qt::EditRole) override;

    Qt::ItemFlags flags(const QModelIndex& index) const override;

    virtual  QHash<int, QByteArray> roleNames() const override;



    Light *list() const;
    void setList(Light *list);

    int getLedMode() const;
    void setLedMode(int value);

private:

    Light *mList;
    int ledMode;
};

#endif // LIGHTMODEL_H

main.qml

StackLayout { 
    id: lampChose 
    currentIndex: gridLamps.indexImage
    Repeater { 
        id: repeater1 
        model: 24 
        StackLayout {
            id: lampStack
            currentIndex: tabBarNm.currentIndex 
            Repeater {
                id: repeater2
                model: 7 
                Column { 
                    id: columnSpinBoxtConfLeds
                    Repeater { 
                        id: repeaterParametersSpinBoxesLEDs 
                        model: LightModel { 
                            id: lightModel 
                            list: light } 
                        SpinBox { 
                            id: spinBoxTest 
                            visible: true 
                            editable: true 
                            value: model.value 
                            from: model.bornInf 
                            to: model.bornSup 
                            stepSize: 1
                            onValueChanged: {
                                model.value = value
                            }
                        } 
                    }
                } 
           }
     }
}

My LightModel class is implemented like ToDoModel in the tutorial exemple : https://github.com/mitchcurtis/todo-list-tutorial/tree/chapter-11

So the question is : how can I access from C++ the content of the LightModel objects because the 24x7 instances are created by .qml file.

Thanks a lot for your time

I've found the solution to my problem : stop using repeaters with StackLayout.

My editable content is stored inside an array, set as context property inside my main.cpp and the view get the value corresponding to the current index

light.h

#ifndef LIGHT_H
#define LIGHT_H

#include <QObject>

class LightV2 : public QObject
{
    Q_OBJECT

public:
    explicit LightV2(QObject *parent = nullptr);

public slots:

    Q_INVOKABLE int getArrayValue(int indexLamp, int indexLight, int indexField);
    Q_INVOKABLE int getBornInf(int indexLamp, int indexLight, int indexField);
    Q_INVOKABLE int getBornSup(int indexLamp, int indexLight, int indexField);
    Q_INVOKABLE int getDecimal(int indexLamp, int indexLight, int indexField);

    Q_INVOKABLE void setArrayValue(int indexLamp, int indexLight, int indexField, int value);

private:
    QString mDescription;
    int mValue;
    int mArrayValue[24][7][6];
    int mBornInf[24][7][6];
    int mBornSup[24][7][6];
    int mDecimal[24][7][6];
};

#endif // LIGHTV2_H

main.cpp

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QApplication app(argc, argv);
    qmlRegisterType<GeneralConf>("Light", 1,0, "GeneralConf");


    QQmlApplicationEngine engine;
    LightV2 lights;


    MainWindow w;
    engine.rootContext()->setContextProperty("lights", &lights);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty())
        return -1;

    w.show();
    return app.exec();
}

finally : solution in main.qml

Column {
            id: columnSpinBoxtConfLeds
            x:110
            y:0
            width:200
            spacing: 10

            Repeater {
                id: repeaterParametersSpinBoxesLEDs
                model: 6
                SpinBox {
                    id: spinBoxTest
                    property int decimals: lights.getDecimal(gridLamps.indexImage,tabBarNm.currentIndex, model.index);
                    property int decimalPresent:{
                        if (decimals == 10){
                            1
                        }
                        else{
                            0
                        }
                    }
                    width : 150
                    height: 25
                    focusPolicy: Qt.TabFocus

                    wheelEnabled: false
                    visible: true
                    editable: true

                    enabled: {
                        console.log("spinbox index:",model.index)
                        if (model.index == 2 || model.index == 3){
                            if(comboBoxMode.currentIndex >=1){
                                1
                            }
                            else{
                                0
                            }
                        }
                        else if (model.index >= 4){
                            if(comboBoxMode.currentIndex >=2){
                                1
                            }
                            else{
                                0
                            }
                        }
                        else{
                            1
                        }
                    }
                    value: lights.getArrayValue(gridLamps.indexImage,tabBarNm.currentIndex, model.index)
                    from : lights.getBornInf(gridLamps.indexImage,tabBarNm.currentIndex, model.index)
                    to : lights.getBornSup(gridLamps.indexImage,tabBarNm.currentIndex, model.index)
                    stepSize: 1

                    textFromValue: function(value, locale){
                        return Number(value / decimals).toLocaleString(locale, 'f',decimalPresent)
                    }
                    valueFromText: function(text,locale){
                        return Number.fromLocaleString(locale, text) * decimals
                    }

                    onValueChanged: {
                        lights.setArrayValue(gridLamps.indexImage,tabBarNm.currentIndex, model.index, value);
                        console.log(lights.getArrayValue(gridLamps.indexImage,tabBarNm.currentIndex, model.index));
                    }
                }

to conclude : this is how I managed to resolve my issue :

lights.getArrayValue(gridLamps.indexImage,tabBarNm.currentIndex, model.index)

and

lights.setArrayValue(gridLamps.indexImage,tabBarNm.currentIndex, model.index, value);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM