PDA

View Full Version : Color rows of QTableView(in python)



panoss
31st May 2017, 18:21
I 'm trying to color the rows of a QTableView which has a QIdentityProxyModel model as it 's model (which has as source model a QSqlQueryModel).

This is the code (compilable):


from PyQt4 import QtGui, QtCore, QtSql
from PyQt4.QtCore import QModelIndex
from PyQt4.QtGui import *
import sys

def main():
app = QtGui.QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())

class MyWindow(QtGui.QTableView):
def __init__(self, *args):
QtGui.QTableView.__init__(self, *args)

# connect to db (if doesn't exist, it's auto-created)
self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
self.db.setDatabaseName('test.db')
self.db.open()

#create a table in db and add some data
query = QtSql.QSqlQuery()
query.exec_("DROP TABLE IF EXISTS games")
query.exec_("CREATE TABLE games(id INTEGER PRIMARY KEY, hometeam TEXT, visitorteam TEXT) ")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('Star', 'Eagles')")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('Best team', 'Reds');")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('NonWinners', 'Loosers');")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('North', 'South');")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('East', 'west');")

# set the model
model = QtSql.QSqlQueryModel(self)
model.setQuery("SELECT * FROM games")
proxy_model = ExtraRolesProxyModel(self)#QtGui.QStandardItemMode l(0, 2)
proxy_model.setSourceModel(model);

self.setModel(proxy_model)


# paint first two rows
#model.setRowsToBeColored([0,3])
rowsToBeColored = []
for i in range(0, 2):
rowsToBeColored.append(i)
#model.setRowsToBeColored(rowsToBeColored)
index = QtCore.QModelIndex(model.index(i, 0))
model.setData(index, QtCore.Qt.red, QtCore.Qt.BackgroundRole)




class ExtraRolesProxyModel(QIdentityProxyModel ):
def __init__(self, dbcursor=None):
super(ExtraRolesProxyModel, self).__init__()
#self.m_extraRoles = []
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


if __name__ == "__main__":
main()




I get error:
"tableIter = self.m_extraRoles.constFind(hashKey)
AttributeError: 'ExtraRolesProxyModel' object has no attribute 'm_extraRoles"

The class ExtraRolesProxyModel is a 'translation' from C++, this is the C+++ code of it:


#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;
};


Any ideas are welcome.

wysota
1st June 2017, 22:48
QSqlQueryModel does not accept data for BackgroundRole. Either subclass it and teach the subclass to return (and accept) the proper data or apply a custom proxy that would do it (the one you have seems to be able to do it).