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. Conversion from QFlags<> to QVariant could be easier
Forum Updated to NodeBB v4.3 + New Features

Conversion from QFlags<> to QVariant could be easier

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 4 Posters 2.4k Views 3 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.
  • R Offline
    R Offline
    Robert Hairgrove
    wrote on last edited by Robert Hairgrove
    #1

    Consider the following code snippet from a run-of-the-mill implementation of the data() function by a class which inherits QAbstractItemModel:

    QVariant MyModel::data(const QModelIndex &index, int role) const
    {
      QVariant retval;
      // this doesn't compile ... I am told by the compiler: 
      // "error: ‘template<class T> class QFlags’ used without template parameters"
      // QFlags::Int i = 0;
      // ...but this does:
      uint i = 0;
      if (index.isValid()) {
        int row = index.row();
        int col = index.column();
        switch (role) {
        case Qt::TextAlignmentRole:
          switch(col) {
          case 0:
            // this doesn't compile: 
            //   "error: no match for ‘operator=’ 
            //   (operand types are ‘QVariant’ and ‘QFlags<Qt::AlignmentFlag>’)":
            // retval = Qt::AlignLeft | Qt::AlignVCenter;
            // but this compiles:
            i = Qt::AlignLeft | Qt::AlignVCenter;
            retval = i;
            break;
          default:
            i = Qt::AlignHCenter | Qt::AlignVCenter;
            retval = i;
            break;
          }
          break;
        case Qt::DisplayRole:
        // etc.
    

    Since this idiom is used in so many places, I wouldn't think that it would be necessary to store a QFlags<> value instantiated with any native Qt types in a temporary variable just so that I can write it to a QVariant; there should be a QFlags::operator QVariant() or something.

    Now I noticed that there is a typedef QFlags::Int which is supposed to resolve either to signed or unsigned int depending on how it is implemented. But I haven't figured out how to use it, so I take my chances with unsigned int and hope that I never have to compare it with a signed value anywhere.

    Is there a better way to do this?

    (EDIT: OK, I need to define i like this, then it will be the correct type:

    QFlags<Qt::AlignmentFlag>::Int i = 0;
    

    but I am still stuck with an intermediate variable I really shouldn't need...

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      What about QVariant::fromValue(Qt::AlignHCenter | Qt::AlignVCenter)?

      (Z(:^

      R 1 Reply Last reply
      1
      • sierdzioS sierdzio

        What about QVariant::fromValue(Qt::AlignHCenter | Qt::AlignVCenter)?

        R Offline
        R Offline
        Robert Hairgrove
        wrote on last edited by
        #3

        @sierdzio : It compiles, but it doesn't seem to work correctly ... everything is left-aligned and vertically top-aligned when I set the return value like this. When I cast it to an integer before setting the QVariant return value, it works correctly. I really don't know what is happening; however, I suspect that the Qt::AlignmentFlag just doesn't have any metadata associated with it which might tell QVariant how to convert it (either directly or by using QVariant::fromValue()). The reverse conversion using the templated QVariant::value<>() function also fails to convert it correctly.

        1 Reply Last reply
        0
        • Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

          If nothing helps why not just write your own toVariant(QFlags<>) - function?

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          1 Reply Last reply
          3
          • Chris KawaC Offline
            Chris KawaC Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Don't assume ints or uints. There's a typedef for that and conversion operators.
            It's a bit of a mouthful but the "correct" way to convert flags to and from variant is:

            Qt::Alignment original = Qt::AlignLeft | Qt::AlignVCenter;
            
            QVariant v = static_cast<Qt::Alignment::Int>(original);
            
            Qt::Alignment retrieved = static_cast<Qt::Alignment>(v.value<Qt::Alignment::Int>());
            

            so in your case it would look like this in the data() method:

            retval = static_cast<Qt::Alignment::Int>(Qt::AlignLeft | Qt::AlignVCenter);
            

            and then on the receiving end:

            Qt::Alignment a = static_cast<Qt::Alignment>(index.data(role).value<Qt::Alignment::Int>());
            
            R 1 Reply Last reply
            3
            • Chris KawaC Chris Kawa

              Don't assume ints or uints. There's a typedef for that and conversion operators.
              It's a bit of a mouthful but the "correct" way to convert flags to and from variant is:

              Qt::Alignment original = Qt::AlignLeft | Qt::AlignVCenter;
              
              QVariant v = static_cast<Qt::Alignment::Int>(original);
              
              Qt::Alignment retrieved = static_cast<Qt::Alignment>(v.value<Qt::Alignment::Int>());
              

              so in your case it would look like this in the data() method:

              retval = static_cast<Qt::Alignment::Int>(Qt::AlignLeft | Qt::AlignVCenter);
              

              and then on the receiving end:

              Qt::Alignment a = static_cast<Qt::Alignment>(index.data(role).value<Qt::Alignment::Int>());
              
              R Offline
              R Offline
              Robert Hairgrove
              wrote on last edited by
              #6

              @chris-kawa : Thank you for the detailed explanation. It is a little less typing to write

              Qt::Alignment::Int
              

              instead of

              QFlags<Qt::AlignmentFlag>::Int
              

              Maybe I will take Christian Ehrlicher's advice and write the toVariant() function? It sounds like a good idea. I was just wondering why this isn't already built into the QVariant class?

              Chris KawaC 1 Reply Last reply
              0
              • R Robert Hairgrove

                @chris-kawa : Thank you for the detailed explanation. It is a little less typing to write

                Qt::Alignment::Int
                

                instead of

                QFlags<Qt::AlignmentFlag>::Int
                

                Maybe I will take Christian Ehrlicher's advice and write the toVariant() function? It sounds like a good idea. I was just wondering why this isn't already built into the QVariant class?

                Chris KawaC Offline
                Chris KawaC Offline
                Chris Kawa
                Lifetime Qt Champion
                wrote on last edited by
                #7

                @robert-hairgrove said in Conversion from QFlags<> to QVariant could be easier:

                I was just wondering why this isn't already built into the QVariant class?

                QFlags is a template so QVariant would have to support all possible specializations, for all possible enum types, which is unrealistic.
                It could be supported on the QFlags side with something like toVariant() and fromVariant(), but if you take a step back this doesn't scale well, because then why not toString, toDouble, toWhatever?

                The best place for this IMO would be outside both QVariant and QFlags, with a function template that would basically do the casts I mentioned. My guess is it's not in Qt because nobody felt like this was big enough of a deal and it wouldn't even be that much shorter either.

                Anyway, those are basically one-liners, so you can easily provide them yourself if you feel like it.

                R 1 Reply Last reply
                1
                • Chris KawaC Chris Kawa

                  @robert-hairgrove said in Conversion from QFlags<> to QVariant could be easier:

                  I was just wondering why this isn't already built into the QVariant class?

                  QFlags is a template so QVariant would have to support all possible specializations, for all possible enum types, which is unrealistic.
                  It could be supported on the QFlags side with something like toVariant() and fromVariant(), but if you take a step back this doesn't scale well, because then why not toString, toDouble, toWhatever?

                  The best place for this IMO would be outside both QVariant and QFlags, with a function template that would basically do the casts I mentioned. My guess is it's not in Qt because nobody felt like this was big enough of a deal and it wouldn't even be that much shorter either.

                  Anyway, those are basically one-liners, so you can easily provide them yourself if you feel like it.

                  R Offline
                  R Offline
                  Robert Hairgrove
                  wrote on last edited by
                  #8

                  @chris-kawa Thank you.

                  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