Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Set background color to a cell of a tableView
Qt 6.11 is out! See what's new in the release blog

Set background color to a cell of a tableView

Scheduled Pinned Locked Moved General and Desktop
54 Posts 5 Posters 52.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    andre
    wrote on last edited by
    #28

    That is an easily made mistake, by the way. Always check the signature of the function if you think it doesn't get called.

    Then, in the slot in the proxy where you receive the rows to highlight, what you are actually doing is changing data in the model. You need to tell the world about such a change, by emitting the void dataChanged ( const QModelIndex & topLeft, const QModelIndex & bottomRight ) signal (defined in QAbstractItemModel). This way, the connected views know they need to update themselves.

    When you just hardcode the rows to highlight (for now), do you get a highlight then?

    1 Reply Last reply
    0
    • P Offline
      P Offline
      poporacer
      wrote on last edited by
      #29

      Ok, I changed the const reference. Now I get a row highlighted, but it is not the row with the lowest number.
      Gerolf, I am pretty sure this is because of the problem you identified
      " I see one problem in your code:
      you calculate highest / lowest value based on the proxy row,but in data ypou comparte to source row."
      I can't figure out how to use the proxy role in the MainClass or the source Role in the data function.
      I did get the following error:
      QSortFilterProxyModel: index from wrong model passed to mapToSource
      I just got home so I will take a look at these two errors. Does anything stick out to you?
      What triggers this proxy to be called?
      I think it would be a cleaner method to have the high and low highlighted in the proxy class. How might start this?

      1 Reply Last reply
      0
      • G Offline
        G Offline
        giesbert
        wrote on last edited by
        #30

        As you calculate high and low value based on the proxy index, you just should compare to the index without mapping it, like in the below code snippet.

        @
        QVariant MyProxyModel::data ( const QModelIndex & index, int role ) const
        {
        if (!index.isValid())
        return QVariant();
        if ( index.row() == m_highRow && role == Qt::BackgroundRole )
        {
        return QVariant( Qt::yellow );
        }
        else
        {
        return QSortFilterProxyModel::data( index, role );
        }
        }
        @

        you never need to call data directly for displaying data, that is done by the views.

        please step through your code to check, where the mapToSource throws the problem.

        I've also rewritten your sales calculation a bit, just to show a bit some things:
        ui->printView->model() ==> proxy

        @
        void MainClass::highlightCells()
        {
        float lowSales=FLT_MAX;
        float highSales=FLT_MIN;
        int rowHigh=0;
        int rowLow=0;
        int totalRows = 0;
        float currentSales;

        // this should be done only once! --> move it to the place where you create the proxy
        connect(this, SIGNAL(sendRows(int, int)), proxy, SLOT(getRows(int, int))); //to pass the rows to be highlighted to the proxy
        
        //get fastest and slowest sales and save row
        int numRows = proxy->rowCount();
        
        for (int r = 0; r < numRows; r++ )
        {
            if (ui->printView->isRowHidden(r)) // you hide rows from the view ???
                continue;
                
            currentSales = proxy->index(r,5).data(Qt::DisplayRole).toFloat();
            if (currentSales < lowSales)
            {
                lowSales = currentSales;
                rowLow = r;
            }
            
            if (currentSales > highSales)
            {
                highSales = currentSales;
                rowHigh = r;
            }
        }
        
        emit sendRows (rowSlow, rowFast);
        

        }
        @

        Nokia Certified Qt Specialist.
        Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

        1 Reply Last reply
        0
        • P Offline
          P Offline
          poporacer
          wrote on last edited by
          #31

          THANKS! I think I am starting to understand the model/view/delegate concept (very slightly!!!) I will continue to read about it so I can understand it better. I haven't been real successful in my search to get the answers on my own. I have just a couple of questions that I hope you would be so kind to answer. From the information I have gathered (and your insights) This is how I think this works. The Model is an interface between the data and "attaches" roles (background, foreground, font, etc) to the raw data. This will keep the roles persistent within the model so that any view will display the data appropriately? The view merely displays that data from the model with a few options available to the view (sort, column/row hidden, etc) Any changes to either the model or view will generate a signal to the other item so that they can update their data accordingly. You can have more than one model between the data and view for additional functionality.
          In my case the code that we have works like this? (I could be totally off course here) When the Model (in my case the sub-classed QSortFilterProxyModel) is getting the data from the base model (it steps through each item as it is added) and it checks the state of several items (valid Index, current role) then sets the role requested and returns the role variable back the the view so that it could be set appropriately? So with this, you can set any of the roles in ItemDataRole through this method? The index passed to the data function of the QSFPM is the index of the base model? And the MaptoSource function gets the index of the proxymodel? That is why you shouldn't use the model index as a persistent item as it is fluid and can change if any changes to the models or view have been made? (this might help other people to understand the concept as well)

          1 Reply Last reply
          0
          • G Offline
            G Offline
            giesbert
            wrote on last edited by
            #32

            [quote author="poporacer" date="1302473664"]THANKS! I think I am starting to understand the model/view/delegate concept (very slightly!!!) I will continue to read about it so I can understand it better. I haven't been real successful in my search to get the answers on my own. I have just a couple of questions that I hope you would be so kind to answer. From the information I have gathered (and your insights) This is how I think this works. The Model is an interface between the data and "attaches" roles (background, foreground, font, etc) to the raw data. This will keep the roles persistent within the model so that any view will display the data appropriately? [/quote]

            This is correct.

            [quote author="poporacer" date="1302473664"]The view merely displays that data from the model with a few options available to the view (sort, column/row hidden, etc) Any changes to either the model or view will generate a signal to the other item so that they can update their data accordingly.[/quote]

            This needs a bit correction:

            • Data changes in the model will be signaled, so all connected views update themselves.
            • Data changes done in a view are handled by a delegate which usually calls setData in the model (custommodels and custom delegates might differ here). The model then signals all connected views about the changes.

            [quote author="poporacer" date="1302473664"]You can have more than one model between the data and view for additional functionality.[/quote]

            I would rephrase this:

            • A view is connected to one model
            • A model can be a proxy model to add functionality, filtering etc.
            • Proxy models may contain models or proxy models, which means it is possible to cascade proxy models.

            [quote author="poporacer" date="1302473664"]In my case the code that we have works like this? (I could be totally off course here) When the Model (in my case the sub-classed QSortFilterProxyModel) is getting the data from the base model (it steps through each item as it is added) and it checks the state of several items (valid Index, current role) then sets the role requested and returns the role variable back the the view so that it could be set appropriately? [/quote]

            I'm not sure, whether I did not understand what you wrote or you had some misunderstanding. I try to say how it is normally:

            The view requests data based on a role and an index. If you have a proxy model, it converts the index to the source index and requests the data in the source model and returns it. In your case, you have some additional data in the proxy model. If the view requests this data, it is directly returned from the proxy model.

            With setData it is the same. The view directly writes to your proxy model and the proxy decides, whether the data is needed inside your proxy model (only if you have a derived proxy model) otherwise the index is converted and the source model setData is called.

            [quote author="poporacer" date="1302473664"]So with this, you can set any of the roles in ItemDataRole through this method? The index passed to the data function of the QSFPM is the index of the base model?[/quote]

            No, this is wrong. The view does not handle the source model indexes. From views point of view, there is only one model. It never checks, whether it is a proxy or not. You always get QSFPM indexes. If you then call the source model from QSFPM you have to call mapToSource yourself.

            [quote author="poporacer" date="1302473664"]And the MaptoSource function gets the index of the proxymodel? [/quote]

            Yes.

            [quote author="poporacer" date="1302473664"]That is why you shouldn't use the model index as a persistent item as it is fluid and can change if any changes to the models or view have been made? (this might help other people to understand the concept as well)[/quote]

            Incorrect. You can use QPersistentModelIndex for storing model indexes. The proxy models (and also source models) catch a list of persitant indexes and update them due to changes. A persitant index might become invalid later on, if a QSFPM filters out the element.

            Only QPersistentModelIndex may be stored inside your class for later usage.

            Nokia Certified Qt Specialist.
            Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

            1 Reply Last reply
            0
            • P Offline
              P Offline
              poporacer
              wrote on last edited by
              #33

              Well, I thought I had it figured out...then I sorted the table and the row that was highlighted in the view was still the same row that was highlighted before the sort. Not the correct row. Is there some signal I should be emitting or somehow capturing the sort routine? I looked at the QSortFilterProxyModel class and I didn't see any slots that would work. I thought the model retained the info for the data roles and the view would signal the changes and update the view. What am I missing?

              1 Reply Last reply
              0
              • A Offline
                A Offline
                andre
                wrote on last edited by
                #34

                My guess is, that you are now trying to let your proxy model do both the highlighting and the sorting, right? While that is possible, it complicates things a bit. You are now probably highlighting based on the row number for the requested index your proxy's data method, right? Well, sorting obviously changes the order of the rows, so those row numbers are not going to be valid anymore. You might, instead of triggering your highlight based on the requested row number, trigger it based on the row number of the source model that the row in the proxy model represents. For instance.

                However, what I would do, is just keep the proxy doing one thing. Simply don't use the sorting facilities of your proxy model (or better yet, disable them), and use a separate proxy for the sorting and the filtering. So you end up with:

                [Source model] -> [Highlight proxy] -> [Sort/filter proxy] -> [View]

                Downside is that a highlighted row might be filtered out this way. I guess if you want to filter too, you might even have to go for:

                [Source model] -> [Filter proxy] -> [Highlight proxy] -> [Sort proxy] -> [View]

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  giesbert
                  wrote on last edited by
                  #35

                  Hi,

                  I would go ab it another way:

                  [Source model] -> [Filter proxy] -> [Sort proxy] -> [Highlight proxy] -> [View]

                  if you sort the base model of the highlight model, the row indexes also change. This way it does not. :-)

                  Nokia Certified Qt Specialist.
                  Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    andre
                    wrote on last edited by
                    #36

                    But the problem with this order is, that the view by default will change the sort property on the model that it is displaying. In this case, that would be the Highlight proxy, while you want it to be the sort proxy. If you are going to have the filter and the sort proxies consecutive, you might as well use a single proxy to do the filtering and the sorting.

                    If the base model of the highlight proxy changes, it needs to re-query for the correct rows to highlight anyway. It would be the same if the base SQL model would be refreshed, for instance.

                    1 Reply Last reply
                    0
                    • I Offline
                      I Offline
                      ihtzudismqa
                      wrote on last edited by
                      #37

                      Hello,
                      I want to color a cell on a SqlRelationalTableModel.
                      The condition is, if the value of the cell is 1, I want it blue otherwise it should be red.
                      After reading the whole topic, I'm very confused. Could someone please help me out?
                      For example, how to start etc.
                      Is it the same way like poporacer did? "Just" inherit from QSortFilterProxyModel ?

                      Thanks in advice

                      1 Reply Last reply
                      0
                      • Z Offline
                        Z Offline
                        ZapB
                        wrote on last edited by
                        #38

                        Yes. The same method is applicable. Sub-class QSFPM and set it as a proxy between your source model and the view.

                        Nokia Certified Qt Specialist
                        Interested in hearing about Qt related work

                        1 Reply Last reply
                        0
                        • A Offline
                          A Offline
                          andre
                          wrote on last edited by
                          #39

                          Indeed, same idea, thought the implementation is obviously simpler. It is easier to determine value == 1 than it is to determine value == maximumValue, of course.

                          1 Reply Last reply
                          0
                          • P Offline
                            P Offline
                            poporacer
                            wrote on last edited by
                            #40

                            [quote author="Andre" date="1302589505"]My guess is, that you are now trying to let your proxy model do both the highlighting and the sorting, right? While that is possible, it complicates things a bit. You are now probably highlighting based on the row number for the requested index your proxy's data method, right? [/quote]

                            I guess that is correct because I am using the proxy model. I don't implement anything else in the proxy except for the highlight part (data function)

                            [quote author="Andre" date="1302589505"]Well, sorting obviously changes the order of the rows, so those row numbers are not going to be valid anymore. You might, instead of triggering your highlight based on the requested row number, trigger it based on the row number of the source model that the row in the proxy model represents. [/quote]

                            This seems like a clean method that would probably work. How would I do that?

                            [quote author="Andre" date="1302589505"] Simply don't use the sorting facilities of your proxy model (or better yet, disable them), and use a separate proxy for the sorting and the filtering. [/quote]

                            Since I only implement the data function in my proxy, I am not sure how to disable the sorting function in one proxy and implement it in another.

                            [quote author="Andre" date="1302589505"] So you end up with: [Source model] -> [Highlight proxy] -> [Sort/filter proxy] -> [View] Downside is that a highlighted row might be filtered out this way. I guess if you want to filter too, you might even have to go for: [Source model] -> [Filter proxy] -> [Highlight proxy] -> [Sort proxy] -> [View] [/quote]

                            So to implement this it would be something like this?
                            @printModel= new QSqlRelationalTableModel (this);
                            printModel-> setTable (mTableName); //or should this be called from sortProxy?
                            printModel->setFilter(mFilterString);//or should this be called from sortProxy?

                            filterproxy->setSourceModel(printModel);
                            proxy->setSourceModel(filterProxy);
                            sortProxy->setSourceModel(proxy);

                            ui->printView->setModel(sortProxy);

                            @

                            If the highlighted row is part of the view, can you identify the row and highlight the correct row via a setData function in the view and then capture the sort routine and then re-iterate through the view and make the appropriate color change? It seems like this is more difficult than it should be just to highlight an identified row. but if that is the way to do it, then I want to learn and understand how.

                            1 Reply Last reply
                            0
                            • I Offline
                              I Offline
                              ihtzudismqa
                              wrote on last edited by
                              #41

                              How can I link the query result which is placed in another class, with the variable(which is neccessary for the evaluating), from derived proxymodel class?

                              1 Reply Last reply
                              0
                              • Z Offline
                                Z Offline
                                ZapB
                                wrote on last edited by
                                #42

                                Can you explain that a little more fully please or even post some code? I think I understand but I could be off the mark.

                                Are you saying that you need some result from your query to be known in your prxoy for comparison? If so just add a member variable and a slot that sets it to your proxy and emit a signal from your query object that emits the needed value. Then connect the signal to the slot. In your slot you should also be sure to invalidate() the proxy.

                                Nokia Certified Qt Specialist
                                Interested in hearing about Qt related work

                                1 Reply Last reply
                                0
                                • I Offline
                                  I Offline
                                  ihtzudismqa
                                  wrote on last edited by
                                  #43

                                  Well,
                                  I have a SqlRelationalTableModel and one column which holds either 1 or 2, shown is the corresponding name. (From Sqlite Database)

                                  Like it's descripted in this thread, I have to inherit from QSortFilterProxyModel and override data().

                                  How do I implement it, that the "real" value behind the cell is going to be evaluated and not the name? Which way could be the best?

                                  It may sound confused, sorry for that. Can you understand my matter?

                                  1 Reply Last reply
                                  0
                                  • A Offline
                                    A Offline
                                    andre
                                    wrote on last edited by
                                    #44

                                    I think what you are after, is that you need to convert the model index that you have for the proxy model to the model index that you need for the source model. QSortFilterProxyModel has mapping methods for both ways. You need mapToSource. This allows you to get the model index for the source data model that corresponds to the item that data() is currently called for in your proxy model.

                                    @
                                    // in your data reimplementation
                                    if (role == Qt::BackgroundRole ) {
                                    sourceIndex = mapToSource(proxyIndex);
                                    if (sourceIndex.data(Qt::EditRole).toInt() == 1) {
                                    return QVariant(Qt::blue);
                                    }
                                    }
                                    @

                                    Or something like that.

                                    1 Reply Last reply
                                    0
                                    • I Offline
                                      I Offline
                                      ihtzudismqa
                                      wrote on last edited by
                                      #45

                                      I guess proxyIndex is equal to QModelIndex &index?

                                      1 Reply Last reply
                                      0
                                      • A Offline
                                        A Offline
                                        andre
                                        wrote on last edited by
                                        #46

                                        [quote author="ihtzudismqa" date="1302861095"]I guess proxyIndex is equal to QModelIndex &index?[/quote]

                                        Yes, sorry.

                                        1 Reply Last reply
                                        0
                                        • P Offline
                                          P Offline
                                          poporacer
                                          wrote on last edited by
                                          #47

                                          I have been reading to see if I can figure out how to get the table to be highlighted correctly after it is sorted but I have not been able to figure it out. I drew a blank with having four models as suggested but I did find something else that might work....but it isn't. I think I should be able to capture the signal from when the user clicks on the header and emit a signal to reload the table. Here is what I tried but when I debug, the signal does not get called.
                                          @QHeaderView *horizHeader;
                                          QSqlRelationalTableModel printModel;
                                          MyProxyModel
                                          proxy;

                                          printModel= new QSqlRelationalTableModel (this);
                                          printModel-> setTable (mTableName);
                                          printModel-> setRelation (2, QSqlRelation("name", "id", "LName"));

                                          printModel->select();
                                          proxy = new MyProxyModel(this);
                                          proxy->setSourceModel(printModel);
                                          ui->printView->setModel(proxy);
                                          horizHeader= ui->printView->horizontalHeader(); connect(horizHeader, SIGNAL(sortIndicatorChanged (int) ),
                                          proxy,SIGNAL(dataChanged ( ) ));
                                          @
                                          I am pretty sure it is because of the wrong syntax for the dataChanged signal, but I am not sure how to make it work. Will this work? Or am I going down the wrong path? Is the model method better? If so, how do I make it work? I have no clue on how to start.

                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved