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
Forum Updated to NodeBB v4.3 + New Features

Model View alter display text

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 4 Posters 1.1k 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