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