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. MainWindow GUI cannot call SLOT in worker thread UDP object
Forum Updated to NodeBB v4.3 + New Features

MainWindow GUI cannot call SLOT in worker thread UDP object

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 5 Posters 2.7k 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.
  • K Offline
    K Offline
    kma005
    wrote on last edited by
    #1

    Hello,

    I am unable to emit() a signal from the MainWindow object to a worker thread that will send & receive UDP Data.
    The goal is to learn how to communicate from the GUI thread to the UDP thread.
    I do not understand why the SLOT is not working. I used the Mandlebrot example but in reverse, by communicating from GUI to thread. I tried QT4 & QT5 connect(signal, slot) functions without success. I get zero errors/warnings @ compile time

    Mandlebrot example:

    connect(&thread, SIGNAL(renderedImage(QImage,double)), this, SLOT(updatePixmap(QImage,double)));
    

    Mine in mainwindow.cpp:

    connect( this, SIGNAL(&MainWindow::runInitializeInthreadUDP), threadObj, SLOT(&MyUDP::Initialize), Qt::QueuedConnection);
    

    They only message I get from the "Application Output" is:

    QObject::connect: Parentheses expected, signal MainWindow::&MainWindow::runInitializeInthreadUDP in mainwindow.cpp:36
    

    Please see the attached code and if anyone is able to help, that would be very much appreciated.
    If more info is needed, please ask.

    Thank you,
    Keith

    //main.cpp

    #include "mainwindow.h"
    #include <QApplication>
    
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        qDebug()<<"From main GUI thread: "<<QThread::currentThreadId();
    
    
        //Create GUI, but it is not shown until GUI.show is called
        MainWindow GUI;
        //generate GUI screen when this main function is finished
        GUI.show();
    
        return a.exec();
    }
    
    

    //mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QtCore>
    
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0); //Class constructor
    
    private:
        Ui::MainWindow *ui;
    
    signals:
        void runInitializeInthreadUDP();
    
    private slots:
        void on_pushButton_clicked();
    };
    
    #endif // MAINWINDOW_H
    
    

    //mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QtCore>
    #include "myudp.h"
    #include "myThread.h"
    
    
    myThread* threadObj = new myThread();
    Worker* worker = new Worker();
    
    
    //MainWindow Class Constructor
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        //Create UDP object and startup worker thread
        //https://wiki.qt.io/QThreads_general_usage
        MyUDP udpObj;
        udpObj.moveToThread(threadObj);
        connect(worker, SIGNAL (&Worker::threadFinishedSignal), threadObj, SLOT (quit()));
        connect(worker, SIGNAL (&Worker::threadFinishedSignal), worker, SLOT (deleteLater()));
        connect(threadObj, SIGNAL (&Worker::threadFinishedSignal), threadObj, SLOT (deleteLater()));
        threadObj->start();
    
    
        //
        //
        //THIS NEXT PART DOES NOT WORK(Initialize() SLOT() function is never called)!!!!
        //
        //
        //initialize UDP ports
        //QT5 VERSION:
        connect( this, SIGNAL(&MainWindow::runInitializeInthreadUDP), threadObj, SLOT(&MyUDP::Initialize), Qt::QueuedConnection);
        //QT4 VERSION:
    //    connect( this, SIGNAL(runInitializeInthreadUDP()), threadObj, SLOT(Initialize()), Qt::QueuedConnection);
        emit runInitializeInthreadUDP();
    }
    
    
    //also does not work when pressing button on GUI (this _clicked function runs, but does not call SLOT &MyUDP::Initialize)
    void MainWindow::on_pushButton_clicked()
    {
        emit runInitializeInthreadUDP();
    }
    
    

    //mythread.h

    //#ifndef WORKERTHREAD_H
    //#define WORKERTHREAD_H
    
    #include <QtCore>
    
    
    //http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/
    class myThread : public QThread
    {
        Q_OBJECT
    
    private:
        void run()
        {
            qDebug()<<"From worker thread: "<<currentThreadId();
            connect(this, &QThread::finished, this, &QObject::deleteLater);
    
            exec();
        }
    };
    
    
    
    //https://wiki.qt.io/QThreads_general_usage
    class Worker : public QObject {
        Q_OBJECT
    
    signals:
        void threadFinishedSignal();
    };
    
    //#endif // WORKERTHREAD_H
    
    

    //myudp.h

    #ifndef UDP_H
    #define UDP_H
    
    //Base class QObject
    #include <QUdpSocket>
    #include <QtCore>
    
    
    class MyUDP : public QObject
    {
        Q_OBJECT
    
        public:
            MyUDP(); //Constructor for UDP Class Object
            ~MyUDP(); //Destructor for UDP Class Object
    
        private:
            QUdpSocket *socket;
    
        public slots:
            void UDPreadInputData();
            //Setup UDP port and connect port to fire function each time a UDP packet is received
            void Initialize();
    };
    
    
    #endif // UDP_H
    
    

    //myudp.cpp

    #include "myudp.h"
    #include <QtCore>
    
    
    //Settings for UDP addresses
    QHostAddress remoteAddress = QHostAddress("192.168.1.1");
    QHostAddress localAddress = QHostAddress("192.168.1.2");
    quint16 sendPort = 1234;
    quint16 receivePort = 5678;
    
    //UDP buffer that will contain the data received from microcontroller
    QByteArray Buffer;
    
    
    
    MyUDP::MyUDP() //Constructor for UDP Class Object
    {
    }
    MyUDP::~MyUDP() //Destructor for UDP Class Object
    {
    }
    
    
    
    void MyUDP::Initialize()
    {
        socket = new QUdpSocket(this);
    
        //We need to bind the UDP socket to an address and a port
    //    socket->bind(QHostAddress::LocalHost,receivePort);
        socket->bind(localAddress,receivePort);
        //Call the "UDPreadyRead" function each time the socket gets data on the defined UDP port
        connect(socket,SIGNAL(readyRead()),this,SLOT(UDPreadInputData()));
    
        qDebug()<<"UDP worker thread initialized";
    }
    
    
    
    //Read something
    void MyUDP::UDPreadInputData()
    {
        Buffer.resize(socket->pendingDatagramSize());
        int bufferSize = Buffer.size();
    
        //read sing UDP packet from hardware ethernet tranceiver on computer
        socket->readDatagram(Buffer.data(), bufferSize, &remoteAddress, &receivePort);
    
    //  http://lists.qt-project.org/pipermail/qt-interest-old/2009-June/008318.html
    //  Read float32 data types out with a QDataStream
        QDataStream ds( Buffer.mid( 0, bufferSize ) );
        //By default, a QDataStream is big endian and must be flipped depending on "processor architecture".
        ds.setByteOrder(QDataStream::LittleEndian);
        ds.setFloatingPointPrecision(QDataStream::SinglePrecision);
    
       //Throw out UDP Ethernet header and two bytes that are unused at beginning of packet (10 bytes)
       for(int i; i<5; i++)
       {
           qint16 temp; //each int16 is 2 bytes
           ds >> temp;
       }
    
       //Read the first two "start of sample bytes"
       qint16 HeaderByte1;
       ds >> HeaderByte1; //54321 start of sample int16
    }
    
    
    1 Reply Last reply
    0
    • Paul ColbyP Offline
      Paul ColbyP Offline
      Paul Colby
      wrote on last edited by Paul Colby
      #2

      Hi @kma005,

      I think this line:

      connect( this, SIGNAL(&MainWindow::runInitializeInthreadUDP), threadObj, SLOT(&MyUDP::Initialize), Qt::QueuedConnection);

      is mixing up the new and old slot syntaxes. Should probably be more like either:

      connect( this, SIGNAL(runInitializeInthreadUDP(type, ...)), threadObj, SLOT(Initialize(type, ...)), Qt::QueuedConnection);
      // or
      connect( this, &MainWindow::runInitializeInthreadUDP, threadObj, &MyUDP::Initialize, Qt::QueuedConnection);
      

      Note, the first version has argument types, and no & characters. And the second version has no SIGNAL nor SLOT macros.

      See https://wiki.qt.io/New_Signal_Slot_Syntax for further explanation.

      Cheers.

      1 Reply Last reply
      3
      • K Offline
        K Offline
        kma005
        wrote on last edited by
        #3

        Paul,

        Please see in "mainwindow.cpp". I have already tried what you said for Qt4 compatibility.
        Both methods were already attempted, but without success.
        //QT5 VERSION:
        connect( this, SIGNAL(&MainWindow::runInitializeInthreadUDP), threadObj, SLOT(&MyUDP::Initialize), Qt::QueuedConnection);
        //QT4 VERSION:
        // connect( this, SIGNAL(runInitializeInthreadUDP()), threadObj, SLOT(Initialize()), Qt::QueuedConnection);
        emit runInitializeInthreadUDP();

        Thank you,
        Keith

        1 Reply Last reply
        0
        • Paul ColbyP Offline
          Paul ColbyP Offline
          Paul Colby
          wrote on last edited by Paul Colby
          #4

          Hi @kma005,

          Your Qt5 version is wrong, as I already described (should not have any SIGNAL nor SLOT macros).

          And both versions are trying to connect to an Initialize slot that does not exist on the receiver threadObj - it exists on udpObj only (if you corrected the Qt5 syntax, the compiler would have pointed that out).

          Also I suspect you'll need to allocate udpObj on the heap, eg:

          MyUDP * udpObj = new MyUDP;
          

          Otherwise it will be destroyed after the MainWindow constructor returns.

          Cheers.

          1 Reply Last reply
          4
          • A Offline
            A Offline
            Asperamanca
            wrote on last edited by
            #5

            Aside from the fact that class myThread does not have any slots, do you start an event loop within the thread? Without an event loop, the thread cannot receive signals.

            1 Reply Last reply
            0
            • K Offline
              K Offline
              kma005
              wrote on last edited by
              #6

              THANK YOU PAUL COLBY!!!

              The issue was the new syntax does not use "SIGNAL() and SLOT()" macros.
              The "mainwindow.cpp" connect() function now does not have the "SIGNAL() and SLOT()" macros.

              Also the biggest issue was udpObj was destroyed when the mainwindow constructor finished.
              I made a "MyUDP *udpObj = new MyUDP();" declaration at the top of "mainwindow.cpp".
              next, "udpObj->moveToThread(threadObj);" is using an arrow since "udpObj" is now a pointer.

              Asperamanca, the thread event loop starts when "threadObj->start();" is called.
              the thread exec() function is called in "myThread.h"
              When "emit runInitializeInthreadUDP()" is called, "udpObj->Initialize()" will be called because the event loop in myThread is already running from the previous "threadObj->start();"

              THANK YOU PAUL COLBY!!!
              I will try to mark this solved.
              Keith

              Please see my updated "mainwindow.cpp" file:

              #include "mainwindow.h"
              #include "ui_mainwindow.h"
              #include <QtCore>
              #include "myudp.h"
              #include "myThread.h"
              
              
              myThread *threadObj = new myThread();
              Worker *worker = new Worker();
              MyUDP *udpObj = new MyUDP();
              
              
              //MainWindow Class Constructor
              MainWindow::MainWindow(QWidget *parent) :
                  QMainWindow(parent),
                  ui(new Ui::MainWindow)
              {
                  ui->setupUi(this);
              
                  //Create UDP object and startup worker thread
                  //https://wiki.qt.io/QThreads_general_usage
              
                  udpObj->moveToThread(threadObj);
                  connect(worker, SIGNAL (&Worker::threadFinishedSignal), threadObj, SLOT (quit()));
                  connect(worker, SIGNAL (&Worker::threadFinishedSignal), worker, SLOT (deleteLater()));
                  connect(threadObj, SIGNAL (&Worker::threadFinishedSignal), threadObj, SLOT (deleteLater()));
                  threadObj->start();
              
              
                  //
                  //
                  //THIS NEXT PART DOES NOT WORK(Initialize() SLOT() function is never called)!!!!
                  //
                  //
                  //initialize UDP ports
                  //QT5 VERSION:
              //    connect( this, SIGNAL(&MainWindow::runInitializeInthreadUDP), threadObj, SLOT(&MyUDP::Initialize), Qt::QueuedConnection);
                  connect( this, &MainWindow::runInitializeInthreadUDP, udpObj, &MyUDP::Initialize, Qt::QueuedConnection);
                  //QT4 VERSION:
              //    connect( this, SIGNAL(runInitializeInthreadUDP()), threadObj, SLOT(Initialize()), Qt::QueuedConnection);
                  emit runInitializeInthreadUDP();
              }
              
              
              //also does not work when pressing button on GUI (this _clicked function runs, but does not call SLOT &MyUDP::Initialize)
              void MainWindow::on_pushButton_clicked()
              {
                  emit runInitializeInthreadUDP();
              }
              
              
              jsulmJ 1 Reply Last reply
              0
              • K kma005

                THANK YOU PAUL COLBY!!!

                The issue was the new syntax does not use "SIGNAL() and SLOT()" macros.
                The "mainwindow.cpp" connect() function now does not have the "SIGNAL() and SLOT()" macros.

                Also the biggest issue was udpObj was destroyed when the mainwindow constructor finished.
                I made a "MyUDP *udpObj = new MyUDP();" declaration at the top of "mainwindow.cpp".
                next, "udpObj->moveToThread(threadObj);" is using an arrow since "udpObj" is now a pointer.

                Asperamanca, the thread event loop starts when "threadObj->start();" is called.
                the thread exec() function is called in "myThread.h"
                When "emit runInitializeInthreadUDP()" is called, "udpObj->Initialize()" will be called because the event loop in myThread is already running from the previous "threadObj->start();"

                THANK YOU PAUL COLBY!!!
                I will try to mark this solved.
                Keith

                Please see my updated "mainwindow.cpp" file:

                #include "mainwindow.h"
                #include "ui_mainwindow.h"
                #include <QtCore>
                #include "myudp.h"
                #include "myThread.h"
                
                
                myThread *threadObj = new myThread();
                Worker *worker = new Worker();
                MyUDP *udpObj = new MyUDP();
                
                
                //MainWindow Class Constructor
                MainWindow::MainWindow(QWidget *parent) :
                    QMainWindow(parent),
                    ui(new Ui::MainWindow)
                {
                    ui->setupUi(this);
                
                    //Create UDP object and startup worker thread
                    //https://wiki.qt.io/QThreads_general_usage
                
                    udpObj->moveToThread(threadObj);
                    connect(worker, SIGNAL (&Worker::threadFinishedSignal), threadObj, SLOT (quit()));
                    connect(worker, SIGNAL (&Worker::threadFinishedSignal), worker, SLOT (deleteLater()));
                    connect(threadObj, SIGNAL (&Worker::threadFinishedSignal), threadObj, SLOT (deleteLater()));
                    threadObj->start();
                
                
                    //
                    //
                    //THIS NEXT PART DOES NOT WORK(Initialize() SLOT() function is never called)!!!!
                    //
                    //
                    //initialize UDP ports
                    //QT5 VERSION:
                //    connect( this, SIGNAL(&MainWindow::runInitializeInthreadUDP), threadObj, SLOT(&MyUDP::Initialize), Qt::QueuedConnection);
                    connect( this, &MainWindow::runInitializeInthreadUDP, udpObj, &MyUDP::Initialize, Qt::QueuedConnection);
                    //QT4 VERSION:
                //    connect( this, SIGNAL(runInitializeInthreadUDP()), threadObj, SLOT(Initialize()), Qt::QueuedConnection);
                    emit runInitializeInthreadUDP();
                }
                
                
                //also does not work when pressing button on GUI (this _clicked function runs, but does not call SLOT &MyUDP::Initialize)
                void MainWindow::on_pushButton_clicked()
                {
                    emit runInitializeInthreadUDP();
                }
                
                
                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on last edited by jsulm
                #7

                @kma005 said in MainWindow GUI cannot call SLOT in worker thread UDP object:

                connect() function now does not have the "SIGNAL() and SLOT()" macros

                This is not correct. SIGNAL/SLOT connect variant is still available (old syntax). Since Qt5 there is the new connect syntax without SIGNAL/SLOT. So, you can use both.
                Your problem was that you were mixing new and old connect syntax at the same time. You either use old or new syntax.

                Here you're mixing:

                connect(worker, SIGNAL (&Worker::threadFinishedSignal), threadObj, SLOT (quit()));
                

                It should be (old syntax):

                connect(worker, SIGNAL(threadFinishedSignal()), threadObj, SLOT (quit()));
                

                New syntax:

                connect(worker, &Worker::threadFinishedSignal, threadObj, &myThread::quit);
                

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                Paul ColbyP 1 Reply Last reply
                0
                • jsulmJ jsulm

                  @kma005 said in MainWindow GUI cannot call SLOT in worker thread UDP object:

                  connect() function now does not have the "SIGNAL() and SLOT()" macros

                  This is not correct. SIGNAL/SLOT connect variant is still available (old syntax). Since Qt5 there is the new connect syntax without SIGNAL/SLOT. So, you can use both.
                  Your problem was that you were mixing new and old connect syntax at the same time. You either use old or new syntax.

                  Here you're mixing:

                  connect(worker, SIGNAL (&Worker::threadFinishedSignal), threadObj, SLOT (quit()));
                  

                  It should be (old syntax):

                  connect(worker, SIGNAL(threadFinishedSignal()), threadObj, SLOT (quit()));
                  

                  New syntax:

                  connect(worker, &Worker::threadFinishedSignal, threadObj, &myThread::quit);
                  
                  Paul ColbyP Offline
                  Paul ColbyP Offline
                  Paul Colby
                  wrote on last edited by
                  #8

                  @jsulm said in MainWindow GUI cannot call SLOT in worker thread UDP object:

                  @kma005 said in MainWindow GUI cannot call SLOT in worker thread UDP object:

                  connect() function now does not have the "SIGNAL() and SLOT()" macros

                  This is not correct. SIGNAL/SLOT connect variant is still available (old syntax).

                  I think @kma005 was saying that his updated connect invocation in mainwindow.cpp is no longer using SIGNAL() and SLOT() macros, ie because he's removed them now. I don't think he was suggesting that the older syntax is no longer available.

                  Cheers.

                  jsulmJ J.HilkJ 2 Replies Last reply
                  0
                  • Paul ColbyP Paul Colby

                    @jsulm said in MainWindow GUI cannot call SLOT in worker thread UDP object:

                    @kma005 said in MainWindow GUI cannot call SLOT in worker thread UDP object:

                    connect() function now does not have the "SIGNAL() and SLOT()" macros

                    This is not correct. SIGNAL/SLOT connect variant is still available (old syntax).

                    I think @kma005 was saying that his updated connect invocation in mainwindow.cpp is no longer using SIGNAL() and SLOT() macros, ie because he's removed them now. I don't think he was suggesting that the older syntax is no longer available.

                    Cheers.

                    jsulmJ Offline
                    jsulmJ Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @Paul-Colby OK, then I misunderstood the post

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    0
                    • Paul ColbyP Paul Colby

                      @jsulm said in MainWindow GUI cannot call SLOT in worker thread UDP object:

                      @kma005 said in MainWindow GUI cannot call SLOT in worker thread UDP object:

                      connect() function now does not have the "SIGNAL() and SLOT()" macros

                      This is not correct. SIGNAL/SLOT connect variant is still available (old syntax).

                      I think @kma005 was saying that his updated connect invocation in mainwindow.cpp is no longer using SIGNAL() and SLOT() macros, ie because he's removed them now. I don't think he was suggesting that the older syntax is no longer available.

                      Cheers.

                      J.HilkJ Online
                      J.HilkJ Online
                      J.Hilk
                      Moderators
                      wrote on last edited by
                      #10

                      @Paul-Colby ,well no, @jsulm is correct.
                      If the Please see my updated "mainwindow.cpp" file: is indeed the one @kma005 uses, than he's still using old and new syntax mixed in one statement:

                      udpObj->moveToThread(threadObj);
                          connect(worker, SIGNAL (&Worker::threadFinishedSignal), threadObj, SLOT (quit()));
                          connect(worker, SIGNAL (&Worker::threadFinishedSignal), worker, SLOT (deleteLater()));
                          connect(threadObj, SIGNAL (&Worker::threadFinishedSignal), threadObj, SLOT (deleteLater()));
                          threadObj->start();
                      
                      
                          //
                          //
                          //THIS NEXT PART DOES NOT WORK(Initialize() SLOT() function is never called)!!!!
                          //
                          //
                          //initialize UDP ports
                          //QT5 VERSION:
                      //    connect( this, SIGNAL(&MainWindow::runInitializeInthreadUDP), threadObj, SLOT(&MyUDP::Initialize), Qt::QueuedConnection);
                          connect( this, &MainWindow::runInitializeInthreadUDP, udpObj, &MyUDP::Initialize, Qt::QueuedConnection);
                          //QT4 VERSION:
                      //    connect( this, SIGNAL(runInitializeInthreadUDP()), threadObj, SLOT(Initialize()), Qt::QueuedConnection);
                          emit runInitializeInthreadUDP();
                      

                      the only connect that will work from that code-example is:
                      connect( this, &MainWindow::runInitializeInthreadUDP, udpObj, &MyUDP::Initialize, Qt::QueuedConnection);

                      everything depending on the thread finished signal is ignored.


                      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                      Q: What's that?
                      A: It's blue light.
                      Q: What does it do?
                      A: It turns blue.

                      1 Reply Last reply
                      1
                      • K Offline
                        K Offline
                        kma005
                        wrote on last edited by
                        #11

                        All,

                        I assure you this line works in "mainwindow.cpp" and the "emit runInitializeInthreadUDP();" in mainwindow.cpp calls the function udpObj->Initialize().
                        connect( this, &MainWindow::runInitializeInthreadUDP, udpObj, &MyUDP::Initialize, Qt::QueuedConnection);

                        I simply omitted the SIGNAL() and SLOT() words and all is right with the world due to Paul Colby.
                        I am using the QT5 syntax since the QT4 compiler did not catch the issue of threadObj->Initialize() was being called instead of udpObj->Initialize(). I had zero errors using the QT4 connect( this, SIGNAL(runInitializeInthreadUDP()), threadObj, SLOT(Initialize()), Qt::QueuedConnection); QT5 syntax for connect seems to catch those bad connection errors when compiling. When I used the QT5 syntax, it told me that udpObj should be used instead of threadObj in the connect() line.

                        I apologize for the confusion.
                        Thank you everyone. I just wanted to check back if people had additional questions and i am glad I did to clear this up.

                        -Keith

                        1 Reply Last reply
                        0
                        • Paul ColbyP Offline
                          Paul ColbyP Offline
                          Paul Colby
                          wrote on last edited by
                          #12

                          @J.Hilk said in MainWindow GUI cannot call SLOT in worker thread UDP object:

                          If the Please see my updated "mainwindow.cpp" file: is indeed the one @kma005 uses, than he's still using old and new syntax mixed in one statement:

                          Yes, that is true - he's still using mixed syntaxes. However, the OP was only ever about the final connect - the one involving the MainWindow::runInitializeInthreadUDP signal, not the others. Its this last one that he's fixed, is no longer user mixed, and that his most recent comments were referring to.

                          Indeed, he still has to go back and fix up the others too. He just wasn't claiming that the older syntax is not supported.

                          Cheers.

                          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