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. Interesting effect with tr().arg()

Interesting effect with tr().arg()

Scheduled Pinned Locked Moved Solved General and Desktop
14 Posts 5 Posters 5.5k 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.
  • C ChrisVT
    21 Jun 2018, 10:44

    Hi all,

    I observed an interesting issue with tr().arg() a minute ago - I do have a work-around but wonder if this is actually a bug. Opinions of course welcome.

    Suppose you do the following:

    tr("%1%2%3").arg("A").arg("%2A").arg("B")

    The expected outcome is "A%2AB", right? Well, the "%" in the second arg() seems to throw the replacement algorithm off, because the actual result is "ABA%3".

    My workaround is to put the "%"-containing text as the last arg(), then it works:

    tr("%1%3%2").arg("A").arg("B").arg("%2A").

    It seem to me that the text in an arg should not affect how the args are treated for tr().

    Best,
    Chris

    J Offline
    J Offline
    JonB
    wrote on 21 Jun 2018, 11:26 last edited by
    #2

    @ChrisVT
    Firstly, I can't see how this can have anything to do with tr() function. As per http://doc.qt.io/qt-5/qobject.html#tr, QObject::tr() simply returns a QString, only then does it evaluate the .arg()s, so the whole thing is simply QString::arg() calls, forget about tr().

    • Check what plain tr("%1%2%3") returns?
    • Check what QString("%1%2%3").arg("A").arg("%2A").arg("B") returns?
    C 1 Reply Last reply 21 Jun 2018, 13:19
    1
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 21 Jun 2018, 12:03 last edited by
      #3

      Hi,

      There's a warning about that in QString's documentation

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • C ChrisVT
        21 Jun 2018, 10:44

        Hi all,

        I observed an interesting issue with tr().arg() a minute ago - I do have a work-around but wonder if this is actually a bug. Opinions of course welcome.

        Suppose you do the following:

        tr("%1%2%3").arg("A").arg("%2A").arg("B")

        The expected outcome is "A%2AB", right? Well, the "%" in the second arg() seems to throw the replacement algorithm off, because the actual result is "ABA%3".

        My workaround is to put the "%"-containing text as the last arg(), then it works:

        tr("%1%3%2").arg("A").arg("B").arg("%2A").

        It seem to me that the text in an arg should not affect how the args are treated for tr().

        Best,
        Chris

        J Offline
        J Offline
        joeQ
        wrote on 21 Jun 2018, 12:32 last edited by joeQ
        #4

        @ChrisVT Hi,Friend,Welcome.

        You can write some test code, to find why. It is interesting.

        Do not omit Intermediate results.

        You will clear well from following snippet:

        #include <QCoreApplication>
        
        #include <QtCore/QDebug>
        
        int main(int argc, char *argv[])
        {
            QCoreApplication a(argc, argv);
            qDebug() << QObject::tr("%1%2%3"); /// %1%2%3
            qDebug() << QObject::tr("%1%2%3").arg("A"); /// A%2%3
        
            qDebug() << QObject::tr("%2%3").arg("A"); ///A%3
        
            qDebug() << QObject::tr("%1%2%3").arg("A").arg("%2A"); /// A%2A%3
            qDebug() << QObject::tr("%1%2%3").arg("A").arg("%2A").arg("B"); /// ABA%3
            // To replace First %, is %1=>A, result is tr(A%2%3).arg(%2A).arg(B) 
            // In Result To replace First %, is %2=>%2, result is (A%2A%3).arg(B)
            // In Result To replace First %, is %2=>B, result is ABA%3
        
            return a.exec();
        }
        
        

        Just do it!

        J 1 Reply Last reply 21 Jun 2018, 13:01
        0
        • V Offline
          V Offline
          VRonin
          wrote on 21 Jun 2018, 12:39 last edited by
          #5

          I discussed in the past this and also the season why you should only use arg(QString) and not the other overloads

          "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

          C 1 Reply Last reply 21 Jun 2018, 13:28
          2
          • J joeQ
            21 Jun 2018, 12:32

            @ChrisVT Hi,Friend,Welcome.

            You can write some test code, to find why. It is interesting.

            Do not omit Intermediate results.

            You will clear well from following snippet:

            #include <QCoreApplication>
            
            #include <QtCore/QDebug>
            
            int main(int argc, char *argv[])
            {
                QCoreApplication a(argc, argv);
                qDebug() << QObject::tr("%1%2%3"); /// %1%2%3
                qDebug() << QObject::tr("%1%2%3").arg("A"); /// A%2%3
            
                qDebug() << QObject::tr("%2%3").arg("A"); ///A%3
            
                qDebug() << QObject::tr("%1%2%3").arg("A").arg("%2A"); /// A%2A%3
                qDebug() << QObject::tr("%1%2%3").arg("A").arg("%2A").arg("B"); /// ABA%3
                // To replace First %, is %1=>A, result is tr(A%2%3).arg(%2A).arg(B) 
                // In Result To replace First %, is %2=>%2, result is (A%2A%3).arg(B)
                // In Result To replace First %, is %2=>B, result is ABA%3
            
                return a.exec();
            }
            
            
            J Offline
            J Offline
            JonB
            wrote on 21 Jun 2018, 13:01 last edited by
            #6

            @joeQ
            I still don't get how this behaviour is anything to do with using QObject::tr(), in your examples and this thread title? I can't test because I don't use C++, but wouldn't your examples behave just the same if you used QString in place of QObject::tr? The arg()s are evaluated after the tr(), not before, aren't they?

            1 Reply Last reply
            1
            • J Offline
              J Offline
              JonB
              wrote on 21 Jun 2018, 13:17 last edited by JonB
              #7

              Further to what I have written above, and to @VRonin 's post:

              ISTM that you should never use qString.arg().arg(). The chained args, which work on the substituted result from the previous arg() calls, are far too dangerous. [You wouldn't use C's sprint(format) with a non-literal format string for the same kind of reason, would you?]

              Like with sprintf, or repeated replaces or regular expression substitutions, you can only afford to use a substituter which works from a single, original string specifying what to do, not one affected by a previous substitution. You need a function which does multiple substitutions at the same time, not one after the other, to be safe.

              So I don't see/where is Qt's QString::argList() function, so you can go like: QString("%1%2%3")::argList(arg1, arg2, arg3), which is what you need to do?

              V 1 Reply Last reply 21 Jun 2018, 13:21
              0
              • J JonB
                21 Jun 2018, 11:26

                @ChrisVT
                Firstly, I can't see how this can have anything to do with tr() function. As per http://doc.qt.io/qt-5/qobject.html#tr, QObject::tr() simply returns a QString, only then does it evaluate the .arg()s, so the whole thing is simply QString::arg() calls, forget about tr().

                • Check what plain tr("%1%2%3") returns?
                • Check what QString("%1%2%3").arg("A").arg("%2A").arg("B") returns?
                C Offline
                C Offline
                ChrisVT
                wrote on 21 Jun 2018, 13:19 last edited by
                #8

                @JonB Correct, this has nothing to do with tr(). This was just the way I used it in my original code, and I didn't remove it. Sorry. The problem also occurs with QString.

                1 Reply Last reply
                1
                • J JonB
                  21 Jun 2018, 13:17

                  Further to what I have written above, and to @VRonin 's post:

                  ISTM that you should never use qString.arg().arg(). The chained args, which work on the substituted result from the previous arg() calls, are far too dangerous. [You wouldn't use C's sprint(format) with a non-literal format string for the same kind of reason, would you?]

                  Like with sprintf, or repeated replaces or regular expression substitutions, you can only afford to use a substituter which works from a single, original string specifying what to do, not one affected by a previous substitution. You need a function which does multiple substitutions at the same time, not one after the other, to be safe.

                  So I don't see/where is Qt's QString::argList() function, so you can go like: QString("%1%2%3")::argList(arg1, arg2, arg3), which is what you need to do?

                  V Offline
                  V Offline
                  VRonin
                  wrote on 21 Jun 2018, 13:21 last edited by
                  #9

                  @JonB said in Interesting effect with tr().arg():

                  You need a function which does multiple substitutions at the same time, not one after the other, to be safe.

                  👍👍👍👍👍👍👍👍

                  @JonB said in Interesting effect with tr().arg():

                  which is what you need to do?

                  Actually it's very easy to solve the problem at hand: tr("%1%2%3").arg(QStringLiteral("A"),QStringLiteral("%2A"),QStringLiteral("B"))

                  "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

                  J 1 Reply Last reply 21 Jun 2018, 13:22
                  2
                  • V VRonin
                    21 Jun 2018, 13:21

                    @JonB said in Interesting effect with tr().arg():

                    You need a function which does multiple substitutions at the same time, not one after the other, to be safe.

                    👍👍👍👍👍👍👍👍

                    @JonB said in Interesting effect with tr().arg():

                    which is what you need to do?

                    Actually it's very easy to solve the problem at hand: tr("%1%2%3").arg(QStringLiteral("A"),QStringLiteral("%2A"),QStringLiteral("B"))

                    J Offline
                    J Offline
                    JonB
                    wrote on 21 Jun 2018, 13:22 last edited by
                    #10

                    @VRonin
                    .arg() takes a list of arguments?

                    V 1 Reply Last reply 21 Jun 2018, 13:23
                    0
                    • J JonB
                      21 Jun 2018, 13:22

                      @VRonin
                      .arg() takes a list of arguments?

                      V Offline
                      V Offline
                      VRonin
                      wrote on 21 Jun 2018, 13:23 last edited by
                      #11

                      Yes, up to 9: http://doc.qt.io/qt-5/qstring.html#arg-21

                      "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

                      J 1 Reply Last reply 21 Jun 2018, 13:27
                      2
                      • V VRonin
                        21 Jun 2018, 13:23

                        Yes, up to 9: http://doc.qt.io/qt-5/qstring.html#arg-21

                        J Offline
                        J Offline
                        JonB
                        wrote on 21 Jun 2018, 13:27 last edited by
                        #12

                        @VRonin
                        Yeah, I just saw that, that's what I call "cheating" :)
                        Are the %numbers limited to 9 in the format string?
                        Where is QString::argv(arrayOfArgs) ? ;-)

                        1 Reply Last reply
                        0
                        • V VRonin
                          21 Jun 2018, 12:39

                          I discussed in the past this and also the season why you should only use arg(QString) and not the other overloads

                          C Offline
                          C Offline
                          ChrisVT
                          wrote on 21 Jun 2018, 13:28 last edited by
                          #13

                          Thanks for all the responses - very insightful!

                          @VRonin This also happens with QStrings:
                          qDebug() << QString("%1%2%3").arg("A").arg("%2A").arg("B"); -> "ABA%3"
                          qDebug() << QString("%1%2%3").arg(QString("A")).arg(QString("%2A")).arg(QString("B")); -> "ABA%3"
                          But yes, implicit type conversion can be very hard to figure out. Been there!

                          @joeB Good advice about using the arglist instead, but
                          (a) this only works for QStrings, not for numerical formats, and
                          (b) Qt offers the ability to use chained args which MOSTLY work.
                          I was incorrectly assuming that arg(a).arg(b) should be the same as .arg(a,b) for constant QStrings a and b. I'll still say it's not all that intuitive that it isn't.

                          J 1 Reply Last reply 21 Jun 2018, 13:37
                          1
                          • C ChrisVT
                            21 Jun 2018, 13:28

                            Thanks for all the responses - very insightful!

                            @VRonin This also happens with QStrings:
                            qDebug() << QString("%1%2%3").arg("A").arg("%2A").arg("B"); -> "ABA%3"
                            qDebug() << QString("%1%2%3").arg(QString("A")).arg(QString("%2A")).arg(QString("B")); -> "ABA%3"
                            But yes, implicit type conversion can be very hard to figure out. Been there!

                            @joeB Good advice about using the arglist instead, but
                            (a) this only works for QStrings, not for numerical formats, and
                            (b) Qt offers the ability to use chained args which MOSTLY work.
                            I was incorrectly assuming that arg(a).arg(b) should be the same as .arg(a,b) for constant QStrings a and b. I'll still say it's not all that intuitive that it isn't.

                            J Offline
                            J Offline
                            JonB
                            wrote on 21 Jun 2018, 13:37 last edited by
                            #14

                            @ChrisVT
                            I love things which "MOSTLY" work :)

                            Be aware, if you are going to use "numerical formats" as you say then, as @VRonin pointed out in the post he referred to, these will not be localed. If you care about that, you must format them to localed strings in the first place, then you can pass them to the list-arg() because they are now strings.

                            1 Reply Last reply
                            0

                            11/14

                            21 Jun 2018, 13:23

                            • Login

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