issue with row in a tableview



  • Hello
    I'm trying to build a GUI to download multiple elements from a distant server.
    I managed to create my model, display it, added all the selectionmode options...but have issues when trying to retrieve the data from the model.
    Here is the code :
    the model :

    SiteListModel
            {
                id: listeSiteDistantsId
                Component.onCompleted: listeSiteDistantsId.loadRemoteSites(loadall,name,reference,ville,departement)
            }
    

    It loads my model, no issue on this part

    here is the GUI :

    ColumnLayout
            {
                id: resultfieldId
                width: 480
                RowLayout
                {
                    TableView
                    {
                        id: tableOfSites
                        anchors.centerIn: parent
                        Layout.minimumWidth: downloadSiteFormId.width
                        Layout.maximumWidth: downloadSiteFormId.width
                        Layout.maximumHeight: 3*downloadSiteFormId.height/4
                        Layout.minimumHeight: 3*downloadSiteFormId.height/4
                        model: listeSiteDistantsId
                        alternatingRowColors: false
                        selectionMode: SelectionMode.MultiSelection
                        TableViewColumn
                        {
                            role: "label"
                            title : qsTr("Nom")
                            width: downloadSiteFormId.width/4
                        }
                        TableViewColumn
                        {
                            role: "reference"
                            title : qsTr("RefSmartC")
                            width: downloadSiteFormId.width/4
                        }
                        TableViewColumn
                        {
                            role: "ville"
                            title : qsTr("Ville")
                            width: downloadSiteFormId.width/4
                        }
                        TableViewColumn
                        {
                            role: "departement"
                            title : qsTr("Département")
                            width: downloadSiteFormId.width/4
                        }
                        itemDelegate: Text {
                                        color:  listeSiteDistantsId.isLock(styleData.row) ? "red" : "black"
                                        text: styleData.value
                        }
                    }
                }
                RowLayout
                {
                    Button
                    {
                        id: startDownloadId
                        Layout.minimumWidth: downloadSiteFormId.width / 6
                        Layout.minimumHeight: downloadSiteFormId.height / 10
                        Layout.leftMargin: 5*downloadSiteFormId.width / 12
                        enabled: (tableOfSites.selection.count ===0)? false : true
                        Text
                        {
                            text: qsTr("Télécharger")
                            verticalAlignment: Text.AlignVCenter
                            horizontalAlignment: Text.AlignHCenter
                            anchors.fill: parent
                            font.family: "Verdana"
                            font.pointSize: 12
                        }
                        onClicked: {
                            tableOfSites.selection.forEach(function(rowIndex){
                                labelSite=listeSiteDistantsId.getLabel(rowIndex)
                                if (listeSiteDistantsId.isLock(rowIndex))
                                {
                                    NotificationListModel.add (qsTr(labelSite + ' est bloqué car il a été téléchargé récemment'))
                                    progressId.visible = false
                                    backButton.visible = true
                                }
                                else
                                {
                                    progressId.visible = true
                                    backButton.visible = false
                                    listeSiteDistantsId.loadFromRemoteDatabase(listeSiteDistantsId.getPkSite(rowIndex))
                                }
                            })
                        }
                    }
                }
            }
    

    I thought the issue was with the forEach, but in fact, after trying to add the color change on the view, it occures to me that the row could not be setted...So I added a debug in the isLock method.

    bool SiteListModel::isLock(const QModelIndex & index)
    {
        if (!index.isValid())
        {
            qDebug() << "isLock index error : "<<index.row();
            return false;
        }
        if (index.row() < 0 || index.row() >= m_SiteList.count())
        {
            qDebug() << "isLock range error : "<<index.row();
            return false;
        }
        const SiteListObject& siteDistant = m_SiteList[index.row()];
        qDebug() << "isLock";
        return siteDistant.lock();
    }
    

    And indeed, it occures that the value is -1

    I feel I'm close...but can't put my finger on the issue...
    Thank you for reading and if you have any tips...



  • @the-moebius
    Try to use isLock value like another role. So:

    QVariant YourModel::data(const QModelIndex &index, int role) const
    {
        if(!index.isValid())
            return QVariant();
    
        switch(role)
        {
    
        // ...
        case IS_LOCK:
            return m_SiteList[index.row()].lock();
        // ...
        }
    
        return QVariant();
    }
    

    And in TableView change itemDelegate to:

    itemDelegate: Text {
                color:  model.isLock ? "red" : "black"
                text: styleData.value
            }
    


  • I've tried your solution, but it isn't trigering the data method.
    I add the full model and the full GUI :

    form.qml:

    import QtQuick 2.4
    import QtQuick.Controls 1.3
    import QtQuick.Controls.Styles 1.3
    import QtQuick.Layouts 1.1
    import QtPositioning 5.4
    import QtQuick.Dialogs 1.2
    import com.ecometering.tablet 1.0
    
    Rectangle
    {
        id: downloadSiteFormId
        radius:5
        color: "lightgrey"
        visible:true
        width: parent.width
        height: parent.height
        border.width: 1
    
        property bool loadall:false;
        property string name: "";
        property string reference: "";
        property string ville: "";
        property string departement: "";
        property int selected: 0;
        property string labelSite:"";
    
        Component.onCompleted:
        {
            titlesStackId.newTitle(qsTr("Téléchargement d'un site"))
    
        }
        SiteListModel
        {
            id: listeSiteDistantsId
            Component.onCompleted: listeSiteDistantsId.loadRemoteSites(loadall,name,reference,ville,departement)
        }
    
        Component.onDestruction:
        {
            titlesStackId.restoreLast()
        }
        ColumnLayout
        {
            id: resultfieldId
            width: 480
            RowLayout
            {
                TableView
                {
                    id: tableOfSites
                    anchors.centerIn: parent
                    Layout.minimumWidth: downloadSiteFormId.width
                    Layout.maximumWidth: downloadSiteFormId.width
                    Layout.maximumHeight: 3*downloadSiteFormId.height/4
                    Layout.minimumHeight: 3*downloadSiteFormId.height/4
                    model: listeSiteDistantsId
                    alternatingRowColors: false
                    selectionMode: SelectionMode.MultiSelection
                    TableViewColumn
                    {
                        role: "label"
                        title : qsTr("Nom")
                        width: downloadSiteFormId.width/4
                    }
                    TableViewColumn
                    {
                        role: "reference"
                        title : qsTr("RefSmartC")
                        width: downloadSiteFormId.width/4
                    }
                    TableViewColumn
                    {
                        role: "ville"
                        title : qsTr("Ville")
                        width: downloadSiteFormId.width/4
                    }
                    TableViewColumn
                    {
                        role: "departement"
                        title : qsTr("Département")
                        width: downloadSiteFormId.width/4
                    }
                    itemDelegate: Text {
                                    color:  listeSiteDistantsId.lock ? "red" : "black"
                                    text: styleData.value
                    }
    
    
                }
            }
            RowLayout
            {
                Button
                {
                    id: startDownloadId
                    Layout.minimumWidth: downloadSiteFormId.width / 6
                    Layout.minimumHeight: downloadSiteFormId.height / 10
                    Layout.leftMargin: 5*downloadSiteFormId.width / 12
                    enabled: (tableOfSites.selection.count ===0)? false : true
                    Text
                    {
                        text: qsTr("Télécharger")
                        verticalAlignment: Text.AlignVCenter
                        horizontalAlignment: Text.AlignHCenter
                        anchors.fill: parent
                        font.family: "Verdana"
                        font.pointSize: 12
                    }
                    onClicked: {
                        tableOfSites.selection.forEach(function(rowIndex){
                            labelSite=listeSiteDistantsId.getLabel(rowIndex)
                            if (listeSiteDistantsId.isLock(rowIndex))
                            {
                                NotificationListModel.add (qsTr(labelSite + ' est bloqué car il a été téléchargé récemment'))
                                progressId.visible = false
                                backButton.visible = true
                            }
                            else
                            {
                                progressId.visible = true
                                backButton.visible = false
                                listeSiteDistantsId.loadFromRemoteDatabase(listeSiteDistantsId.getPkSite(rowIndex))
                            }
                        })
                    }
                }
            }
        }
        Connections {
            target: databaseManager
            onSigUploadSiteLockComplete : {
                progressId.visible = false ;
                backButton.visible = true;
                NotificationListModel.add (qsTr(labelSite + 'téléchargé avec succès'))
            }
            onSigUploadSiteSynchroProgress: progressId.value = parameters
        }
        ProgressBar {
            id: progressId
            minimumValue: 0
            maximumValue: 100
    
            anchors.centerIn: parent
            visible: false
        }
    }
    

    model.h

    #ifndef SITELISTMODEL_H
    #define SITELISTMODEL_H
    
    #include <QAbstractListModel>
    #include <QDateTime>
    #include <QDebug>
    #include <QList>
    #include <QString>
    #include <QStringList>
    
    class SiteListObject;
    
    // Created from "Models and Views: AbstractItemModel Example"
    class SiteListModel : public QAbstractListModel
    {
        Q_OBJECT
    public:
        enum SiteDistantRoles  {
            LabelRole = Qt::UserRole + 1,
            PkSiteRole,
            LockRole,
            NameRole,
            RefSmartCRole,
            VilleRole,
            DepartementRole
        };
    
        Q_INVOKABLE void checkUploadableSites();
        /*! @brief Delete site from local database
            @param id_site
        */
        Q_INVOKABLE void deleteSite (int);
        Q_INVOKABLE void loadRemoteSites(bool loadall, QString siteName, QString siteRef, QString siteVille, QString siteDept);
        /*! @brief Download remote database site
            @param id_site
        */
        Q_INVOKABLE void loadFromRemoteDatabase(int) const;
        /*! @brief Upload local site to remote server DB
            @param id_site
        */
        Q_INVOKABLE bool uploadLocalSite (int) const;
    
        Q_INVOKABLE int  rowCount(const QModelIndex & parent = QModelIndex()) const;
        QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
        Q_INVOKABLE bool isLock(const QModelIndex & index);
        Q_INVOKABLE QString getLabel(const QModelIndex & index);
        Q_INVOKABLE int getPkSite(const QModelIndex & index);
    
    public:
        SiteListModel(QObject * = 0);
        ~SiteListModel();
    
    signals:
        void sigLoadRemoteSites ();
        void sigLoadRemoteSitesbySearch(QString siteName, QString siteRef, QString siteVille, QString siteDept);
    
    protected slots:
        void slotListLocalSites  (const QStringList&, const QList<int> &, const QList<bool> &, const QList<int> &);
        void slotListRemoteSites (const QStringList&, const QStringList&, const QStringList&, const QStringList&, const QList<int> &, const QList<bool> &, const QList<int> &);
    
    protected:
        void add(const SiteListObject&);
        QHash<int, QByteArray> roleNames() const;
    
    protected:
        QList<SiteListObject> m_SiteList;
    };
    
    #endif // SITELISTMODEL_H
    
    

    model.cpp

    #include "siteListModel.h"
    
    #include <QQmlContext>
    #include <QQmlEngine>
    #include <QtSql>
    
    #include "DatabaseManager.h"
    #include "siteListObject.h"
    
    //! @brief Roles (~Properties) of listed item
    QHash<int, QByteArray> SiteListModel::roleNames() const
    {
        QHash<int, QByteArray> roles;
        roles[LabelRole] = "label";
        roles[RefSmartCRole] = "reference";
        roles[VilleRole] = "ville";
        roles[DepartementRole] = "departement";
        roles[PkSiteRole] = "pkSite";
        roles[LockRole] = "lock";
        return roles;
    }
    
    //! @brief Add to the list some item
    void SiteListModel::add(const SiteListObject& o)
    {
        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        m_SiteList.push_back(o);
        endInsertRows();
    }
    
    //! @brief Insert in the model labels, id_sites and lock_date of each remote site
    void SiteListModel::slotListLocalSites(const QStringList&,
                                           const QList<int> & pkSites,
                                           const QList<bool> &,
                                           const QList<int> & lockVersion)
    {
        // Check incoming datas
        Q_ASSERT (pkSites.size() == lockVersion.size());
    
        // Select each record in table site
        QSqlTableModel site;
        site.setTable("site");
        site.select();
    
        // Each one is about to inserted in the list
        for (int i = 0; i < site.rowCount(); ++i)
        {
            QSqlRecord rec = site.record(i);
            SiteListObject o (rec.value("label").toString(), rec.value("id_site").toInt(), false);
    
            // If a local site is also on the server, check if it can be uploaded
            if (pkSites.contains(o.pkSite()))
            {
                int j = pkSites.indexOf(o.pkSite());
                int localVersion = rec.value("last_version").toInt();
                int remoteVersion = lockVersion[j];
                // If remote version is not null and local Version is inferior to the remote
                // That means someone else has somehow uploaded a new site's version
                // Thus site cannot be uploaded, and needs to be locked
                if (localVersion < remoteVersion)
                {
                    qWarning() << tr("La version locale du site") << o.label() << "(" << o.pkSite()
                               << tr(") ne peux être envoyée au serveur :\nSur le serveur, le site est en version") << remoteVersion
                               << tr("alors que sa version locale est") << localVersion;
                    o.setLock(true);
                }
            }
            add (o);
        }
    }
    
    //! @brief Insert in the model labels, id_sites and lock_date of each remote site
    void SiteListModel::slotListRemoteSites(const QStringList & labels,
                                            const QStringList& reference,
                                            const QStringList& ville,
                                            const QStringList& departement,
                                               const QList <int> & pkSites,
                                               const QList<bool> & locks,
                                               const QList<int> &)
    {
        Q_ASSERT (labels.size() == pkSites.size());
        Q_ASSERT (labels.size() == locks.size());
    
        // Each element is a list entry
        for (int i = 0; i < labels.size(); ++i)
        {
            // Check if the "lock" is present on the server
            if (locks[i])
                qWarning() << tr("Le Site ") << labels[i] << '(' << pkSites[i] << ')'
                           << tr("est bloqué sur le serveur (car il a été téléchargé récemment).");
            SiteListObject o (labels[i], reference[i], ville[i],departement[i],pkSites[i], locks[i]);
            add(o);
        }
    }
    
    void SiteListModel::checkUploadableSites()
    {
        DatabaseManager* dbm = DatabaseManager::getInstance(DEFAULT);
        if (dbm)
            connect (dbm,  SIGNAL(sigRemoteSitesData(const QStringList&, const QStringList&,const QStringList&,const QStringList&,const QList<int> &, const QList<bool> &, const QList<int> &)),
                     this,  SLOT(slotListLocalSites (const QStringList&, const QStringList&,const QStringList&,const QStringList&,const QList<int> &, const QList<bool> &, const QList<int> &)), Qt::UniqueConnection);
    
        emit sigLoadRemoteSites();
    }
    
    void SiteListModel::deleteSite(int i)
    {
        if (m_SiteList.contains(i))
        {
            int index = m_SiteList.indexOf(i);
            beginRemoveRows(QModelIndex(), index, index);
            m_SiteList[index].deleteSite();
            endRemoveRows();
        }
    }
    
    void SiteListModel::loadRemoteSites(bool loadall, QString siteName, QString siteRef, QString siteVille, QString siteDept)
    {
        DatabaseManager* dbm = DatabaseManager::getInstance(DEFAULT);
        if (dbm)
        {
            connect (dbm,  SIGNAL(sigRemoteSitesData(const QStringList&, const QStringList&,const QStringList&,const QStringList&,const QList<int> &, const QList<bool> &, const QList<int> &)),
                     this,  SLOT(slotListRemoteSites(const QStringList&, const QStringList&,const QStringList&,const QStringList&,const QList<int> &, const QList<bool> &, const QList<int> &)), Qt::UniqueConnection);
        }
        if (loadall)
        {
            emit sigLoadRemoteSites();
        }
        else
        {
            emit sigLoadRemoteSitesbySearch(siteName, siteRef, siteVille, siteDept);
        }
    }
    
    void SiteListModel::loadFromRemoteDatabase(int i) const
    {
        if (m_SiteList.contains(i)) {
            m_SiteList[m_SiteList.indexOf(i)].loadFromRemoteDatabase(); }
    }
    
    bool SiteListModel::uploadLocalSite(int i) const
    {
        if (m_SiteList.contains(i))
        {
            if (m_SiteList[m_SiteList.indexOf(i)].uploadLocalSite())
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
    
    int SiteListModel::rowCount(const QModelIndex&) const
    {
        return m_SiteList.count();
    }
    
    QVariant SiteListModel::data(const QModelIndex& index, int role) const
    {
        if (index.row() < 0 || index.row() >= m_SiteList.count())
        {
            qDebug() << "index range error : "<<index.row();
            return QVariant();
        }
    
        const SiteListObject& siteDistant = m_SiteList[index.row()];
        switch (role) {
        case LabelRole:
            return siteDistant.label();
        case RefSmartCRole:
            return siteDistant.reference();
        case VilleRole:
            return siteDistant.ville();
        case DepartementRole:
            return siteDistant.departement();
        case PkSiteRole:
            return siteDistant.pkSite();
        case LockRole:
            qDebug() << "lock asked : "<<siteDistant.lock();
            return siteDistant.lock();
        default:
        return QVariant();
        }
    }
    
    bool SiteListModel::isLock(const QModelIndex & index)
    {
        if (!index.isValid())
        {
            qDebug() << "isLock index error : "<<index.row();
            return false;
        }
        if (index.row() < 0 || index.row() >= m_SiteList.count())
        {
            qDebug() << "isLock range error : "<<index.row();
            return false;
        }
        const SiteListObject& siteDistant = m_SiteList[index.row()];
        qDebug() << "isLock";
        return siteDistant.lock();
    }
    
    QString SiteListModel::getLabel(const QModelIndex & index)
    {
        if (index.row() < 0 || index.row() >= m_SiteList.count())
        {
            qDebug() << "getLabel range error";
            return "error";
        }
        const SiteListObject& siteDistant = m_SiteList[index.row()];
        qDebug() << "getLabel";
        return siteDistant.label();
    }
    int SiteListModel::getPkSite(const QModelIndex & index)
    {
        if (index.row() < 0 || index.row() >= m_SiteList.count())
            return 0;
        const SiteListObject& siteDistant = m_SiteList[index.row()];
        return siteDistant.pkSite();
    }
    
    /*! @brief  Creator
        @note   L'instance crée est connectée au DatabaseManager (network -> slots/signaux)
    */
    SiteListModel::SiteListModel(QObject* parent)
        : QAbstractListModel(parent)
    {
        DatabaseManager* dbm = DatabaseManager::getInstance(DEFAULT);
        if (dbm)
        {
            qDebug() << "mise en place des conexion";
            connect (this,  SIGNAL(sigLoadRemoteSites()),
                     dbm,   SLOT(slotListRemoteSites()), Qt::QueuedConnection);
            connect (this,  SIGNAL(sigLoadRemoteSitesbySearch(QString,QString,QString,QString)),
                     dbm,   SLOT(slotListRemoteSitesBySearch(QString,QString,QString,QString)), Qt::QueuedConnection);
        }
    }
    
    SiteListModel::~SiteListModel()
    {
    }
    
    

    as you can see, I called the lock role in the qml, this time. Still, none of the debugs are trigered.



  • @the-moebius
    @medyakovvit said:

    itemDelegate: Text {
    color: model.lock ? "red" : "black" // not listeSiteDistantsId.lock
    text: styleData.value
    }

    use model.lock not listeSiteDistantsId.lock. "model" reference to TableView property, not to some id of model.



  • Indeed, it works...my bad :p

    However, I tried to do the same for the froEach part, but

    labelSite=tableOfSites.model.label
    

    returns

    Error: Cannot assign [undefined] to QString
    

    and

    labelSite=tableOfSites.model.label(rowIndex)
    

    returns

    TypeError: Property 'label' of object SiteListModel(0x33d12358) is not a function
    

    any idea ?



  • @the-moebius
    Maybe change to:

    Q_INVOKABLE QString getLabel(int row);
    

    And in forEach:

    labelSite = listeSiteDistantsId.getLabel(rowIndex);
    


  • It works...finally
    thank you a lot


Log in to reply
 

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