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

model mapping issue

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 3 Posters 787 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.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #1

    I have an app build on the model/view framework. Various QWidgets display various parts of the model, and it's always been straightforward; usually I map a column to a QLineEdit or something like that:

        m_mapper->addMapping(ui->lineEditTimeZone, TAG_TIME_ZONE_CODE);
    

    Now, though, I'd like to do something a little more ambitious.

    The app interfaces to an embedded application, communicating via XML messages. One of my widgets displays a combo box for selecting time zones. The combo box is populated from this:

        typedef QMap<string, string> TimeZoneMap;
        TimeZoneMap timeZoneMap =
        {
            {"Pacific/Niue",	"NUT+11"},
            {"Pacific/Honolulu",	"HAST+10"},
            {"America/Anchorage",	"AKST+9AKDT,M3.2.0,M11.1.0"},
            {"America/Los_Angeles",	"PST+8PDT,M3.2.0,M11.1.0"},
    

    I want to display the key (eg "Pacific/Niue") to the user, but when I communicate with my embedded app, I use the value (eg "AKST+9AKDT,M3.2.0,M11.1.0"). So, when I initialize my widget, instead of mapping from a column, I have to translate that column from value to key, and map to that. Ideas?

    I hope this makes sense; I've been struggling with how to present this issue.

    JonBJ 1 Reply Last reply
    0
    • fcarneyF Offline
      fcarneyF Offline
      fcarney
      wrote on last edited by fcarney
      #2

      Is memory an issue? Because you could map it like you are. Then go through a pull every key/value out and add that back as an inverse map. It will take up more memory, but you only maintain one mapping by hand.

      Edit:
      This might be more efficient memory wise:
      https://stackoverflow.com/questions/21760343/is-there-a-more-efficient-implementation-for-a-bidirectional-map

      C++ is a perfectly valid school of magic.

      1 Reply Last reply
      0
      • mzimmersM mzimmers

        I have an app build on the model/view framework. Various QWidgets display various parts of the model, and it's always been straightforward; usually I map a column to a QLineEdit or something like that:

            m_mapper->addMapping(ui->lineEditTimeZone, TAG_TIME_ZONE_CODE);
        

        Now, though, I'd like to do something a little more ambitious.

        The app interfaces to an embedded application, communicating via XML messages. One of my widgets displays a combo box for selecting time zones. The combo box is populated from this:

            typedef QMap<string, string> TimeZoneMap;
            TimeZoneMap timeZoneMap =
            {
                {"Pacific/Niue",	"NUT+11"},
                {"Pacific/Honolulu",	"HAST+10"},
                {"America/Anchorage",	"AKST+9AKDT,M3.2.0,M11.1.0"},
                {"America/Los_Angeles",	"PST+8PDT,M3.2.0,M11.1.0"},
        

        I want to display the key (eg "Pacific/Niue") to the user, but when I communicate with my embedded app, I use the value (eg "AKST+9AKDT,M3.2.0,M11.1.0"). So, when I initialize my widget, instead of mapping from a column, I have to translate that column from value to key, and map to that. Ideas?

        I hope this makes sense; I've been struggling with how to present this issue.

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

        @mzimmers
        Just checking one thing: you are aware that QComboBoxes can display strings while returning a corresponding data value, which you could populate from your TimeZoneMap? I admit this has nothing to do with QDataMapperWidget, and I haven't seen that support it, so it's possibly quite unsuitable for what you want to do, but just checking?

        1 Reply Last reply
        0
        • fcarneyF Offline
          fcarneyF Offline
          fcarney
          wrote on last edited by
          #4

          Heh, for fun I wanted to see what it would take to make an efficient dual mapped QMap:

          {
                  // two way map
                  using DualMap = QMap<QString, const QString*>;
                  DualMap map;
          
                  auto insert = [](DualMap& map, QString key, QString val){
                      auto km = map.insert(key, nullptr);
                      auto kmp = &(km.key());
                      auto vm = map.insert(val, nullptr);
                      auto vmp = &(vm.key());
                      *km = vmp;
                      *vm = kmp;
                  };
                  auto retrieve = [](DualMap& map, QString key)->QString{
                      return *(map.value(key));
                  };
          
                  insert(map, "one","1");
                  insert(map, "two","2");
                  qInfo() << retrieve(map, "one") << retrieve(map, "1");
                  qInfo() << retrieve(map, "two") << retrieve(map, "2");
          }
          

          Probably would be better to put this in a generic class though.

          C++ is a perfectly valid school of magic.

          1 Reply Last reply
          0
          • mzimmersM Offline
            mzimmersM Offline
            mzimmers
            wrote on last edited by mzimmers
            #5

            Trying to keep the solution understandable to my simple mind, I tried this:

                int index;
                QVariant qv;
                QString qs;
             
                qv = m_modelDevices->getModel()->data(*qmi);
                qs = (qv.toString());
                string k = m_timeZoneMap.key(qs.toStdString());
                it = m_timeZoneMap.find(k);
            

            only to discover that QMap iterators are bidirectional, not random access, so this line is illegal:

            index = it - m_timeZoneMap.begin();
            

            So, I'm not sure where to go from here. I could just increment through an interator until I get the one I want, but that seems quite wasteful, even in this day and age of super-fast processors. Maybe a QMap isn't the right container for this after all...?

            EDIT: found a solution. It's probably not super CPU efficient, but it works:

                index = distance(m_timeZoneMap.begin(), it);
            

            Seems to work now. Not a perfect solution, and I don't actually use the mapper, but it works. Thanks to all who looked at this.

            JonBJ 1 Reply Last reply
            0
            • mzimmersM mzimmers

              Trying to keep the solution understandable to my simple mind, I tried this:

                  int index;
                  QVariant qv;
                  QString qs;
               
                  qv = m_modelDevices->getModel()->data(*qmi);
                  qs = (qv.toString());
                  string k = m_timeZoneMap.key(qs.toStdString());
                  it = m_timeZoneMap.find(k);
              

              only to discover that QMap iterators are bidirectional, not random access, so this line is illegal:

              index = it - m_timeZoneMap.begin();
              

              So, I'm not sure where to go from here. I could just increment through an interator until I get the one I want, but that seems quite wasteful, even in this day and age of super-fast processors. Maybe a QMap isn't the right container for this after all...?

              EDIT: found a solution. It's probably not super CPU efficient, but it works:

                  index = distance(m_timeZoneMap.begin(), it);
              

              Seems to work now. Not a perfect solution, and I don't actually use the mapper, but it works. Thanks to all who looked at this.

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

              @mzimmers
              Can you remind me when you even need to map from "extended TZ syntax" value back to "friendly name" column? So far you have only said you have a combo where you want to display the latter but send the former to the embedded app.

              mzimmersM 1 Reply Last reply
              0
              • JonBJ JonB

                @mzimmers
                Can you remind me when you even need to map from "extended TZ syntax" value back to "friendly name" column? So far you have only said you have a combo where you want to display the latter but send the former to the embedded app.

                mzimmersM Offline
                mzimmersM Offline
                mzimmers
                wrote on last edited by
                #7

                @JonB my Qt app is a utility for communicating with an embedded device for status, configuration and the like. The time zone software on the embedded system doesn't support use of the user-friendly strings, which I want to use in my Qt app.

                So, the easiest thing seemed to be to present the user-friendly strings (the keys in my map) on Qt, but use the TZ strings (the values) for communication with the embedded system. As an alternative, I could copy my map to the embedded system, but then I'd have to concern myself with field updates, keeping everything in sync, and so on.

                JonBJ 1 Reply Last reply
                0
                • mzimmersM mzimmers

                  @JonB my Qt app is a utility for communicating with an embedded device for status, configuration and the like. The time zone software on the embedded system doesn't support use of the user-friendly strings, which I want to use in my Qt app.

                  So, the easiest thing seemed to be to present the user-friendly strings (the keys in my map) on Qt, but use the TZ strings (the values) for communication with the embedded system. As an alternative, I could copy my map to the embedded system, but then I'd have to concern myself with field updates, keeping everything in sync, and so on.

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

                  @mzimmers
                  I understand the embedded cannot handle the friendly names. I understand you need a mapping in the UI app from user friendly names to the tz stuff to send to the embedded app.

                  What I still don't understand is where/why you need to back from the tz spec in the second column to the friendly name in the first column?

                  mzimmersM 1 Reply Last reply
                  0
                  • JonBJ JonB

                    @mzimmers
                    I understand the embedded cannot handle the friendly names. I understand you need a mapping in the UI app from user friendly names to the tz stuff to send to the embedded app.

                    What I still don't understand is where/why you need to back from the tz spec in the second column to the friendly name in the first column?

                    mzimmersM Offline
                    mzimmersM Offline
                    mzimmers
                    wrote on last edited by
                    #9

                    @JonB oh: when I bring up the display below, I populate all the fields with information from the embedded device. In the case of the time zone, it comes in as a TZ string, so I have to convert it to the user-friendly string for display.

                    wb_util.PNG

                    JonBJ 1 Reply Last reply
                    0
                    • mzimmersM mzimmers

                      @JonB oh: when I bring up the display below, I populate all the fields with information from the embedded device. In the case of the time zone, it comes in as a TZ string, so I have to convert it to the user-friendly string for display.

                      wb_util.PNG

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

                      @mzimmers
                      OK.

                      So, personally, I'd do it in 5 minutes. I wouldn't bother with any map at all, I don't know how that plays with your data widget mapper or model.

                      Like I said earlier, QComboBox has addItem(const QString &text, const QVariant &userData = QVariant()) for associated data value against string display, and int QComboBox::findData(const QVariant &data, ...). I would leverage that existing support. I'd just store the friendly name string with the tz-format string as data, and use findData() to back-map.

                      Is it as efficient at back-mapping as a map would be? No, it's doubtless just a sequential search of the combo items. Of which you have some hundreds? I can't believe that looking through those once when initially populating a combobox is in practice going to lead your app to a grinding halt and upset your users? And you could be getting on with other coding :)

                      mzimmersM 1 Reply Last reply
                      2
                      • JonBJ JonB

                        @mzimmers
                        OK.

                        So, personally, I'd do it in 5 minutes. I wouldn't bother with any map at all, I don't know how that plays with your data widget mapper or model.

                        Like I said earlier, QComboBox has addItem(const QString &text, const QVariant &userData = QVariant()) for associated data value against string display, and int QComboBox::findData(const QVariant &data, ...). I would leverage that existing support. I'd just store the friendly name string with the tz-format string as data, and use findData() to back-map.

                        Is it as efficient at back-mapping as a map would be? No, it's doubtless just a sequential search of the combo items. Of which you have some hundreds? I can't believe that looking through those once when initially populating a combobox is in practice going to lead your app to a grinding halt and upset your users? And you could be getting on with other coding :)

                        mzimmersM Offline
                        mzimmersM Offline
                        mzimmers
                        wrote on last edited by
                        #11

                        @JonB I agree; your way is simpler. I left the original data as a QMap (didn't feel like changing it), but the combo box population is simpler now:

                            // populate the timezone combo box.
                            for (it = m_timeZoneMap.begin(); it != m_timeZoneMap.end(); ++ it)
                            {
                                ui->comboBoxTimeZone->addItem(it.key(), it.value());
                            }
                        

                        Setting the current index:

                          // set the timezone combo box index.
                            m_modelDevices->getModel()->data(*m_qmi);
                            row = m_qmi->row();
                            column = TAG_TIME_ZONE_CODE;
                            *m_qmi = m_modelDevices->getModel()->index(row, column);
                            qv = m_modelDevices->getModel()->data(*m_qmi);
                            index = ui->comboBoxTimeZone->findData(qv);
                            ui->comboBoxTimeZone->setCurrentIndex(index);
                        

                        And retrieving the data for sending to the embedded device:

                                s = ui->comboBoxTimeZone->currentData().toString().toStdString();
                                msg.add(TAG_TIME_ZONE_CODE, s);
                        

                        Thanks for the suggestion.

                        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