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. Timer with Lambda function
QtWS25 Last Chance

Timer with Lambda function

Scheduled Pinned Locked Moved Unsolved General and Desktop
35 Posts 6 Posters 5.0k 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.
  • SPlattenS Offline
    SPlattenS Offline
    SPlatten
    wrote on last edited by SPlatten
    #1

    I am sending JSON messages between processes and I want start a timer when the message is sent, if no acknowledge is received then the timer will timeout and the same message will be written again, at least that's the intention.

    I have a structure:

    typedef struct {
        QJsonObject objMsg;
        QTimer* pTimer;
    } tAckMsgTracking;
    
    typedef std::map<qulonglong, tAckMsgTracking*> mmpAck;
    

    The map is keyed by a message transaction ID which is uniquely generated when the message is sent. The problem I'm having is that the lambda slot does not get called:

    tAckMsgTracking* pAckMsgTrkr = new tAckMsgTracking;
    pAckMsgTrkr->objMsg = objJSON;
    pAckMsgTrkr->pTimer = new QTimer(this);
    QObject::connect(pAckMsgTrkr->pTimer, &QTimer::timeout, [this, pAckMsgTrkr]() {
    //Re-send message
        emit write(pAckMsgTrkr->objMsg);
    });
    //Insert a unique message ID into the message
    objJSON.insert(clsJSON::mscszMsgID, QString::number(++clsMsgSender::msulnglngMsgID));
    //Insert entry into the map
    clsMsgSender::msmpAcks.insert(std::make_pair(clsMsgSender::msulnglngMsgID, pAckMsgTrkr));
    //Start the timer that will resend message if ack. not received
    pAckMsgTrkr->pTimer->start(clsMsgSender::mscuint16AckTimeout);
    

    The value of 'mscuint16AckTimeout' is 5000 (milliseconds). I've also tried:

    pAckMsgTrkr->pTimer->start(std::chrono::milliseconds(clsMsgSender::mscuint16AckTimeout));
    

    I have a break point in the lambda slot, it doesn't get hit.

    Kind Regards,
    Sy

    jsulmJ JonBJ KroMignonK 3 Replies Last reply
    0
    • SPlattenS SPlatten

      I am sending JSON messages between processes and I want start a timer when the message is sent, if no acknowledge is received then the timer will timeout and the same message will be written again, at least that's the intention.

      I have a structure:

      typedef struct {
          QJsonObject objMsg;
          QTimer* pTimer;
      } tAckMsgTracking;
      
      typedef std::map<qulonglong, tAckMsgTracking*> mmpAck;
      

      The map is keyed by a message transaction ID which is uniquely generated when the message is sent. The problem I'm having is that the lambda slot does not get called:

      tAckMsgTracking* pAckMsgTrkr = new tAckMsgTracking;
      pAckMsgTrkr->objMsg = objJSON;
      pAckMsgTrkr->pTimer = new QTimer(this);
      QObject::connect(pAckMsgTrkr->pTimer, &QTimer::timeout, [this, pAckMsgTrkr]() {
      //Re-send message
          emit write(pAckMsgTrkr->objMsg);
      });
      //Insert a unique message ID into the message
      objJSON.insert(clsJSON::mscszMsgID, QString::number(++clsMsgSender::msulnglngMsgID));
      //Insert entry into the map
      clsMsgSender::msmpAcks.insert(std::make_pair(clsMsgSender::msulnglngMsgID, pAckMsgTrkr));
      //Start the timer that will resend message if ack. not received
      pAckMsgTrkr->pTimer->start(clsMsgSender::mscuint16AckTimeout);
      

      The value of 'mscuint16AckTimeout' is 5000 (milliseconds). I've also tried:

      pAckMsgTrkr->pTimer->start(std::chrono::milliseconds(clsMsgSender::mscuint16AckTimeout));
      

      I have a break point in the lambda slot, it doesn't get hit.

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

      @SPlatten said in Timer with Lambda function:

      pAckMsgTrkr->pTimer = new QTimer(this);

      Not related, but: why do you allocate timer on the heap?

      So, you don't get acknowledge and timeout slot is not called?

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

      SPlattenS 1 Reply Last reply
      0
      • jsulmJ jsulm

        @SPlatten said in Timer with Lambda function:

        pAckMsgTrkr->pTimer = new QTimer(this);

        Not related, but: why do you allocate timer on the heap?

        So, you don't get acknowledge and timeout slot is not called?

        SPlattenS Offline
        SPlattenS Offline
        SPlatten
        wrote on last edited by
        #3

        @jsulm, I create a timeout for each message that is sent as the queue doesn't wait one message to be sent successfully, before it sends another. So the timeout is for each message sent, the same queue can send to different hosts.

        Kind Regards,
        Sy

        jsulmJ 1 Reply Last reply
        0
        • SPlattenS SPlatten

          @jsulm, I create a timeout for each message that is sent as the queue doesn't wait one message to be sent successfully, before it sends another. So the timeout is for each message sent, the same queue can send to different hosts.

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

          @SPlatten I still don't see the need for heap allocation for pTimer...

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

          SPlattenS 1 Reply Last reply
          0
          • jsulmJ jsulm

            @SPlatten I still don't see the need for heap allocation for pTimer...

            SPlattenS Offline
            SPlattenS Offline
            SPlatten
            wrote on last edited by
            #5

            @jsulm , what else would you suggest? I don't want to static allocate and I cannot use the stack.

            Kind Regards,
            Sy

            jsulmJ 1 Reply Last reply
            0
            • SPlattenS SPlatten

              @jsulm , what else would you suggest? I don't want to static allocate and I cannot use the stack.

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

              @SPlatten said in Timer with Lambda function:

              what else would you suggest?

              Make it member instead of a pointer? What's the point to have it as pointer allocate memory on the heap (which is slower) and then care to not to forget to delete it?

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

              1 Reply Last reply
              1
              • SPlattenS SPlatten

                I am sending JSON messages between processes and I want start a timer when the message is sent, if no acknowledge is received then the timer will timeout and the same message will be written again, at least that's the intention.

                I have a structure:

                typedef struct {
                    QJsonObject objMsg;
                    QTimer* pTimer;
                } tAckMsgTracking;
                
                typedef std::map<qulonglong, tAckMsgTracking*> mmpAck;
                

                The map is keyed by a message transaction ID which is uniquely generated when the message is sent. The problem I'm having is that the lambda slot does not get called:

                tAckMsgTracking* pAckMsgTrkr = new tAckMsgTracking;
                pAckMsgTrkr->objMsg = objJSON;
                pAckMsgTrkr->pTimer = new QTimer(this);
                QObject::connect(pAckMsgTrkr->pTimer, &QTimer::timeout, [this, pAckMsgTrkr]() {
                //Re-send message
                    emit write(pAckMsgTrkr->objMsg);
                });
                //Insert a unique message ID into the message
                objJSON.insert(clsJSON::mscszMsgID, QString::number(++clsMsgSender::msulnglngMsgID));
                //Insert entry into the map
                clsMsgSender::msmpAcks.insert(std::make_pair(clsMsgSender::msulnglngMsgID, pAckMsgTrkr));
                //Start the timer that will resend message if ack. not received
                pAckMsgTrkr->pTimer->start(clsMsgSender::mscuint16AckTimeout);
                

                The value of 'mscuint16AckTimeout' is 5000 (milliseconds). I've also tried:

                pAckMsgTrkr->pTimer->start(std::chrono::milliseconds(clsMsgSender::mscuint16AckTimeout));
                

                I have a break point in the lambda slot, it doesn't get hit.

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

                @SPlatten
                Since the code looks OK (other than heap issue), try a qDebug() instead of relying on breakpoint, and move the timeout down to 0 to debug.

                1 Reply Last reply
                0
                • SPlattenS SPlatten

                  I am sending JSON messages between processes and I want start a timer when the message is sent, if no acknowledge is received then the timer will timeout and the same message will be written again, at least that's the intention.

                  I have a structure:

                  typedef struct {
                      QJsonObject objMsg;
                      QTimer* pTimer;
                  } tAckMsgTracking;
                  
                  typedef std::map<qulonglong, tAckMsgTracking*> mmpAck;
                  

                  The map is keyed by a message transaction ID which is uniquely generated when the message is sent. The problem I'm having is that the lambda slot does not get called:

                  tAckMsgTracking* pAckMsgTrkr = new tAckMsgTracking;
                  pAckMsgTrkr->objMsg = objJSON;
                  pAckMsgTrkr->pTimer = new QTimer(this);
                  QObject::connect(pAckMsgTrkr->pTimer, &QTimer::timeout, [this, pAckMsgTrkr]() {
                  //Re-send message
                      emit write(pAckMsgTrkr->objMsg);
                  });
                  //Insert a unique message ID into the message
                  objJSON.insert(clsJSON::mscszMsgID, QString::number(++clsMsgSender::msulnglngMsgID));
                  //Insert entry into the map
                  clsMsgSender::msmpAcks.insert(std::make_pair(clsMsgSender::msulnglngMsgID, pAckMsgTrkr));
                  //Start the timer that will resend message if ack. not received
                  pAckMsgTrkr->pTimer->start(clsMsgSender::mscuint16AckTimeout);
                  

                  The value of 'mscuint16AckTimeout' is 5000 (milliseconds). I've also tried:

                  pAckMsgTrkr->pTimer->start(std::chrono::milliseconds(clsMsgSender::mscuint16AckTimeout));
                  

                  I have a break point in the lambda slot, it doesn't get hit.

                  KroMignonK Offline
                  KroMignonK Offline
                  KroMignon
                  wrote on last edited by KroMignon
                  #8

                  @SPlatten said in Timer with Lambda function:

                  I have a break point in the lambda slot, it doesn't get hit.

                  There are only 2 things why slot is not called:

                  • the thread in which the QTimer in living does not have a running event loop
                  • the event loop is locked (by a QThread::sleep() or a forever loop)

                  It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                  1 Reply Last reply
                  0
                  • SPlattenS Offline
                    SPlattenS Offline
                    SPlatten
                    wrote on last edited by
                    #9

                    I've re-written the code instead of a structure:

                        class clsMsgTrkr : QTimer {
                        private:
                            static const quint16 mscuint16AckTimeout = 5000;
                            static mmpAck msmpAcks;
                    
                            QJsonObject mobjMsg;
                            clsMsgSender* mpMsgSndr;
                    
                        public:
                            clsMsgTrkr(clsMsgSender* pMsgSndr, const QJsonObject& crobjJSON) {
                                setInterval(mscuint16AckTimeout);
                                mobjMsg = crobjJSON;
                                mpMsgSndr = pMsgSndr;
                        //Add tracker to list
                                clsMsgTrkr::msmpAcks.insert(std::make_pair(clsMsgSender::ulnglngGetMsgID(), this));
                    
                                QObject::connect(this, &QTimer::timeout, [this]() {
                                    qdbg() << "TIMEOUT!";
                                    //Re-send message
                                    emit mpMsgSndr->write(mobjMsg);
                                });
                                start();
                            }
                        };
                    

                    I can see in the debugger the constructor is getting called and processed the timer is started but I don't get anything in the slot.

                    Kind Regards,
                    Sy

                    jsulmJ JonBJ 2 Replies Last reply
                    0
                    • SPlattenS SPlatten

                      I've re-written the code instead of a structure:

                          class clsMsgTrkr : QTimer {
                          private:
                              static const quint16 mscuint16AckTimeout = 5000;
                              static mmpAck msmpAcks;
                      
                              QJsonObject mobjMsg;
                              clsMsgSender* mpMsgSndr;
                      
                          public:
                              clsMsgTrkr(clsMsgSender* pMsgSndr, const QJsonObject& crobjJSON) {
                                  setInterval(mscuint16AckTimeout);
                                  mobjMsg = crobjJSON;
                                  mpMsgSndr = pMsgSndr;
                          //Add tracker to list
                                  clsMsgTrkr::msmpAcks.insert(std::make_pair(clsMsgSender::ulnglngGetMsgID(), this));
                      
                                  QObject::connect(this, &QTimer::timeout, [this]() {
                                      qdbg() << "TIMEOUT!";
                                      //Re-send message
                                      emit mpMsgSndr->write(mobjMsg);
                                  });
                                  start();
                              }
                          };
                      

                      I can see in the debugger the constructor is getting called and processed the timer is started but I don't get anything in the slot.

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

                      @SPlatten Don't know why you are now subclassing QTimer...
                      You can add a destrcutor with debug output to see whether the instance is destroyed before timeout occurs.
                      Also check what others wrote.

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

                      1 Reply Last reply
                      1
                      • SPlattenS SPlatten

                        I've re-written the code instead of a structure:

                            class clsMsgTrkr : QTimer {
                            private:
                                static const quint16 mscuint16AckTimeout = 5000;
                                static mmpAck msmpAcks;
                        
                                QJsonObject mobjMsg;
                                clsMsgSender* mpMsgSndr;
                        
                            public:
                                clsMsgTrkr(clsMsgSender* pMsgSndr, const QJsonObject& crobjJSON) {
                                    setInterval(mscuint16AckTimeout);
                                    mobjMsg = crobjJSON;
                                    mpMsgSndr = pMsgSndr;
                            //Add tracker to list
                                    clsMsgTrkr::msmpAcks.insert(std::make_pair(clsMsgSender::ulnglngGetMsgID(), this));
                        
                                    QObject::connect(this, &QTimer::timeout, [this]() {
                                        qdbg() << "TIMEOUT!";
                                        //Re-send message
                                        emit mpMsgSndr->write(mobjMsg);
                                    });
                                    start();
                                }
                            };
                        

                        I can see in the debugger the constructor is getting called and processed the timer is started but I don't get anything in the slot.

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

                        @SPlatten
                        As @jsulm has just said. And as I suggested, put timeout down to 0 while you debug....

                        SPlattenS 1 Reply Last reply
                        0
                        • JonBJ JonB

                          @SPlatten
                          As @jsulm has just said. And as I suggested, put timeout down to 0 while you debug....

                          SPlattenS Offline
                          SPlattenS Offline
                          SPlatten
                          wrote on last edited by SPlatten
                          #12

                          I added a call after call:

                          start();
                          qdbg() << this->isActive();
                          

                          qdbg is just a macro I use which is:

                          #define qdbg()      qDebug().noquote().nospace()
                          

                          In the Application Output I see true so the timer is active, but doesn't timeout. Also, I just set the timer interval to 0, still no change, no timeout signal occurs.

                          Kind Regards,
                          Sy

                          KroMignonK 1 Reply Last reply
                          0
                          • SPlattenS SPlatten

                            I added a call after call:

                            start();
                            qdbg() << this->isActive();
                            

                            qdbg is just a macro I use which is:

                            #define qdbg()      qDebug().noquote().nospace()
                            

                            In the Application Output I see true so the timer is active, but doesn't timeout. Also, I just set the timer interval to 0, still no change, no timeout signal occurs.

                            KroMignonK Offline
                            KroMignonK Offline
                            KroMignon
                            wrote on last edited by
                            #13

                            @SPlatten said in Timer with Lambda function:

                            In the Application Output I see true so the timer is active, but doesn't timeout. Also, I just set the timer interval to 0, still no change, no timeout signal occurs.

                            Do you have a forever loop in your code or do you use QThread::sleep()?
                            Are you sure QEventLoop of the used thread is working?

                            It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                            SPlattenS 1 Reply Last reply
                            0
                            • KroMignonK KroMignon

                              @SPlatten said in Timer with Lambda function:

                              In the Application Output I see true so the timer is active, but doesn't timeout. Also, I just set the timer interval to 0, still no change, no timeout signal occurs.

                              Do you have a forever loop in your code or do you use QThread::sleep()?
                              Are you sure QEventLoop of the used thread is working?

                              SPlattenS Offline
                              SPlattenS Offline
                              SPlatten
                              wrote on last edited by
                              #14

                              @KroMignon, the message transmission is in a thread and there very short sleep in the thread loop:

                              void clsMsgSender::run() {    
                                  QJsonObject objJSON;
                                  while( blnAnythingToDo(objJSON) == true ) {
                                  //Sleep to allow a small cap between transmission
                                      QThread::usleep(100);
                                  //Look for a module name in the message
                                      QJsonObject::iterator itrFound = objJSON.find(clsJSON::mscszMsgType);
                              
                                      if ( itrFound != objJSON.end() ) {
                                          const QJsonValueRef crobjMsgType = itrFound.value();
                                          QString strMsgType(crobjMsgType.toString());
                              
                                          if ( strMsgType.compare(clsJSON::mscszAck) != 0 ) {
                                  //Insert a unique message ID into the message
                                              objJSON.insert(clsJSON::mscszMsgID, QString::number(++clsMsgSender::msulnglngMsgID));
                                  //Create entry to monitor status of this message
                                              new clsMsgTrkr(this, objJSON);
                                          }
                                      }
                                  //Writes message to socket
                                      emit write(objJSON);
                                  }
                                  emit queueEmpty();
                              }
                              

                              Kind Regards,
                              Sy

                              jsulmJ KroMignonK 2 Replies Last reply
                              0
                              • SPlattenS SPlatten

                                @KroMignon, the message transmission is in a thread and there very short sleep in the thread loop:

                                void clsMsgSender::run() {    
                                    QJsonObject objJSON;
                                    while( blnAnythingToDo(objJSON) == true ) {
                                    //Sleep to allow a small cap between transmission
                                        QThread::usleep(100);
                                    //Look for a module name in the message
                                        QJsonObject::iterator itrFound = objJSON.find(clsJSON::mscszMsgType);
                                
                                        if ( itrFound != objJSON.end() ) {
                                            const QJsonValueRef crobjMsgType = itrFound.value();
                                            QString strMsgType(crobjMsgType.toString());
                                
                                            if ( strMsgType.compare(clsJSON::mscszAck) != 0 ) {
                                    //Insert a unique message ID into the message
                                                objJSON.insert(clsJSON::mscszMsgID, QString::number(++clsMsgSender::msulnglngMsgID));
                                    //Create entry to monitor status of this message
                                                new clsMsgTrkr(this, objJSON);
                                            }
                                        }
                                    //Writes message to socket
                                        emit write(objJSON);
                                    }
                                    emit queueEmpty();
                                }
                                
                                jsulmJ Offline
                                jsulmJ Offline
                                jsulm
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                @SPlatten You expect this to work?

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

                                SPlattenS 1 Reply Last reply
                                0
                                • jsulmJ jsulm

                                  @SPlatten You expect this to work?

                                  SPlattenS Offline
                                  SPlattenS Offline
                                  SPlatten
                                  wrote on last edited by SPlatten
                                  #16

                                  @jsulm , ok, perhaps I'm to close to see the obvious, what have I done wrong? Its not complete yet, I haven't finished the code yet, but is there something that would explain why the timer isn't working?

                                  Kind Regards,
                                  Sy

                                  1 Reply Last reply
                                  0
                                  • SPlattenS SPlatten

                                    @KroMignon, the message transmission is in a thread and there very short sleep in the thread loop:

                                    void clsMsgSender::run() {    
                                        QJsonObject objJSON;
                                        while( blnAnythingToDo(objJSON) == true ) {
                                        //Sleep to allow a small cap between transmission
                                            QThread::usleep(100);
                                        //Look for a module name in the message
                                            QJsonObject::iterator itrFound = objJSON.find(clsJSON::mscszMsgType);
                                    
                                            if ( itrFound != objJSON.end() ) {
                                                const QJsonValueRef crobjMsgType = itrFound.value();
                                                QString strMsgType(crobjMsgType.toString());
                                    
                                                if ( strMsgType.compare(clsJSON::mscszAck) != 0 ) {
                                        //Insert a unique message ID into the message
                                                    objJSON.insert(clsJSON::mscszMsgID, QString::number(++clsMsgSender::msulnglngMsgID));
                                        //Create entry to monitor status of this message
                                                    new clsMsgTrkr(this, objJSON);
                                                }
                                            }
                                        //Writes message to socket
                                            emit write(objJSON);
                                        }
                                        emit queueEmpty();
                                    }
                                    
                                    KroMignonK Offline
                                    KroMignonK Offline
                                    KroMignon
                                    wrote on last edited by KroMignon
                                    #17

                                    @SPlatten I've told you many times to read basic Qt documentation.

                                    this cannot work!!!

                                    First, I suppose clsMsgSender is subclassing QThread. And you have create your own run() implementation. So there is no running QEventLoop. This means, all QObject which are running in this thread can NOT receive/emit signals.

                                    Second, you have a forever loop, so even if there where a running QEventLoop, it will not be called!

                                    It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                                    SPlattenS 1 Reply Last reply
                                    1
                                    • KroMignonK KroMignon

                                      @SPlatten I've told you many times to read basic Qt documentation.

                                      this cannot work!!!

                                      First, I suppose clsMsgSender is subclassing QThread. And you have create your own run() implementation. So there is no running QEventLoop. This means, all QObject which are running in this thread can NOT receive/emit signals.

                                      Second, you have a forever loop, so even if there where a running QEventLoop, it will not be called!

                                      SPlattenS Offline
                                      SPlattenS Offline
                                      SPlatten
                                      wrote on last edited by
                                      #18

                                      @KroMignon , I'm impatient, I know there is benefit from reading the documentation, I just don't want to stop what I'm doing to spend what would seem a long time to digest the documentation.

                                      Kind Regards,
                                      Sy

                                      KroMignonK jsulmJ 2 Replies Last reply
                                      0
                                      • SPlattenS SPlatten

                                        @KroMignon , I'm impatient, I know there is benefit from reading the documentation, I just don't want to stop what I'm doing to spend what would seem a long time to digest the documentation.

                                        KroMignonK Offline
                                        KroMignonK Offline
                                        KroMignon
                                        wrote on last edited by KroMignon
                                        #19

                                        @SPlatten said in Timer with Lambda function:

                                        I'm impatient,

                                        Perhaps you are impatient, but in fact you are losing days doing nonsense code which not working.
                                        If that is the best way to work, I am pretty sure NO.

                                        Reading this document would take you 1 or 2 hours, how many hours have you spend to create those non working code?

                                        It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                                        1 Reply Last reply
                                        2
                                        • SPlattenS SPlatten

                                          @KroMignon , I'm impatient, I know there is benefit from reading the documentation, I just don't want to stop what I'm doing to spend what would seem a long time to digest the documentation.

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

                                          @SPlatten said in Timer with Lambda function:

                                          I just don't want to stop what I'm doing to spend what would seem a long time to digest the documentation

                                          So, instead you waste your time here?
                                          I really don't get the logic...

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

                                          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