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. 0 == 1 == 2 ???
QtWS25 Last Chance

0 == 1 == 2 ???

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 4 Posters 1.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.
  • devDawgD Offline
    devDawgD Offline
    devDawg
    wrote on last edited by
    #1

    Okay, this has to be the most ridiculously frustrating bug I have seen to date using Qt.

    All I am trying to do is set up a GUI with 3 buttons, each with its own enum. If the enum is equal to Reboot (2), then the system is supposed to reboot. If the enum is 0 or 1, the process is supposed to call a different command.

    Initially when I was typing "transitionTo.goToNext(transitionTo.EnumValue)", it was interpeting the int as a unicode character, which I didn't know how to deal with and didn't want to spend the time learning.

    Now, I am just sending single character strings. In transition_functions.cpp, num.toInt() always prints the correct enum integer value, but whether it is 0, 1, or 2, num.compare("2") == 0 always returns true, because the reboot command executes for every button pressed!!! Extremely frustrated with this trivial code. Please help and/or shed some light on this tomfoolery.

    I should also mention that the second script command is a placeholder at this point.

    main.cpp:

    #include "transition_functions.cpp"
    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include <QChar>
    
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
        QQmlApplicationEngine engine;
        transition_functions *context_property = new transition_functions();
        context_property->passPid(app.applicationPid());
        qDebug() << transition_functions::App_ScreenTest << "," << transition_functions::App_UiTest << "," << transition_functions::Reboot;
        QQmlContext *context = engine.rootContext();
        context->setContextProperty("transitionTo",context_property);
    
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    

    transition_functions.h:

    #include <QObject>
    #include <QProcess>
    #include <QString>
    #include <QStringList>
    #include <QDebug>
    
    class transition_functions: public QObject
    {
        Q_OBJECT
        Q_ENUMS(Next)
    
    public:
    
        enum Next { App_UiTest, App_ScreenTest, Reboot};
    
        transition_functions(QObject *parent = nullptr): QObject(parent) { }
    
        Q_INVOKABLE void goToNext(QString num);
        void passPid(int val) { _appPid = val; }
        virtual ~transition_functions() { }
    
        int _appPid;
    
    };
    

    transition_functions.cpp:

    #include "transition_functions.h"
    
    
    void transition_functions::goToNext(QString num) {
    
            QProcess *proc = new QProcess();
            qDebug() << "button pressed: " << num.toInt();
            if (num.compare("2") == 0) {
    
                if (num.toInt() != 2) { qDebug() << "this is fucked."; }
                proc->start("/bin/bash",QStringList() << "-c" << "echo 'reboot' > /dev/ttyS0");
            } else {
    
            QString command = "echo '. scriptpathname.sh " + QString(QString::fromStdString(std::to_string(_appPid))) + " " +
            num + "' > /dev/ttyS0";
            //passes the pid and the chosen app based on the button press.
    
            proc->start("/bin/bash", QStringList() << "-c" << command);
            }
    }
    

    main.qml:

    Window {
        visible: true
        width: 800
        height: 480
        title: qsTr("thing")
    
        MainForm {
            anchors.fill: parent
            testButton.onClicked: transitionTo.goToNext("0") //App_UiTest
            screenButton.onClicked: transitionTo.goToNext("1") //App_ScreenTest
            powerButton.onClicked: transitionTo.goToNext("2") //Reboot
        }
    }
    
    

    Anything worthwhile is never achieved easily.

    JonBJ 1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      A quick test shows that:

      qDebug() << QString("0").compare("2")
                        << QString("1").compare("2")
                        << QString("2").compare("2");
      

      returns -2, -1, 0 respectively.

      By the way, why not compare the int value since you convert it anyway ?

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

      devDawgD 1 Reply Last reply
      1
      • SGaistS SGaist

        Hi,

        A quick test shows that:

        qDebug() << QString("0").compare("2")
                          << QString("1").compare("2")
                          << QString("2").compare("2");
        

        returns -2, -1, 0 respectively.

        By the way, why not compare the int value since you convert it anyway ?

        devDawgD Offline
        devDawgD Offline
        devDawg
        wrote on last edited by devDawg
        #3

        @SGaist

        I did at one point compare int values, but now I am trying strings.

        Your quick test confirms my frustration; why would the if statement

        if (num.compare("2") == 0)
        

        be true for num equal to "0", "1", & "2" ? It should be false for 2 of the cases, but it's true for all 3.

        Anything worthwhile is never achieved easily.

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

          What do you get printed on your application output ?

          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
          • mrjjM Offline
            mrjjM Offline
            mrjj
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Hi
            What Qt version are you using ?
            Cant reproduce either

            QString num = "2";
              if (num.compare("0") == 0 ) { qDebug() << "TRUE 0"; }
              if (num.compare("1") == 0 ) { qDebug() << "TRUE 1"; }
              if (num.compare("2") == 0 ) { qDebug() << "TRUE 2"; }
            

            says
            TRUE 2

            devDawgD 1 Reply Last reply
            4
            • devDawgD devDawg

              Okay, this has to be the most ridiculously frustrating bug I have seen to date using Qt.

              All I am trying to do is set up a GUI with 3 buttons, each with its own enum. If the enum is equal to Reboot (2), then the system is supposed to reboot. If the enum is 0 or 1, the process is supposed to call a different command.

              Initially when I was typing "transitionTo.goToNext(transitionTo.EnumValue)", it was interpeting the int as a unicode character, which I didn't know how to deal with and didn't want to spend the time learning.

              Now, I am just sending single character strings. In transition_functions.cpp, num.toInt() always prints the correct enum integer value, but whether it is 0, 1, or 2, num.compare("2") == 0 always returns true, because the reboot command executes for every button pressed!!! Extremely frustrated with this trivial code. Please help and/or shed some light on this tomfoolery.

              I should also mention that the second script command is a placeholder at this point.

              main.cpp:

              #include "transition_functions.cpp"
              #include <QGuiApplication>
              #include <QQmlApplicationEngine>
              #include <QQmlContext>
              #include <QChar>
              
              
              int main(int argc, char *argv[])
              {
                  QGuiApplication app(argc, argv);
                  QQmlApplicationEngine engine;
                  transition_functions *context_property = new transition_functions();
                  context_property->passPid(app.applicationPid());
                  qDebug() << transition_functions::App_ScreenTest << "," << transition_functions::App_UiTest << "," << transition_functions::Reboot;
                  QQmlContext *context = engine.rootContext();
                  context->setContextProperty("transitionTo",context_property);
              
                  engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                  if (engine.rootObjects().isEmpty())
                      return -1;
              
                  return app.exec();
              }
              

              transition_functions.h:

              #include <QObject>
              #include <QProcess>
              #include <QString>
              #include <QStringList>
              #include <QDebug>
              
              class transition_functions: public QObject
              {
                  Q_OBJECT
                  Q_ENUMS(Next)
              
              public:
              
                  enum Next { App_UiTest, App_ScreenTest, Reboot};
              
                  transition_functions(QObject *parent = nullptr): QObject(parent) { }
              
                  Q_INVOKABLE void goToNext(QString num);
                  void passPid(int val) { _appPid = val; }
                  virtual ~transition_functions() { }
              
                  int _appPid;
              
              };
              

              transition_functions.cpp:

              #include "transition_functions.h"
              
              
              void transition_functions::goToNext(QString num) {
              
                      QProcess *proc = new QProcess();
                      qDebug() << "button pressed: " << num.toInt();
                      if (num.compare("2") == 0) {
              
                          if (num.toInt() != 2) { qDebug() << "this is fucked."; }
                          proc->start("/bin/bash",QStringList() << "-c" << "echo 'reboot' > /dev/ttyS0");
                      } else {
              
                      QString command = "echo '. scriptpathname.sh " + QString(QString::fromStdString(std::to_string(_appPid))) + " " +
                      num + "' > /dev/ttyS0";
                      //passes the pid and the chosen app based on the button press.
              
                      proc->start("/bin/bash", QStringList() << "-c" << command);
                      }
              }
              

              main.qml:

              Window {
                  visible: true
                  width: 800
                  height: 480
                  title: qsTr("thing")
              
                  MainForm {
                      anchors.fill: parent
                      testButton.onClicked: transitionTo.goToNext("0") //App_UiTest
                      screenButton.onClicked: transitionTo.goToNext("1") //App_ScreenTest
                      powerButton.onClicked: transitionTo.goToNext("2") //Reboot
                  }
              }
              
              
              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #6

              @devDawg said in 0 == 1 == 2 ???:

                  qDebug() << "button pressed: " << num.toInt();
                  if (num.compare("2") == 0) {
              
                      if (num.toInt() != 2) { qDebug() << "this is f***ed."; }
              

              I don't really believe this code can be followed to printing the rude message if num != "2" (unless something is seriously wrong with your Qt).

              But why not use the optional parameter for http://doc.qt.io/qt-5/qstring.html#toInt

              Returns 0 if the conversion fails.
              If a conversion error occurs, *ok is set to false; otherwise *ok is set to true.

              bool ok;
              int result = num.toInt(&ok);
              

              What is the value of ok? Because if by any chance it's false, somehow, the toInt() would return 0, which would result in it following your "unexpected" num.toInt() != 2 route....

              1 Reply Last reply
              3
              • mrjjM mrjj

                Hi
                What Qt version are you using ?
                Cant reproduce either

                QString num = "2";
                  if (num.compare("0") == 0 ) { qDebug() << "TRUE 0"; }
                  if (num.compare("1") == 0 ) { qDebug() << "TRUE 1"; }
                  if (num.compare("2") == 0 ) { qDebug() << "TRUE 2"; }
                

                says
                TRUE 2

                devDawgD Offline
                devDawgD Offline
                devDawg
                wrote on last edited by
                #7

                @mrjj 5.9.3, unfortunately. The device that I am building the app for is configured for an older version of Qt. As for your test, I got the same result.

                @JonB I never gave the optional parameter a thought, that's a very good point. I apologize for the rude message, I have just been really frustrated by this.

                transition_functions.cpp:

                void transition_functions::goToNext(QString num) {
                
                        QProcess *proc = new QProcess();
                        bool ok;
                        qDebug() << "button pressed: " << num.toInt(&ok);
                        qDebug() << "conversion was " << ok;
                        if (num.compare("2") == 0) {
                
                            qDebug() << "reboot triggered" ;
                            proc->start("/bin/bash",QStringList() << "-c" << "echo 'reboot' > /dev/ttyS0");
                
                        } else {
                
                        QString command = "echo '. scriptpathname.sh " + QString(QString::fromStdString(std::to_string(_appPid))) + " " + num + "' > /dev/ttyS0";
                        //passes the pid and the chosen app based on the button press.
                
                        proc->start("/bin/bash", QStringList() << "-c" << command);
                        }
                }
                

                Upon testing each button press this morning, these are the results:

                pressing the App_UiTest button (0),

                button pressed: 0
                ok == true
                

                pressing this button triggered a reboot, without printing the "reboot triggered" message within the if statement.

                pressing the App_ScreenTest button (1),

                button pressed: 1
                ok == true
                

                pressing this button also triggered a reboot, & again did not print the "reboot triggered" message within the if statement.

                pressing the Reboot button (2),

                button pressed: 2
                ok == true
                reboot triggered
                

                everything here is the same as the other 2 buttons, except we actually see the "reboot triggered" message get printed.

                I am not sure what to make of these results. It is almost as if in the first 2 cases, the reboot function is being triggered without even entering the if statement.

                So I modified the test slightly by commenting out all the code in the else statement, leaving only a print statement "no reboot." Now when I pressed the buttons, they behave as expected. This only happened when I commented out the
                proc->start() command in the else statement. Interesting to say the least.

                Any thoughts?

                Anything worthwhile is never achieved easily.

                1 Reply Last reply
                0
                • JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #8

                  @devDawg
                  So if I understand correctly, I see the following behaviour:

                  • The num.toInt(&ok) always succeeds, and always returns the correct number.

                  • The num.compare("2") always correctly matches "2" and only "2". The correct path of its if ... else is always followed.

                  • The above two statements are as to be expected. Whatever your problem is, it is not to do with number parsing. Any time you think it is again, isolate only the parsing code (not your actions) and verify that parsing is not at issue. It can't be. This is the answer to your question as originally posted.

                  • When it follows the if it always correctly correctly prints the reboot message and reboots.

                  • But when it follows the else path, it does not print a reboot message (correct) but it still reboots. Though if you replace the else's proc-start() with a "no reboot" statement you get that message but no reboot.

                  The only conclusion is that the else''s proc->start() is itself causing a reboot, whether you like it or not!

                  Now, I don't know what might be in your scriptpathname.sh, maybe that causes a reboot (umm, what does it do? you haven't left a reboot in there, have you????) ... Or, writing anything to /dev/ttyS0 causes a reboot. Or, ....

                  I can't do your debugging for you. I am confident that the number parsing is not at issue (code is following correct path), and I am confident that when the else path is followed whatever it does it does not "magically" execute the proc->start() from the if route.

                  There is much more playing you can do to satisfy yourself about what must, or must not, be going on. For example, your two proc->start()s could both echo stuff into some files instead of to /dev/ttyS0 so that you can see what's going on.

                  devDawgD 1 Reply Last reply
                  2
                  • JonBJ JonB

                    @devDawg
                    So if I understand correctly, I see the following behaviour:

                    • The num.toInt(&ok) always succeeds, and always returns the correct number.

                    • The num.compare("2") always correctly matches "2" and only "2". The correct path of its if ... else is always followed.

                    • The above two statements are as to be expected. Whatever your problem is, it is not to do with number parsing. Any time you think it is again, isolate only the parsing code (not your actions) and verify that parsing is not at issue. It can't be. This is the answer to your question as originally posted.

                    • When it follows the if it always correctly correctly prints the reboot message and reboots.

                    • But when it follows the else path, it does not print a reboot message (correct) but it still reboots. Though if you replace the else's proc-start() with a "no reboot" statement you get that message but no reboot.

                    The only conclusion is that the else''s proc->start() is itself causing a reboot, whether you like it or not!

                    Now, I don't know what might be in your scriptpathname.sh, maybe that causes a reboot (umm, what does it do? you haven't left a reboot in there, have you????) ... Or, writing anything to /dev/ttyS0 causes a reboot. Or, ....

                    I can't do your debugging for you. I am confident that the number parsing is not at issue (code is following correct path), and I am confident that when the else path is followed whatever it does it does not "magically" execute the proc->start() from the if route.

                    There is much more playing you can do to satisfy yourself about what must, or must not, be going on. For example, your two proc->start()s could both echo stuff into some files instead of to /dev/ttyS0 so that you can see what's going on.

                    devDawgD Offline
                    devDawgD Offline
                    devDawg
                    wrote on last edited by
                    #9

                    @JonB scriptpathname.sh, as I stated earlier, is not a valid script, it is simply a placeholder.

                    Thanks for the help!

                    Anything worthwhile is never achieved easily.

                    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