get the content from a tableview and change it
-
Hi,
I'm new in Qt and c++.
I want get the content of a cell and if the requirement is true i will change the content in the tableview.
But I make something wrong but I don't know wat exactly.there I'm getting the background color of the cell and it works fine
QVariant TableCustomise::data(const QModelIndex &index, int role) const { if(role == Qt::BackgroundRole ) { QString content = index.sibling(index.row(), 0).data(Qt::DisplayRole).toString(); if ( content == "red" ) { return QBrush(Qt::red); } } return QSqlQueryModel::data(index, role); }
therefore I thried to change the content of the cell the same way
but this doesn't work
why?QVariant TableCustomise::data(const QModelIndex &index, int role)const { if(role == Qt::DisplayRole()) { QString content = index.sibling(index.row(), index.column()).data(Qt::DisplayRole).toString(); if (content == "1") { return "red"; } } return QSqlQueryModel::data(index, role) ; }
I hope someone can help me.
Thank you
-
Hi,
I'm new in Qt and c++.
I want get the content of a cell and if the requirement is true i will change the content in the tableview.
But I make something wrong but I don't know wat exactly.there I'm getting the background color of the cell and it works fine
QVariant TableCustomise::data(const QModelIndex &index, int role) const { if(role == Qt::BackgroundRole ) { QString content = index.sibling(index.row(), 0).data(Qt::DisplayRole).toString(); if ( content == "red" ) { return QBrush(Qt::red); } } return QSqlQueryModel::data(index, role); }
therefore I thried to change the content of the cell the same way
but this doesn't work
why?QVariant TableCustomise::data(const QModelIndex &index, int role)const { if(role == Qt::DisplayRole()) { QString content = index.sibling(index.row(), index.column()).data(Qt::DisplayRole).toString(); if (content == "1") { return "red"; } } return QSqlQueryModel::data(index, role) ; }
I hope someone can help me.
Thank you
@Mogli123
In yourQSqlQueryModel::data()
, when you start looking at another cell in order to determine the result for one cell you have to be very careful. And that's your problem here!In your working example, to return a cell's
Qt::BackgroundRole
you look at another cell'sQt::DisplayRole
, and that's OK.However, in your second example to return a cell's
Qt::DisplayRole
you look at another cell'sQt::DisplayRole
, the same role. Now if you think about it, that causes a potentially "infinite recursion", because when you look at the other cell'sQt::DisplayRole
you will be re-executing the same pathway in yourTableCustomise::data()
, and that in turn will look at that cell's sibling, and so on....The first, most obvious problem is that when you come to look at the right-most cell, your code still asks for that one's
sibling()
, but there isn't one. http://doc.qt.io/qt-5/qmodelindex.html#sibling :Returns the sibling at column for the current row. If there is no sibling at this position, an invalid
QModelIndex
is returned.So you must check for your
index.sibling(index.row(), index.column())
returning invalid, which you are not presently doing.Beyond that, you need to think out what you want here. You keep saying that each cell's
Qt::DisplayRole
depends on its sibling'sQt::DisplayRole
value. That can't be right: it needs to stop somewhere. Perhaps this only applies whereindex.column()
has a certain value?There are other approaches which may help. But since you're a beginner I won't go into them yet, don't want to overload you with information. And it may not be necessary, depending on what you wish to change your code to do.
Let us know!
-
Thank you for your answer
I want only know what the content of the cells from each row is.
Than I decide which color get the background of the complet row.
Therefore I want to write the color in the first columnFurthermore is it possible to split the two funktions above?
I dont't want the two code in the same method -
Thank you for your answer
I want only know what the content of the cells from each row is.
Than I decide which color get the background of the complet row.
Therefore I want to write the color in the first columnFurthermore is it possible to split the two funktions above?
I dont't want the two code in the same method@Mogli123
I'm afraid I don't understand what you are saying in the 3 line-paragraph in your response. So it's difficult to answer! If you are saying you only want"red"
returned whenindex.column() == 0
then you need code for that for a start.For the 2 line-paragraph: I think you are saying that when trying to return the
Qt::DisplayRole
of"red"
for a cell, you would rather not have to call the sameTableCustomise::data()
code to read theQt::DisplayRole
of the sibling, which is what causes the potential recursion?Unfortunately, so far as I know once you have written a
QSqlQueryModel::data()
override you cannot help but have that called to query all cells' data --- there is no way to call another cell's baseQSqlQueryModel::data()
instead of your overridden method. Because that would have made it easier....Unless a C++ expert knows better, the way I can think of to do this is: You can define your own, additional roles. They start at something like
Qt::UserRole + 1
, or something like that, it's in the docs. I would define that, and have yourTableCustomise::data()
if called with that asrole
goif (role == Qt::UserRole + 1) return QSqlQueryModel::data(index, Qt::DisplayRole);
The intention is that route should return the original display-role value, not the one altered by your override, so no recursion/alteration. You'll have to check this, as I'm not a C++-er.
Then when looking for the sibling's value you can go
if (role == Qt::DisplayRole()) { QString content = index.sibling(index.row(), index.column()).data(Qt::UserRole + 1).toString(); .... }
That's assuming this is what you mean by
Furthermore is it possible to split the two funktions above?
I dont't want the two code in the same methodSorry, I know you're a beginner, you'll have to do a bit of work to read & implement what I've written. Because I don't have time, I really must get on with my own work....!
-
@Mogli123
I'm afraid I don't understand what you are saying in the 3 line-paragraph in your response. So it's difficult to answer! If you are saying you only want"red"
returned whenindex.column() == 0
then you need code for that for a start.For the 2 line-paragraph: I think you are saying that when trying to return the
Qt::DisplayRole
of"red"
for a cell, you would rather not have to call the sameTableCustomise::data()
code to read theQt::DisplayRole
of the sibling, which is what causes the potential recursion?Unfortunately, so far as I know once you have written a
QSqlQueryModel::data()
override you cannot help but have that called to query all cells' data --- there is no way to call another cell's baseQSqlQueryModel::data()
instead of your overridden method. Because that would have made it easier....Unless a C++ expert knows better, the way I can think of to do this is: You can define your own, additional roles. They start at something like
Qt::UserRole + 1
, or something like that, it's in the docs. I would define that, and have yourTableCustomise::data()
if called with that asrole
goif (role == Qt::UserRole + 1) return QSqlQueryModel::data(index, Qt::DisplayRole);
The intention is that route should return the original display-role value, not the one altered by your override, so no recursion/alteration. You'll have to check this, as I'm not a C++-er.
Then when looking for the sibling's value you can go
if (role == Qt::DisplayRole()) { QString content = index.sibling(index.row(), index.column()).data(Qt::UserRole + 1).toString(); .... }
That's assuming this is what you mean by
Furthermore is it possible to split the two funktions above?
I dont't want the two code in the same methodSorry, I know you're a beginner, you'll have to do a bit of work to read & implement what I've written. Because I don't have time, I really must get on with my own work....!
2 minor notes:
index.sibling(index.row(), index.column())
isindex
@JonB said in get the content from a tableview and change it:
there is no way to call another cell's base QSqlQueryModel::data() instead of your overridden method.
There is and you are using it 2 rows below
QSqlQueryModel::data(index, Qt::DisplayRole);
-
2 minor notes:
index.sibling(index.row(), index.column())
isindex
@JonB said in get the content from a tableview and change it:
there is no way to call another cell's base QSqlQueryModel::data() instead of your overridden method.
There is and you are using it 2 rows below
QSqlQueryModel::data(index, Qt::DisplayRole);
index.sibling(index.row(), index.column())
isindex
What does this mean?
QModelIndex::sibling()
returns some (next?) "sibling" ofindex
, no (err, now I wonder..)? I said the OP that he must check that is valid.QSqlQueryModel::data(index, Qt::DisplayRole);
I'm getting lost here in C++ vs the Python I have to use for PyQt/Qt. I thought this would still call his
TableCustomise::data()
override on the cell specified byindex
, no? I'm sure when I tried this via PyQt (we can't use the same syntax as C++, and we cannot directly call C++ function, only their PyQt wrappers) it did.... :( -
sorry my enlish ist not the best
The first code example just shows where I got the idea for the code in the second example.
And how I color the rows.I just want to know how I can read the information of a cell and, because of the content, write content in a cell of my choice
For example:
I want color the row red if in one of the cells of the row stands a 0.
therefore I want to write "red" in the first cell of the row if that is true.I hope you understand what I mean
I understand if you haven't time to help me.
-
sorry my enlish ist not the best
The first code example just shows where I got the idea for the code in the second example.
And how I color the rows.I just want to know how I can read the information of a cell and, because of the content, write content in a cell of my choice
For example:
I want color the row red if in one of the cells of the row stands a 0.
therefore I want to write "red" in the first cell of the row if that is true.I hope you understand what I mean
I understand if you haven't time to help me.
@Mogli123
Very briefly:I want color the row red if in one of the cells of the row stands a 0.
therefore I want to write "red" in the first cell of the row if that is true.Do you want to color the row (use
role == Qt::BackgroundRole
like first example) or do you want to write the string"red
" in the first column's cell (userole == Qt::DisplayRole()
) like your second example, or both, or what? -
At first thank you for your answers
First I want to write the color in a cell (for example "red")
After that I want to color the row with the wantet color like the first exampleI know that I could color the lines with the desired condition without writing the color in the cell
but i would like to separate these two methods if possible -
At first thank you for your answers
First I want to write the color in a cell (for example "red")
After that I want to color the row with the wantet color like the first exampleI know that I could color the lines with the desired condition without writing the color in the cell
but i would like to separate these two methods if possible@Mogli123
My literally last scribbled ideas:-
You will need your function to have two cases, one for
role == Qt::BackgroundRole
and another forQt::DisplayRole()
, respectively. -
If you have multiple cells in a row, and you want to know if any of them contains something to affect the coloring, you'll need to look at all the cells after the first one, calling
sibling()
or similar in a loop to look at each one. -
I think you'll need to set the
Qt::BackgroundRole
for each cell (unless there's a way to do it one for a whole row), but set theQt::DisplayRole()
only for column 0. -
Do not examine the value of column 0 itself when calculating, as you may recurse infinitely.
-
-
index.sibling(index.row(), index.column())
isindex
What does this mean?
QModelIndex::sibling()
returns some (next?) "sibling" ofindex
, no (err, now I wonder..)? I said the OP that he must check that is valid.QSqlQueryModel::data(index, Qt::DisplayRole);
I'm getting lost here in C++ vs the Python I have to use for PyQt/Qt. I thought this would still call his
TableCustomise::data()
override on the cell specified byindex
, no? I'm sure when I tried this via PyQt (we can't use the same syntax as C++, and we cannot directly call C++ function, only their PyQt wrappers) it did.... :(@JonB said in get the content from a tableview and change it:
What does this mean?
QModelIndex QAbstractItemModel::sibling(int row, int column, const QModelIndex &idx) const { return (row == idx.row() && column == idx.column()) ? idx : index(row, column, parent(idx)); }
so if you pass the same rows and columns as the original index you get back the original index
-
I have changed
QString content = index.sibling(index.row(), 0).data(Qt::DisplayRole).toString();
to
QString content = index.sibling(index.row(), index.column()).data(Qt::EditRole).toString();
and it seems that it works
is this the right way?my only problem now is that i would separate the to mehods
the problem is that they have the same nam
but on which place I can change the name that I can separate the methods?sorry for that if this is basic
-
I have changed
QString content = index.sibling(index.row(), 0).data(Qt::DisplayRole).toString();
to
QString content = index.sibling(index.row(), index.column()).data(Qt::EditRole).toString();
and it seems that it works
is this the right way?my only problem now is that i would separate the to mehods
the problem is that they have the same nam
but on which place I can change the name that I can separate the methods?sorry for that if this is basic
@Mogli123
You cannot "separate the methods", per se.The way Qt works is that its infrastructure always calls
QSqlQueryModel::data(index, role)
(and thus yourTableCustomise::data()
override) for different attributes/effects/results, passing in varying values forrole
accordingly. That's just the way it is, and you cannot alter that.Usually you just write your overload stuff in the one function, using
if (role == ...) ... else if (role == ) ... else ...
(or similar, you may be able to use aswitch
statement instead for neatness) for the various cases, and your code is all in that function.If you feel your code is too big, you would have to write your own separate, new functions for each case and just call them in your code, like:
QVariant TableCustomise::data(const QModelIndex &index, int role)const { if (role == Qt::DisplayRole()) return displayData(index); else if (role == Qt::backgroundRole()) return backgroundData(index); else return QSqlQueryModel::data(index, role) ; } QVariant TableCustomise::displayData(const QModelIndex &index )const { return ...; } QVariant TableCustomise::backgroundData(const QModelIndex &index )const { return ...; }