Results 1 to 20 of 25

Thread: Color a row - QSqlRelationalTableModel or QSqlQueryModel

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Sep 2016
    Posts
    12
    Qt products
    Qt5
    Platforms
    Windows

    Default Color a row - QSqlRelationalTableModel or QSqlQueryModel

    I am trying both QSqlRelationalTableModel and QSqlQueryModel to view records from a database in a QtableView, but when I want to do something as simple as setting a background color on a row, i bang my head on the wall,... two days, and still nothing is working... i cant believe how impossible it is to find a simple solution to this. I have read so many messages on forums and various websites, and there is nothing that works, it all suggests the same things that does not work. You can for example not use:

    model->setData(index, QVariant(QColor(Qt::yellow)), Qt::BackgroundRole);

    ... because both QSqlRelationalTableModel and QSqlQueryModel is ignoring Qt::BackgroundRole. QSqlQueryModel is read only, so only model->data() works for getting data. QSqlRelationalTableModel can model->setData() but it only cares about Qt::EditRole, and ignores all I try to do with background color.

    I have found some extremely long and complicated solutions, that might work, but I cant believe that i have to write several pages of code to set a freaking background color on a row.

    Please, if someone knows how to do this, I would really appreciate some help on this.
    Thank you,

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts

    Default Re: Color a row - QSqlRelationalTableModel or QSqlQueryModel

    You can derive from the model class and reimplement data() such that it returns something for the Qt::BackgroundRole.
    Whether you set that value from outside or whether the value is determined in the model itself is up to you.

    You can use a QIdentityProxyModel between the model and the view to provide data for additional roles.
    More or less very similar to the first approach, but works independent of what the source model is.

    You can set your own item delegate that draws the background in a way you want.

    First option is obviously the easiest one, only a handful of lines of code, the last one is the most demanding one.

    Cheers,
    _

  3. #3
    Join Date
    Sep 2016
    Posts
    12
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Color a row - QSqlRelationalTableModel or QSqlQueryModel

    Well, if I create a new class, and a new data(), then i can use the index it receives and read what row im on, and what column im on, and set the color on the row if I know the row number i want.

    But lets say i want to put blue background on the row if column 2 is blank. I cant get to my model to create a new index to check on that column from within the data().

  4. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts

    Default Re: Color a row - QSqlRelationalTableModel or QSqlQueryModel

    Quote Originally Posted by AKG View Post
    But lets say i want to put blue background on the row if column 2 is blank.
    Then you retrieve the value for column 2 of the same row and check it?

    Quote Originally Posted by AKG View Post
    I cant get to my model to create a new index to check on that column from within the data().
    You don't need to "get to my model", inside data() you are the model.

    But even if you weren't QModelIndex::model() always gives you access to the model an index came from.

    Cheers,
    _

  5. #5
    Join Date
    Sep 2016
    Posts
    12
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Color a row - QSqlRelationalTableModel or QSqlQueryModel

    Im not explaining well, that is why you don't see what I am actually trying to ask. Sorry about that, english is not my primary language.

    I have a view with lots of images and hundres of columns, and a ton of rows, so when data() is called by the view on every cell every time the user clicks on something, it takes a lot of time to refresh if I do to much in the data() function.

    I understand how to do all that is suggested, and i can get it to do all i want, but the code i end up with is just not fast enough. There is to much code that does things like getting my model from the index, then creating a new index, then getting the row and the column of the cell i am checking the content of from that index, for then finally setting some changes to a cell.... remember, this code is run for every single cell, every singe time something in the view is clicked.

    Someone on a different forum made me aware of the sibling function, that lets me stay on the same row, ans i assume all columns are sibling of the same row ?? I have not tired it at this time, but if that is true, i guess that will shorten the code a bit.

    I just wish i could do a row at a time, or some other logic ... maybe saving the criteria for the cells in the database, and then displaying every second column, hiding the "setting column" ... i don't know.

    If the columns in my database alternate between one settings row, then one content column. The data() function will read the setting row to find out what and how to display it, and display what ever is in the content column.

    any thoughts ?? I feel like Im stubling around in the dark right now. Just cant get this to go faster.

  6. #6
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts

    Default Re: Color a row - QSqlRelationalTableModel or QSqlQueryModel

    Quote Originally Posted by AKG View Post
    Im not explaining well, that is why you don't see what I am actually trying to ask. Sorry about that, english is not my primary language.
    Then maybe post the code for data()?

    Quote Originally Posted by AKG View Post
    Someone on a different forum made me aware of the sibling function, that lets me stay on the same row, ans i assume all columns are sibling of the same row ?? I have not tired it at this time, but if that is true, i guess that will shorten the code a bit.
    sibling() will also just call index().
    If you have the same background color for each cell in a row, you could cache the value.

    Cheers,
    _

  7. #7
    Join Date
    Sep 2016
    Posts
    12
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Color a row - QSqlRelationalTableModel or QSqlQueryModel

    I don't understand what you mean by cash the value ?

    A simple data() function to deal with background color wold be for example like this:

    Qt Code:
    1. QVariant CustomSqlModel::data(const QModelIndex &index, int role) const
    2. {
    3. const QAbstractItemModel * model = index.model();
    4. QModelIndex index2 = model->index(index.row(), 1, QModelIndex()); // position 1 on current row
    5. QVariant value2 = QSqlQueryModel::data(index2, Qt::DisplayRole);
    6. if(value2.toString() == "" && role == Qt::BackgroundRole) { // if the column 2 on the same row is blank we set the color
    7. return QVariant(QColor(Qt::yellow));
    8. }
    9. QVariant value = QSqlQueryModel::data(index, role);
    10. return value;
    11. }
    To copy to clipboard, switch view to plain text mode 

    The code is called on every cell, so every cell on the row that has a blank column 2 will be painted - because this if is true on all cell on that row

    The faster way would be to have a list of what needs to be updated and the indexes saved - and then call a function that goes in to only the selected rows and repaints only those cell that needs extra features / colors etc. This function must be automatically triggered after the view calls the data function on all cells every time it does that.

    Any ideas ?

    Or if I try to ask a more precise question : where can i intercept the code that fires the data() function ?? so that I can add a function call to a function that only selct spesific cells to pain over again... hmmm dont know if im makins sence or not sorry.
    Last edited by AKG; 5th September 2016 at 22:58.

  8. #8
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts

    Default Re: Color a row - QSqlRelationalTableModel or QSqlQueryModel

    Quote Originally Posted by AKG View Post
    I don't understand what you mean by cash the value ?
    You determine the value the first time you need it and store it in a data member for retrieval when it is needed again.

    Quote Originally Posted by AKG View Post
    A simple data() function to deal with background color wold be for example like this:
    That is like an example from a C++ recruiter, when potential hires are asked "what is wrong with this".

    Obviously the worst thing is doing unnecessary things all the time which are only needed when retrieving the background color, but in order of execution:

    Quote Originally Posted by AKG View Post
    Qt Code:
    1. const QAbstractItemModel * model = index.model();
    To copy to clipboard, switch view to plain text mode 
    Creating an alias for "this". Through a function call so that the compiler can't easily figure out that "model" and "this" are the same.
    Would be worse of course if QModelIndex::model() weren't inline and a const expression.

    Quote Originally Posted by AKG View Post
    Qt Code:
    1. QModelIndex index2 = model->index(index.row(), 1, QModelIndex()); // position 1 on current row
    2. QVariant value2 = QSqlQueryModel::data(index2, Qt::DisplayRole);
    To copy to clipboard, switch view to plain text mode 
    As already pointed out, doing things not necessary for all calls to data()

    Quote Originally Posted by AKG View Post
    Qt Code:
    1. if(value2.toString() == "" && role == Qt::BackgroundRole) { // if the column 2 on the same row is blank we set the color
    To copy to clipboard, switch view to plain text mode 
    This is one is a classic :-)
    Doing the two condition parts in the wrong order, expensive string comparison before the cheap int comparison.
    Also needlessly doing a string comparison, which would be even worse if QString:perator==() didn't have a const char* overload.
    Very likely needless conversion from QVariant to QString, depending on the column's data.

    Quote Originally Posted by AKG View Post
    Qt Code:
    1. QVariant value = QSqlQueryModel::data(index, role);
    2. return value;
    3. }
    To copy to clipboard, switch view to plain text mode 
    Creating of a local, non-const, variable to force the compiler to track it for optimization.

    Quote Originally Posted by AKG View Post
    The code is called on every cell
    Which usually means that code in data() should not be artifically pessimised a lot.

    Quote Originally Posted by AKG View Post
    so every cell on the row that has a blank column 2 will be painted - because this if is true on all cell on that row
    Which would lend itself to caching.

    Quote Originally Posted by AKG View Post
    The faster way would be to have a list of what needs to be updated and the indexes saved - and then call a function that goes in to only the selected rows and repaints only those cell that needs extra features / colors etc. This function must be automatically triggered after the view calls the data function on all cells every time it does that.
    The view calls data() when it thinks it needs it, e.g. when a new cell comes into view, when the model signals change.

    Quote Originally Posted by AKG View Post
    Or if I try to ask a more precise question : where can i intercept the code that fires the data() function ?? so that I can add a function call to a function that only selct spesific cells to pain over again... hmmm dont know if im makins sence or not sorry.
    That is in the view code, in your case likely somewhere here https://code.woboq.org/qt5/qtbase/sr...eview.cpp.html

    Cheers,
    _

  9. #9
    Join Date
    Sep 2016
    Posts
    12
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Color a row - QSqlRelationalTableModel or QSqlQueryModel

    Thank you,

    I am afraid i am having som problems undestanding what you are saying.
    I would really appreciate if you can write the code for this data() function, so i can see this is code. It is easier for me to understand if you just write it in code how this should be done.

    Thank you again

  10. #10
    Join Date
    Dec 2009
    Location
    New Orleans, Louisiana
    Posts
    791
    Qt products
    Qt5
    Platforms
    MacOS X
    Thanks
    13
    Thanked 153 Times in 150 Posts

    Default Re: Color a row - QSqlRelationalTableModel or QSqlQueryModel

    Pardon me for jumping into this thread late, but are you looking for something as simple as the following (uncompiled and untested but should be close):
    Qt Code:
    1. QVariant CustomSqlModel::data(const QModelIndex &index, int role) const
    2. {
    3. QVariant value = QSqlQueryModel::data(index, role);
    4.  
    5. if (role == Qt::BackgroundRole && index.column() == 2 && QSqlQueryModel::data(index, Qt::DisplayRole).toString() == "")
    6. value = QColor(Qt::yellow);
    7.  
    8. return value;
    9. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by jefftee; 8th September 2016 at 05:20.
    I write the best type of code possible, code that I want to write, not code that someone tells me to write!

  11. #11
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts

    Default Re: Color a row - QSqlRelationalTableModel or QSqlQueryModel

    Close, but the background color applies for all cells of the row. this would be something more like

    Qt Code:
    1. QVariant CustomSqlModel::data(const QModelIndex &index, int role) const
    2. {
    3. if (role == Qt::BackgroundRole) {
    4. const QModelIndex column1Index = this->index(index.row(), 1);
    5. const QVariant value = QSqlQueryModel::data(column1Index, Qt::DisplayRole);
    6.  
    7. if (!value.isValid() || value.toString().isEmpty()) return QColor(Qt::yellow);
    8. }
    9.  
    10. return QSqlQueryModel::data(index, role);
    11. }
    To copy to clipboard, switch view to plain text mode 

    Cheers,
    _

Similar Threads

  1. Replies: 3
    Last Post: 3rd February 2014, 17:04
  2. Replies: 0
    Last Post: 10th September 2013, 11:05
  3. Replies: 4
    Last Post: 8th September 2011, 08:22
  4. Replies: 3
    Last Post: 22nd January 2010, 16:46
  5. Display Label Color by selecting Color Picker
    By sosanjay in forum Qt Programming
    Replies: 1
    Last Post: 25th September 2009, 06:11

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.