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. Nested thread (QThread) does not emit the signal
Forum Updated to NodeBB v4.3 + New Features

Nested thread (QThread) does not emit the signal

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 3 Posters 1.5k Views 1 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.
  • J Offline
    J Offline
    Jacobotto
    wrote on last edited by
    #1

    Hi all,

    This is my code in the QtWidgetsApplication1.cpp (main file, main thread) where I'm creating a new worker class object and starting the thread:

    void QtWidgetsApplication1::on_pushButton_4_clicked() {
    
        ui.pushButton_2->setEnabled(false);
        mThread = new QThread;
        worker = new BinconThreadWorker;
        worker->Stop = false;
        QObject::connect(mThread, SIGNAL(started()), worker, SLOT(process2()));
        QObject::connect(worker, SIGNAL(valueChanged(std::string)), this, SLOT(onValueChanged(std::string)));
        QObject::connect(worker, SIGNAL(process3_Fb(std::string)), this, SLOT(onValueChanged(std::string)));
        QObject::connect(worker, SIGNAL(valueSecChanged(std::string)), this, SLOT(onValueSecChanged(std::string)));
        QObject::connect(worker, SIGNAL(finished()), mThread, SLOT(quit()));
        QObject::connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
        QObject::connect(mThread, SIGNAL(finished()), mThread, SLOT(deleteLater()));
        worker->moveToThread(mThread);
        mThread->start();
    
    }
    

    So I'm starting in the BinconThreadWorker process2:

    void BinconThreadWorker::process2() {
    //(...)
    if (Taken==false) {
                            mThread = new QThread;
                            worker = new BinconThreadWorker_child0;
                            Taken = true;
                            QObject::connect(mThread, SIGNAL(started()), worker, SLOT(process3()));
                            QObject::connect(worker, SIGNAL(valueChanged(std::string)), this, SLOT(onValueChanged(std::string)));
                            QObject::connect(worker, SIGNAL(finished()), mThread, SLOT(quit()));
                            QObject::connect(worker, SIGNAL(finished()), this, SLOT(threadTaken()));
                            QObject::connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
                            QObject::connect(mThread, SIGNAL(finished()), mThread, SLOT(deleteLater()));
                            worker->moveToThread(mThread);
                            mThread->start();
                        }
    //(...)
    
    }
    void BinconThreadWorker::onValueChanged(std::string s) {
        emit valueChanged(s);
    }
    

    and here I'm starting nested thread here and process3:

    void BinconThreadWorker_child0::process3() {
    
        std::string s = "Started";
        emit valueChanged(s);
        emit finished();
    
    }
    

    For now I expect it to work that way:

    1. I'm creating from the main thread new BinconThreadWorker and starting it in the new QThread.
    2. BinconThreadWorker function process2 is creating new, nested BinconThreadWorker_child0 and starting next new QThread.
    3. From the nested BinconThreadWorker_child0 and it's process3 function I'm sending valueChanged signal and it should go to onValueChanged slot in the BinconThreadWorker and then emit signal to the main thread.

    Is it the correct way of doing this? As I'm not getting emitted string at all or the program freezes and I'm getting "ucrtbase.pdb not loaded". Signals from the BinconThreadWorker are emitted correctly.

    I'm using MS Visual Studio 2022 and QT 6.2.3. Thanks for all the tips.

    Pl45m4P Christian EhrlicherC 2 Replies Last reply
    0
    • J Jacobotto

      Hi all,

      This is my code in the QtWidgetsApplication1.cpp (main file, main thread) where I'm creating a new worker class object and starting the thread:

      void QtWidgetsApplication1::on_pushButton_4_clicked() {
      
          ui.pushButton_2->setEnabled(false);
          mThread = new QThread;
          worker = new BinconThreadWorker;
          worker->Stop = false;
          QObject::connect(mThread, SIGNAL(started()), worker, SLOT(process2()));
          QObject::connect(worker, SIGNAL(valueChanged(std::string)), this, SLOT(onValueChanged(std::string)));
          QObject::connect(worker, SIGNAL(process3_Fb(std::string)), this, SLOT(onValueChanged(std::string)));
          QObject::connect(worker, SIGNAL(valueSecChanged(std::string)), this, SLOT(onValueSecChanged(std::string)));
          QObject::connect(worker, SIGNAL(finished()), mThread, SLOT(quit()));
          QObject::connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
          QObject::connect(mThread, SIGNAL(finished()), mThread, SLOT(deleteLater()));
          worker->moveToThread(mThread);
          mThread->start();
      
      }
      

      So I'm starting in the BinconThreadWorker process2:

      void BinconThreadWorker::process2() {
      //(...)
      if (Taken==false) {
                              mThread = new QThread;
                              worker = new BinconThreadWorker_child0;
                              Taken = true;
                              QObject::connect(mThread, SIGNAL(started()), worker, SLOT(process3()));
                              QObject::connect(worker, SIGNAL(valueChanged(std::string)), this, SLOT(onValueChanged(std::string)));
                              QObject::connect(worker, SIGNAL(finished()), mThread, SLOT(quit()));
                              QObject::connect(worker, SIGNAL(finished()), this, SLOT(threadTaken()));
                              QObject::connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
                              QObject::connect(mThread, SIGNAL(finished()), mThread, SLOT(deleteLater()));
                              worker->moveToThread(mThread);
                              mThread->start();
                          }
      //(...)
      
      }
      void BinconThreadWorker::onValueChanged(std::string s) {
          emit valueChanged(s);
      }
      

      and here I'm starting nested thread here and process3:

      void BinconThreadWorker_child0::process3() {
      
          std::string s = "Started";
          emit valueChanged(s);
          emit finished();
      
      }
      

      For now I expect it to work that way:

      1. I'm creating from the main thread new BinconThreadWorker and starting it in the new QThread.
      2. BinconThreadWorker function process2 is creating new, nested BinconThreadWorker_child0 and starting next new QThread.
      3. From the nested BinconThreadWorker_child0 and it's process3 function I'm sending valueChanged signal and it should go to onValueChanged slot in the BinconThreadWorker and then emit signal to the main thread.

      Is it the correct way of doing this? As I'm not getting emitted string at all or the program freezes and I'm getting "ucrtbase.pdb not loaded". Signals from the BinconThreadWorker are emitted correctly.

      I'm using MS Visual Studio 2022 and QT 6.2.3. Thanks for all the tips.

      Pl45m4P Offline
      Pl45m4P Offline
      Pl45m4
      wrote on last edited by Pl45m4
      #2

      @Jacobotto said in Nested thread (QThread) does not emit the signal:

      Is it the correct way of doing this?

      Cant see something wrong here. But cant tell...At least not from what you've posted (we cant see how your classes look like).
      Made a simple "3-cascading worker thread example" just to be sure, that I'm not missing anything and it works for me... it was possible to pass the string through all workers and end the QThreads properly.

      QThread(0x1a3325e0)   "Worker started" // last child worker
      QThread(0x1a3325d0)   "Worker started" // first worker
      QThread(0x18ae79c8)   "Worker started" // "main" gui thread with mainWindow
      

      All threads receive the string as you can see from the output in valueChanged slot of every worker.

      So what else do you do in/with your classes? Show them please.
      You could reduce your code to a minimal example (like I created for testing) and check if the error still occures... but the code, from Qt / signal-slot perspective, looks ok.


      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

      1 Reply Last reply
      1
      • J Jacobotto

        Hi all,

        This is my code in the QtWidgetsApplication1.cpp (main file, main thread) where I'm creating a new worker class object and starting the thread:

        void QtWidgetsApplication1::on_pushButton_4_clicked() {
        
            ui.pushButton_2->setEnabled(false);
            mThread = new QThread;
            worker = new BinconThreadWorker;
            worker->Stop = false;
            QObject::connect(mThread, SIGNAL(started()), worker, SLOT(process2()));
            QObject::connect(worker, SIGNAL(valueChanged(std::string)), this, SLOT(onValueChanged(std::string)));
            QObject::connect(worker, SIGNAL(process3_Fb(std::string)), this, SLOT(onValueChanged(std::string)));
            QObject::connect(worker, SIGNAL(valueSecChanged(std::string)), this, SLOT(onValueSecChanged(std::string)));
            QObject::connect(worker, SIGNAL(finished()), mThread, SLOT(quit()));
            QObject::connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
            QObject::connect(mThread, SIGNAL(finished()), mThread, SLOT(deleteLater()));
            worker->moveToThread(mThread);
            mThread->start();
        
        }
        

        So I'm starting in the BinconThreadWorker process2:

        void BinconThreadWorker::process2() {
        //(...)
        if (Taken==false) {
                                mThread = new QThread;
                                worker = new BinconThreadWorker_child0;
                                Taken = true;
                                QObject::connect(mThread, SIGNAL(started()), worker, SLOT(process3()));
                                QObject::connect(worker, SIGNAL(valueChanged(std::string)), this, SLOT(onValueChanged(std::string)));
                                QObject::connect(worker, SIGNAL(finished()), mThread, SLOT(quit()));
                                QObject::connect(worker, SIGNAL(finished()), this, SLOT(threadTaken()));
                                QObject::connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
                                QObject::connect(mThread, SIGNAL(finished()), mThread, SLOT(deleteLater()));
                                worker->moveToThread(mThread);
                                mThread->start();
                            }
        //(...)
        
        }
        void BinconThreadWorker::onValueChanged(std::string s) {
            emit valueChanged(s);
        }
        

        and here I'm starting nested thread here and process3:

        void BinconThreadWorker_child0::process3() {
        
            std::string s = "Started";
            emit valueChanged(s);
            emit finished();
        
        }
        

        For now I expect it to work that way:

        1. I'm creating from the main thread new BinconThreadWorker and starting it in the new QThread.
        2. BinconThreadWorker function process2 is creating new, nested BinconThreadWorker_child0 and starting next new QThread.
        3. From the nested BinconThreadWorker_child0 and it's process3 function I'm sending valueChanged signal and it should go to onValueChanged slot in the BinconThreadWorker and then emit signal to the main thread.

        Is it the correct way of doing this? As I'm not getting emitted string at all or the program freezes and I'm getting "ucrtbase.pdb not loaded". Signals from the BinconThreadWorker are emitted correctly.

        I'm using MS Visual Studio 2022 and QT 6.2.3. Thanks for all the tips.

        Christian EhrlicherC Online
        Christian EhrlicherC Online
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #3

        @Jacobotto said in Nested thread (QThread) does not emit the signal:

        As I'm not getting emitted string

        You should take a look at the debug output - I'm pretty sure Qt complains that std::string is not a registered metatype (and also tells you what to do in this case whereas I simply would switch to QString or QByteArray instead)

        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
        2
        • J Offline
          J Offline
          Jacobotto
          wrote on last edited by
          #4

          I changed to QString but it didn't help. Anyway, I commented launching thread section in BinconThreadWorker and still I'm getting an error, but not always, just like before. So to explain more this is the while loop from process2 which is running when error happens:

          while (true) {
          
                      if (this->Stop == true) break;
          
                      j = bincon_obj.get24hTicker();
                      int v_it = 0;
          
                      for (auto it : j) {
          
                          symbol = it.at("symbol").dump();
                          symbol = symbol.substr(1, symbol.length() - 2);
          
                          if (symbol.substr(symbol.length() - 4, 4) != "USDT") continue;
          
                          if (symbol != v[v_it][0]) {
                              s = "Incompatibility of vector and data, breaking...";
                              logFileStream << s.toStdString() << "\n";
                              logFileStream.flush();
                              emit valueChanged(s + "\n");
                              break;
                              this->Stop = true;
                          }
                          
                          lastPrice = it.at("lastPrice").dump();
                          lastPrice = lastPrice.substr(1, lastPrice.length() - 2);
                          flastPrice = stof(lastPrice);
          
                          //(...)
          
                          if (v[v_it][2] == "8") {
                              s = "Worth interest: " + QString::fromStdString(v[v_it][0]);
                              logFileStream << s.toStdString() << "\n";
                              logFileStream.flush();
                              emit valueChanged(s);
          
                            /*    if (Taken == false) {
                                  
                                  mThread = new QThread;
                                  worker = new BinconThreadWorker_child0;
                                  Taken = true;
                                  QObject::connect(mThread, SIGNAL(started()), worker, SLOT(process3()));
                                  QObject::connect(worker, SIGNAL(valueChanged(QString)), this, SLOT(onValueChanged(QString)));
                                  QObject::connect(worker, SIGNAL(finished()), mThread, SLOT(quit()));
                                  QObject::connect(worker, SIGNAL(finished()), this, SLOT(threadTaken()));
                                  QObject::connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
                                  QObject::connect(mThread, SIGNAL(finished()), mThread, SLOT(deleteLater()));
                                  worker->moveToThread(mThread);
                                  mThread->start();
                              }*/
                          }
          
                          v_it++;
                         
                          if (this->Stop == true) break;
                      }
          

          My program connects with API and gets some data, then it compares it and emits signals if requirments are met.
          In the first post I showed you how I'm starting QThread from the main GUI thread and this is the short code of final slot:

          void QtWidgetsApplication1::onValueChanged(QString s) {
              ui.plainTextEdit->appendPlainText(s);
              ui.plainTextEdit->verticalScrollBar()->setValue(maximumHeight());
          }
          

          So as you can see, I have plaintTextEdit widget which is my "console" where all QString data should be shown and indeed it normally works until some time when I get mentioned error:
          698.png
          887.png

          Pl45m4P 1 Reply Last reply
          0
          • J Jacobotto

            I changed to QString but it didn't help. Anyway, I commented launching thread section in BinconThreadWorker and still I'm getting an error, but not always, just like before. So to explain more this is the while loop from process2 which is running when error happens:

            while (true) {
            
                        if (this->Stop == true) break;
            
                        j = bincon_obj.get24hTicker();
                        int v_it = 0;
            
                        for (auto it : j) {
            
                            symbol = it.at("symbol").dump();
                            symbol = symbol.substr(1, symbol.length() - 2);
            
                            if (symbol.substr(symbol.length() - 4, 4) != "USDT") continue;
            
                            if (symbol != v[v_it][0]) {
                                s = "Incompatibility of vector and data, breaking...";
                                logFileStream << s.toStdString() << "\n";
                                logFileStream.flush();
                                emit valueChanged(s + "\n");
                                break;
                                this->Stop = true;
                            }
                            
                            lastPrice = it.at("lastPrice").dump();
                            lastPrice = lastPrice.substr(1, lastPrice.length() - 2);
                            flastPrice = stof(lastPrice);
            
                            //(...)
            
                            if (v[v_it][2] == "8") {
                                s = "Worth interest: " + QString::fromStdString(v[v_it][0]);
                                logFileStream << s.toStdString() << "\n";
                                logFileStream.flush();
                                emit valueChanged(s);
            
                              /*    if (Taken == false) {
                                    
                                    mThread = new QThread;
                                    worker = new BinconThreadWorker_child0;
                                    Taken = true;
                                    QObject::connect(mThread, SIGNAL(started()), worker, SLOT(process3()));
                                    QObject::connect(worker, SIGNAL(valueChanged(QString)), this, SLOT(onValueChanged(QString)));
                                    QObject::connect(worker, SIGNAL(finished()), mThread, SLOT(quit()));
                                    QObject::connect(worker, SIGNAL(finished()), this, SLOT(threadTaken()));
                                    QObject::connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
                                    QObject::connect(mThread, SIGNAL(finished()), mThread, SLOT(deleteLater()));
                                    worker->moveToThread(mThread);
                                    mThread->start();
                                }*/
                            }
            
                            v_it++;
                           
                            if (this->Stop == true) break;
                        }
            

            My program connects with API and gets some data, then it compares it and emits signals if requirments are met.
            In the first post I showed you how I'm starting QThread from the main GUI thread and this is the short code of final slot:

            void QtWidgetsApplication1::onValueChanged(QString s) {
                ui.plainTextEdit->appendPlainText(s);
                ui.plainTextEdit->verticalScrollBar()->setValue(maximumHeight());
            }
            

            So as you can see, I have plaintTextEdit widget which is my "console" where all QString data should be shown and indeed it normally works until some time when I get mentioned error:
            698.png
            887.png

            Pl45m4P Offline
            Pl45m4P Offline
            Pl45m4
            wrote on last edited by Pl45m4
            #5

            @Jacobotto said in Nested thread (QThread) does not emit the signal:

            while (true) {

                    if (this->Stop == true) break;
            
                    j = bincon_obj.get24hTicker();
                    int v_it = 0;
            
                    for (auto it : j) {
            
                        symbol = it.at("symbol").dump();
                        symbol = symbol.substr(1, symbol.length() - 2);
            
                        if (symbol.substr(symbol.length() - 4, 4) != "USDT") continue;
            
                        if (symbol != v[v_it][0]) {
                            s = "Incompatibility of vector and data, breaking...";
                            logFileStream << s.toStdString() << "\n";
                            logFileStream.flush();
                            emit valueChanged(s + "\n");
            

            What do you think how emitting/receiving a signal inside a while(true) loop should work?!

            As long as you are trapped inside this while - loop, you wont be able to receive signals from your other workers. That's why you see the valueChanged response not frequently (or never).

            Check out this post on StackOverflow... in the comments, you also find a possible solution.


            If debugging is the process of removing software bugs, then programming must be the process of putting them in.

            ~E. W. Dijkstra

            1 Reply Last reply
            1
            • J Offline
              J Offline
              Jacobotto
              wrote on last edited by
              #6

              Ok I think I understand in case why I can't get anything from nested thread to the parent nested thread. However my direct signals from BinconThreadWorker to main GUI thread work fine until the error. I think that way is correct, like in this example: GuiThread.

              void MyThread::run()
              {
                  for(int i = 0; i <= 100; i++)
                  {
                      QMutex mutex;
                      // prevent other threads from changing the "Stop" value
                      mutex.lock();
                      if(this->Stop) break;
                      mutex.unlock();
              
                      // emit the signal for the count label
                      emit valueChanged(i);
              
                      // slowdown the count change, msec
                      this->msleep(500);
                  }
              }
              

              The author is emitting signals while the for loop is running, so similar like in my example.
              In my program when the other void (process) is started from the main GUI thread it is also running in while(true) loop without any issues (or I didn't met it already). If I'm starting some function from the GUI I need to make it run until user clicks on "Stop" button, so I need it to constantly connect with the API and if some requirments are met it should start next, nested thread to do something because it needs to run further itself and do checks. How can I solve this, looking from the C++ perepective, not QT (like QEventLoop)? What can be the alternative? When reading the stackoverflow topic @Pl45m4 sent I think it should be based on signals/slots instead. Maybe something like this?:

              void BinconThreadWorker::process2() {
              
              //do something but not while(true)
              
              emit checkIfStop();
              }
              
              
              checkIfStopFunc(){
              
              if(this->Stop==true){
               emit finished();
              }else{
               process2();
              }
              
              }
              

              Anyway, it won't solve the issue with ucrtbase.dll.

              Pl45m4P 1 Reply Last reply
              0
              • J Jacobotto

                Ok I think I understand in case why I can't get anything from nested thread to the parent nested thread. However my direct signals from BinconThreadWorker to main GUI thread work fine until the error. I think that way is correct, like in this example: GuiThread.

                void MyThread::run()
                {
                    for(int i = 0; i <= 100; i++)
                    {
                        QMutex mutex;
                        // prevent other threads from changing the "Stop" value
                        mutex.lock();
                        if(this->Stop) break;
                        mutex.unlock();
                
                        // emit the signal for the count label
                        emit valueChanged(i);
                
                        // slowdown the count change, msec
                        this->msleep(500);
                    }
                }
                

                The author is emitting signals while the for loop is running, so similar like in my example.
                In my program when the other void (process) is started from the main GUI thread it is also running in while(true) loop without any issues (or I didn't met it already). If I'm starting some function from the GUI I need to make it run until user clicks on "Stop" button, so I need it to constantly connect with the API and if some requirments are met it should start next, nested thread to do something because it needs to run further itself and do checks. How can I solve this, looking from the C++ perepective, not QT (like QEventLoop)? What can be the alternative? When reading the stackoverflow topic @Pl45m4 sent I think it should be based on signals/slots instead. Maybe something like this?:

                void BinconThreadWorker::process2() {
                
                //do something but not while(true)
                
                emit checkIfStop();
                }
                
                
                checkIfStopFunc(){
                
                if(this->Stop==true){
                 emit finished();
                }else{
                 process2();
                }
                
                }
                

                Anyway, it won't solve the issue with ucrtbase.dll.

                Pl45m4P Offline
                Pl45m4P Offline
                Pl45m4
                wrote on last edited by Pl45m4
                #7

                @Jacobotto said in Nested thread (QThread) does not emit the signal:

                The author is emitting signals while the for loop is running, so similar like in my example.

                Not every tutorial or guide you find out there is recommended or correct...

                I suggest you to read

                • https://doc.qt.io/qt-5/threads-technologies.html
                  (esp. this chapter, last two rows of the table since you have/want a permanent call)

                and

                • https://doc.qt.io/qt-5/thread-basics.html

                There you can compare what possibilities you have and decide what might fit the most.
                But in general: Mixing infinite loops and signal-slots is not the best approach, since you are blocking the event loop. Incoming signals and events won't get processed until you break out of your while loop... and then your whole "task" might be over. So you won't receive any signals at runtime.

                If you want to stick to the infinite loop, you should use the QThread::run approach (override it) and "interrupt" your run using QThread::requestInterruption when you want to stop it. The disadvantage is that this lacks the easy communication with other threads using signals and slots (at least receiving data in between is not possible; your threads need to send and receive as your project is now)

                • https://doc.qt.io/qt-5/qthread.html#isInterruptionRequested

                If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                ~E. W. Dijkstra

                1 Reply Last reply
                1
                • J Offline
                  J Offline
                  Jacobotto
                  wrote on last edited by
                  #8

                  Thank you, it explains a lot. So all my threads just do some work and sending info back to the main GUI thread, they don't have to receive from the parent thread additional data besides termination. I could indeed use QThread::run but it would be best that nested thread would send signal directly to GUI thread, omitting parent thread (in this case the one handling BinconThreadWorker class object). Is it possible?
                  Anyway, when leaving just main thread and new one started from there, like I wrote before, another very similar function with while(true) loop is working completely fine and this one too (because nothing is blocking receiving the signals in the main thread), until ucrtbase.dll error. Any thoughts?

                  J 1 Reply Last reply
                  0
                  • J Jacobotto

                    Thank you, it explains a lot. So all my threads just do some work and sending info back to the main GUI thread, they don't have to receive from the parent thread additional data besides termination. I could indeed use QThread::run but it would be best that nested thread would send signal directly to GUI thread, omitting parent thread (in this case the one handling BinconThreadWorker class object). Is it possible?
                    Anyway, when leaving just main thread and new one started from there, like I wrote before, another very similar function with while(true) loop is working completely fine and this one too (because nothing is blocking receiving the signals in the main thread), until ucrtbase.dll error. Any thoughts?

                    J Offline
                    J Offline
                    Jacobotto
                    wrote on last edited by
                    #9

                    FYI I have copied my inifinity loop to the c++ console app and it's crashing randomly too due to json library, so it's not the QT issue, I suspected that. However, the topic problem was solved I suppose anyway, I will try to use QThread::Run, or try to send signal from nested thread directly to GUI thread if it's possible (please answer if anybody knows) or just I will go not the way Main Thread->start Thread1-> start Thread2 but Main Thread->Thread1->emit signal to Main Thread to start Thread2. It will fit my needs too.

                    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