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. get the content from a tableview and change it

get the content from a tableview and change it

Scheduled Pinned Locked Moved Unsolved General and Desktop
14 Posts 3 Posters 1.3k Views
  • 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.
  • M Mogli123

    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

    JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by JonB
    #2

    @Mogli123
    In your QSqlQueryModel::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's Qt::DisplayRole, and that's OK.

    However, in your second example to return a cell's Qt::DisplayRole you look at another cell's Qt::DisplayRole, the same role. Now if you think about it, that causes a potentially "infinite recursion", because when you look at the other cell's Qt::DisplayRole you will be re-executing the same pathway in your TableCustomise::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's Qt::DisplayRole value. That can't be right: it needs to stop somewhere. Perhaps this only applies where index.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!

    1 Reply Last reply
    1
    • M Offline
      M Offline
      Mogli123
      wrote on last edited by Mogli123
      #3

      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 column

      Furthermore is it possible to split the two funktions above?
      I dont't want the two code in the same method

      JonBJ 1 Reply Last reply
      0
      • M Mogli123

        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 column

        Furthermore is it possible to split the two funktions above?
        I dont't want the two code in the same method

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #4

        @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 when index.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 same TableCustomise::data() code to read the Qt::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 base QSqlQueryModel::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 your TableCustomise::data() if called with that as role go

        if (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 method

        Sorry, 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....!

        VRoninV 1 Reply Last reply
        0
        • JonBJ JonB

          @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 when index.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 same TableCustomise::data() code to read the Qt::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 base QSqlQueryModel::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 your TableCustomise::data() if called with that as role go

          if (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 method

          Sorry, 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....!

          VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #5

          2 minor notes:
          index.sibling(index.row(), index.column()) is index

          @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);

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          JonBJ 1 Reply Last reply
          1
          • VRoninV VRonin

            2 minor notes:
            index.sibling(index.row(), index.column()) is index

            @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);

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #6

            @VRonin

            index.sibling(index.row(), index.column()) is index

            What does this mean? QModelIndex::sibling() returns some (next?) "sibling" of index, 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 by index, 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.... :(

            VRoninV 1 Reply Last reply
            0
            • M Offline
              M Offline
              Mogli123
              wrote on last edited by
              #7

              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.

              JonBJ 1 Reply Last reply
              0
              • M Mogli123

                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.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #8

                @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 (use role == Qt::DisplayRole()) like your second example, or both, or what?

                1 Reply Last reply
                1
                • M Offline
                  M Offline
                  Mogli123
                  wrote on last edited by Mogli123
                  #9

                  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 example

                  I 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

                  JonBJ 1 Reply Last reply
                  0
                  • M Mogli123

                    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 example

                    I 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

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by
                    #10

                    @Mogli123
                    My literally last scribbled ideas:

                    • You will need your function to have two cases, one for role == Qt::BackgroundRole and another for Qt::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 the Qt::DisplayRole() only for column 0.

                    • Do not examine the value of column 0 itself when calculating, as you may recurse infinitely.

                    1 Reply Last reply
                    1
                    • JonBJ JonB

                      @VRonin

                      index.sibling(index.row(), index.column()) is index

                      What does this mean? QModelIndex::sibling() returns some (next?) "sibling" of index, 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 by index, 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.... :(

                      VRoninV Offline
                      VRoninV Offline
                      VRonin
                      wrote on last edited by
                      #11

                      @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

                      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                      ~Napoleon Bonaparte

                      On a crusade to banish setIndexWidget() from the holy land of Qt

                      1 Reply Last reply
                      2
                      • M Offline
                        M Offline
                        Mogli123
                        wrote on last edited by
                        #12

                        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

                        JonBJ 1 Reply Last reply
                        0
                        • M Mogli123

                          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

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by
                          #13

                          @Mogli123
                          You cannot "separate the methods", per se.

                          The way Qt works is that its infrastructure always calls QSqlQueryModel::data(index, role) (and thus your TableCustomise::data() override) for different attributes/effects/results, passing in varying values for role 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 a switch 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 ...;
                          }
                          
                          1 Reply Last reply
                          3
                          • M Offline
                            M Offline
                            Mogli123
                            wrote on last edited by
                            #14

                            Thank you very much

                            that looks great

                            I will trie it

                            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