Unsolved Change color of a row of a QSqlQueryModel (QTableView)?
-
I changed function data to setData which has a parameter called 'p_object' and I use it for color:
def setData(self, QModelIndex, p_object, role=None): v = QtSql.QSqlQueryModel.data(self, QModelIndex, role); if role == QtCore.Qt.BackgroundRole: self.dataChanged.emit(QModelIndex, QModelIndex) return QtGui.QColor(p_object) return (v);
I call it this way:
model.setData(index, QtCore.Qt.red, QtCore.Qt.BackgroundRole)
But it's not working, maybe the emit Signal is not correct.
-
@Panoss You really have to read up on the documentation. If you intend to work further with Qt's model system, there is no way around it. For this case, look here:
http://doc.qt.io/qt-5/qabstractitemmodel.html#setData -
c64zottel thank you, I saw in the link you posted that I have to emit the signal.
I tried with:self.dataChanged.emit(QModelIndex, QModelIndex)
But doesn't seem to work.
For sure, I 'm doing something wrong. -
@Panoss Ok, this is Python anyway, I am out of my league here. But, as a last resort, you can try to call:
beginResetModel();
endResetModel(); -
I tried with beginResetModel() and endResetModel() in many places witihn the function setData, but with no success.
I don't know what else should I try, any ideas are welcome. -
@Panoss That was exactly how it works in my application. Maybe they just support the dataChanged signal, which you used earlier. But I just saw, that you do not specify the correct arguments. You have to send the signal like:
dataChanged( ModelIndex to first item changed, ModelIndex to last item changed )
Model indices can be created with:
QModelIndex QAbstractItemModel::index(int row, int column, const QModelIndex &parent = QModelIndex()) const -
@c64zottel said in Change color of a row of a QSqlQueryModel (QTableView)?:
@Panoss That was exactly how it works in my application.
Maybe you could post the code from your setData function?
And I will 'translate' it in python. -
@Panoss I don't have a setData function. The code I use for reset is:
void BattlefieldModel::refresh( const QSet< LinearCoordinate > & indices ) { for( int lc : indices ) { QModelIndex a = index( lc ); emit dataChanged( a, a ); } }
But this is only ok because, ... well lets not get into it.
The arguments of index ( row, column) is just the position you want to update. Since I have just rows, I update just rows.
-
First of all, let me start by saying that using a
QStandardItemModel
filled manually from aQSqlQuery
is probably the fastest way to go.having said that you can use this proxy model to make it work:
Sorry for C++
#include <QIdentityProxyModel> class ExtraRolesProxyModel : public QIdentityProxyModel { Q_OBJECT Q_DISABLE_COPY(ExtraRolesProxyModel) public: explicit ExtraRolesProxyModel(QObject* parent=Q_NULLPTR) :QIdentityProxyModel(parent) {} virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE{ const qint64 hashKey = (static_cast<qint64>(index.row()) << 32) | static_cast<qint64>(index.column()); auto tableIter = m_extraRoles.constFind(hashKey); if(tableIter==m_extraRoles.constEnd()) return QIdentityProxyModel::data(index,role); auto roleIter = tableIter.value().constFind(role); if(roleIter==tableIter.value().constEnd()) return QIdentityProxyModel::data(index,role); return roleIter.value(); } virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE { if(!index.isValid()) return false; Q_ASSERT(index.model()==this); const qint64 hashKey = (static_cast<qint64>(index.row()) << 32) | static_cast<qint64>(index.column()); if(value.isValid()){ m_extraRoles[hashKey][role] = value; emit dataChanged(index,index,QVector<int>(1,role)); return true; } auto tableIter = m_extraRoles.find(hashKey); if(tableIter==m_extraRoles.end()) return false; auto roleIter = tableIter.value().find(role); if(roleIter==tableIter.value().end()) return false; tableIter.value().erase(roleIter); if(tableIter.value().isEmpty()) m_extraRoles.erase(tableIter); emit dataChanged(index,index,QVector<int>(1,role)); return true; } private: QHash<qint64,QHash<qint32,QVariant> > m_extraRoles; };
-
How can this line be explained in plain english?
const qint64 hashKey = (static_cast<qint64>(index.row()) << 32) | static_cast<qint64>(index.column());
If index.row() is smaller than 32 thne hashkey = index.row().
Else hashkey = index.column()? -
@Panoss That row means: prepare an integer with 64 bits, the 32 leftmost bits will contain the row, the 32 rightmost the column. The bitshift operator is the same even in python https://wiki.python.org/moin/BitwiseOperators
-
I translated it likes this: (I get no error on this line, seems ok)
hashKey = index.row() << 32 | index.column()
But this one;
auto tableIter = m_extraRoles.constFind(hashKey);
Converted to python:
tableIter = m_extraRoles.constFind(hashKey)
Says variable m_extraRoles 'Unresolved reference'. It has not been declared anywhere.
-
shouldn't it be
this.m_extraRoles.constFind(hashKey)
? -
Yes, you 're right VRonin:
tableIter = self.m_extraRoles.constFind(hashKey)
This shows no underlined code in Pychrm (if there were any errors, it would be underlined. With red color.)
But this look very hard to convert to python:
Q_ASSERT(index.model()==this)
Q_ASSERT?? omg
-
You can actually remove that line altogether, it's just a check that is done only in debug mode
-
Only one (!!) line is left:
emit dataChanged(index,index,QVector<int>(1,role));
Translated to:
self.dataChanged.emit(index,index,QVector(int((1,role)))
But there is no QVector in Python.
(I mean it doesn't exist in any library like PyQt4.QtCore) -
Leave it with just
self.dataChanged.emit(index,index)
then. the last one is an optional parameter and even Qt's native models don't use it -
I set for source of the proxy model (ExtraRolesProxyModel) a QSqlQueryModel.
But I get an error:
'tableIter = self.m_extraRoles.constFind(hashKey)
AttributeError: 'ExtraRolesProxyModel' object has no attribute 'm_extraRoles' -
And this is the whole code (of the class):
class ExtraRolesProxyModel(QIdentityProxyModel ): def __init__(self, dbcursor=None): super(ExtraRolesProxyModel, self).__init__() def data(self, index, role): hashKey = index.row() << 32 | index.column() tableIter = self.m_extraRoles.constFind(hashKey) if tableIter==self.m_extraRoles.constEnd: return QtSql.QSqlQueryModel.data(index,role); roleIter = tableIter.value().constFind(role) if roleIter==tableIter.value().constEnd(): return QtSql.QSqlQueryModel.data(index,role); return roleIter.value() def setData(self, index, value, role=None): if not index.isValid(): return False hashKey = index.row() << 32 | index.column() if value: self.m_extraRoles[hashKey][role] = value self.dataChanged.emit(index,index) return True; tableIter = self.m_extraRoles.find(hashKey) if tableIter== self.m_extraRoles.end(): return False roleIter = tableIter.value().find(role) if roleIter==tableIter.value().end(): return False tableIter.value().erase(roleIter) if tableIter.value().isEmpty(): self.m_extraRoles.erase(tableIter) self.dataChanged.emit(index, index) return True
-
@Panoss said in Change color of a row of a QSqlQueryModel (QTableView)?:
AttributeError: 'ExtraRolesProxyModel' object has no attribute 'm_extraRoles'
You have to declare it in the
__init__
method (not sure how you deal with templates in python though)
@Panoss said in Change color of a row of a QSqlQueryModel (QTableView)?:
if tableIter==self.m_extraRoles.constEnd:
Missing ()
if value:
Does it work?