c++qtqvectorqproperty

Using QVector in Q_PROPERTY and accesing each data


I would like to update weekKm and weekTime to update automatically when I change any value in m_weekKmAndTime, but I am struggling with that. I would like to access it just like DbModel.weekKm(0), and have a value, not struggle with vars in QML and trying to get a value there.

.h:

Q_PROPERTY(QVector<QPair<int, int>> weekKmAndTime READ weekKmAndTime NOTIFY weekKmAndTimeChanged)
weekKm and weekTime are Q_INVOKABLE

.cpp:

QVector<QPair<int, int>> DataBaseModel::weekKmAndTime() const
{
    return m_weekKmAndTime;
}
int DataBaseModel::weekKm(int day) const
{
    return m_weekKmAndTime[day].first;
}
int DataBaseModel::weekTime(int day) const
{
    return m_weekKmAndTime[day].second;
}
void DataBaseModel::setWeek(QString day, int new_km, int new_time) {
    m_weekKmAndTime[returnNumberFromDay(day)] = qMakePair(new_km, new_time);
    qDebug() << new_km << " " << new_time;
    emit weekKmAndTimeChanged();
    emit weekKmChanged();//this on its own doesn't work
    emit weekTimeChanged();
}

Solution

  • Tried to figure out what do you want to achieve. Because I saw that you want to update individual components of the structure, I moved them into a separate class and not messing with QPair. Like this they have their own named properties and their notification signal can be connected to QML. I was lazy with the memory deallocation, so keep in mind that you need to do that.

    #ifndef DATABASEMODEL_H
    #define DATABASEMODEL_H
    
    #include <QObject>
    #include <QVector>
    #include <QDebug>
    
    class wkmt : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QVariant km READ km NOTIFY kmChanged)
        Q_PROPERTY(int time READ time NOTIFY timeChanged)
    public:
        explicit wkmt(int km, int time, QObject*parent=nullptr) : mKM{km}, mTime{time}, QObject{parent}
        {}
        int km() const { return mKM; }
        void setKM(int km)
        {
            if(mKM==km)return;
            mKM = km;
            emit kmChanged();
        }
    
        void setTime(int time)
        {
            if(mTime==time)return;
            mTime = time;
            emit timeChanged();
        }
    
        int time() const { return mTime; }
    
    signals:
        void kmChanged();
        void timeChanged();
    
    private:
        int mKM;
        int mTime;
    };
    
    class DataBaseModel : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QVector<wkmt*> weekKmAndTime READ weekKmAndTime NOTIFY weekKmAndTimeChanged)
    public:
        explicit DataBaseModel(QObject *parent = nullptr) : QObject{parent}
        {
            m_weekKmAndTime.push_back(new wkmt(0, 0));
            m_weekKmAndTime.push_back(new wkmt(0, 0));
            m_weekKmAndTime.push_back(new wkmt(0, 0));
            m_weekKmAndTime.push_back(new wkmt(0, 0));
            m_weekKmAndTime.push_back(new wkmt(0, 0));
            m_weekKmAndTime.push_back(new wkmt(0, 0));
            m_weekKmAndTime.push_back(new wkmt(0, 0));
            setWeek("Monday", 23, 99);
            setWeek("Tuesday", 23, 99);
            setWeek("Wednesday", 23, 99);
            setWeek("Thursday", 23, 99);
            setWeek("Friday", 23, 99);
            setWeek("Saturday", 23, 99);
            setWeek("Sunday", 23, 99);
        }
        QVector<wkmt*> weekKmAndTime() const
        {
            return m_weekKmAndTime;
        }
    
        int weekKm(int day) const
        {
            return m_weekKmAndTime[day]->km();
        }
    
        int weekTime(int day) const
        {
            return m_weekKmAndTime[day]->time();
        }
    
        Q_INVOKABLE void setWeek(QString day, int new_km, int new_time) {
            m_weekKmAndTime[returnNumberFromDay(day)] = new wkmt(new_km, new_time);
            emit weekKmAndTimeChanged();
        }
    
        int returnNumberFromDay(const QString& day)
        {
            QVector<QString> days;
            days << "Monday" <<  "Tuesday" << "Wednesday" << "Thursday" << "Friday" << "Saturday" << "Sunday";
            return days.indexOf(day);
        }
    
    signals:
        void weekKmAndTimeChanged();
    
    private:
        QVector<wkmt*> m_weekKmAndTime;
    };
    
    #endif // DATABASEMODEL_H
    

    QML code:

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Controls 2.12
    
    Window {
        width: 640
        height: 480
        visible: true
    
        Column {
            Column {
                Repeater {
                    model: dbModel.weekKmAndTime
                    delegate: Row {
                        Text {
                            text: "km: " + dbModel.weekKmAndTime[index].km
                        }
    
                        Text {
                            text: ", time: " + dbModel.weekKmAndTime[index].time
                        }
                    }
                }
            }
    
            Button {
                text: "Update Tuesday"
                onClicked: dbModel.setWeek("Tuesday", 88, 123);
            }
        }
    }
    

    The app looks like this and by pressing the button, it will update the second row (Tuesday)

    Test app