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. Model View alter display text

Model View alter display text

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 4 Posters 1.2k Views 2 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.
  • JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by JonB
    #1

    I have a model (QStandardItemModel-derived) and a view (QTableView-derived). I wish to alter the displayed text for certain rows which hold a numeric to show as percentage, e.g. 30 -> 30%. (The principle here would apply to any other transformation, e.g. $30 or (30) for accountancy negative numbers, and is not uncommon in tables displaying, say, numeric values)

    I used to accomplish this by overriding data(const QModelIndex &index, int role = Qt::DisplayRole) const having it go essentially:

    if (role == Qt::DisplayRole)
        if (index.row() == percentRow)
        {
            int val = Base::data(index, role).toInt();
            return QString("%1%").arg(val);
        }
    

    i.e. making it return the string I wanted instead of the numeric. This was easy and I could do it in 30 seconds.

    I was told in no uncertain terms by experts here that this was wicked, I must leave the data type returned as-was for all sorts of reasons, not convert to string here. I should use QStyledItemDelegate for this. Fair enough.

    I come to do that now and was assuming I could use QString QStyledItemDelegate::displayText(const QVariant &value, const QLocale &locale) const, which would not have been too bad. However I now see that does not convey the QModelIndex, so I cannot select by row/column.

    Which means I seem to be left with overriding void QStyledItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const, and doing quite a bit of work there (converting to string and dealing with painters).

    Is this really what I have to do to alter the string displayed for a number? Seems crazy to me to be going down into painters :( There isn't anything I can do via the QStyleOptionViewItem &option, is there? Nor can I get a displayText() override to know about the QModelIndex, can I?

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by VRonin
      #6

      initStyleOption is also virtual so you can do the chage directly there with minimal effort.

      class ListviewDelegate : public QStyledItemDelegate{
          Q_OBJECT
          Q_DISABLE_COPY_MOVE(ListviewDelegate)
      public:
          explicit ListviewDelegate(QObject* parent = nullptr)
              : QStyledItemDelegate(parent)
          {}
      protected:
          void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override{
              QStyledItemDelegate::initStyleOption(option,index);
              if (index.row() == percentRow)
                  option->text += QChar('%');
          }
      };
      

      if you need to do anything more fancy to the text you can just use option->text = doSomethingFancy(displayText(index.data(Qt::DisplayRole), option->locale));

      "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
      4
      • B Offline
        B Offline
        Bonnie
        wrote on last edited by
        #2

        I'm not a expert but returning a QString looks fine to me. :)

        JonBJ 1 Reply Last reply
        0
        • B Bonnie

          I'm not a expert but returning a QString looks fine to me. :)

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

          @Bonnie
          I wish! I got beyond shouted out (nicely) by expert people here saying I should be boiled in oil :) Not quite, but they were very firm on "don't change the return type of Qt::DisplayRole, it isn't intended for this at all, and the only time it should differ from Qt::EditRole is as an example where you are doing a spreadsheet and you have the display role showing a calculated result number while the edit role is the text of a formula". A quite different type of situation. For output like this the way to do is through a item delegate, only. Model code must not concern with output format. I posted an explicit question about just this and gracefully accepted their answers, and promised I would adhere to it next time I wrote code... :)

          Lemme see if I can find it:

          1 Reply Last reply
          0
          • mrjjM Offline
            mrjjM Offline
            mrjj
            Lifetime Qt Champion
            wrote on last edited by
            #4

            Hi
            Its not that much painter code to append %

            void ListviewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                                         const QModelIndex &index) const
            {
            
            
                QStyleOptionViewItem nonConstOption(option);
                initStyleOption(&nonConstOption, index);
                int val = 66;// get from model
                nonConstOption.text = QString("%1%").arg(val);
                QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &nonConstOption, painter, nullptr);
            }
            
            
            JonBJ 1 Reply Last reply
            1
            • mrjjM mrjj

              Hi
              Its not that much painter code to append %

              void ListviewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                                           const QModelIndex &index) const
              {
              
              
                  QStyleOptionViewItem nonConstOption(option);
                  initStyleOption(&nonConstOption, index);
                  int val = 66;// get from model
                  nonConstOption.text = QString("%1%").arg(val);
                  QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &nonConstOption, painter, nullptr);
              }
              
              
              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #5

              @mrjj
              Thank you for supplying this. Looks to me like some damn hairy code to append a % to a number :)

              I need to look through the docs for this tomorrow to understand what is going on. Since I won't want to interfere with whatever paint() does or does not do for all other cases, I guess I'll want something like:

              if (index.row() == percentRow)
              {
                  QVariant v = data(index);
                  if (v.somethingAboutTypeIsNumber())
                  {
                      ( your code, using  QString("%1%").arg(v);, but I don't think that accepts a QVariant )
                      return;
                  }
              }
              QStyledItemDelegate::paint(painter, option, index);
              

              Good grief, this is getting hard for one darned % character...! :(

              1 Reply Last reply
              0
              • VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by VRonin
                #6

                initStyleOption is also virtual so you can do the chage directly there with minimal effort.

                class ListviewDelegate : public QStyledItemDelegate{
                    Q_OBJECT
                    Q_DISABLE_COPY_MOVE(ListviewDelegate)
                public:
                    explicit ListviewDelegate(QObject* parent = nullptr)
                        : QStyledItemDelegate(parent)
                    {}
                protected:
                    void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override{
                        QStyledItemDelegate::initStyleOption(option,index);
                        if (index.row() == percentRow)
                            option->text += QChar('%');
                    }
                };
                

                if you need to do anything more fancy to the text you can just use option->text = doSomethingFancy(displayText(index.data(Qt::DisplayRole), option->locale));

                "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
                4
                • VRoninV VRonin

                  initStyleOption is also virtual so you can do the chage directly there with minimal effort.

                  class ListviewDelegate : public QStyledItemDelegate{
                      Q_OBJECT
                      Q_DISABLE_COPY_MOVE(ListviewDelegate)
                  public:
                      explicit ListviewDelegate(QObject* parent = nullptr)
                          : QStyledItemDelegate(parent)
                      {}
                  protected:
                      void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override{
                          QStyledItemDelegate::initStyleOption(option,index);
                          if (index.row() == percentRow)
                              option->text += QChar('%');
                      }
                  };
                  

                  if you need to do anything more fancy to the text you can just use option->text = doSomethingFancy(displayText(index.data(Qt::DisplayRole), option->locale));

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

                  @VRonin
                  Thank you, this looks much more like a reasonable approach! No offence to @mrjj's :) I will go investigate this now and report back....

                  ...and I am pleased to report this works as desired, and in a reasonable code fashion. The secret was indeed that initStyleOption() is virtual.

                  1 Reply Last reply
                  1

                  • Login

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