Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct


    Qt World Summit: Early-Bird Tickets

    Solved issue with row in a tableview

    QML and Qt Quick
    2
    7
    1408
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • the moebius
      the moebius last edited by

      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...

      M 1 Reply Last reply Reply Quote 0
      • M
        medyakovvit @the moebius last edited by

        @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
                }
        
        1 Reply Last reply Reply Quote 0
        • the moebius
          the moebius last edited by

          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.

          M 1 Reply Last reply Reply Quote 0
          • M
            medyakovvit @the moebius last edited by medyakovvit

            @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.

            1 Reply Last reply Reply Quote 0
            • the moebius
              the moebius last edited by

              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 ?

              M 1 Reply Last reply Reply Quote 0
              • M
                medyakovvit @the moebius last edited by

                @the-moebius
                Maybe change to:

                Q_INVOKABLE QString getLabel(int row);
                

                And in forEach:

                labelSite = listeSiteDistantsId.getLabel(rowIndex);
                
                1 Reply Last reply Reply Quote 0
                • the moebius
                  the moebius last edited by

                  It works...finally
                  thank you a lot

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post