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. QTimer::singleShot()'s syntax

QTimer::singleShot()'s syntax

Scheduled Pinned Locked Moved Solved General and Desktop
34 Posts 9 Posters 11.3k 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.
  • A agarny
    12 Apr 2018, 07:46

    @JonB said in QTimer::singleShot()'s syntax:

    @agarny said in QTimer::singleShot()'s syntax:

    I have recently updated the code of my project to use the new signal/slot syntax, and did this for my calls to QTimer::singleShot().

    Just to absolutely clear (although you do seem to know what you are talking about, so this is perhaps obvious to you), given you are making this change:

    • You're not doing the change against a different version/compilation of Qt, are you?
    • Given that you are "cleaning up" code, there aren't any other changes to your code, are there?

    Indeed, I am using the same version of Qt (5.9.4) with both the old and new syntax. In fact, when it comes to this thread, the only thing I have done to my code is using either:

    QTimer::singleShot(0, this, SLOT(callCheckSimulationResults()));
    

    or

    QTimer::singleShot(0, this, &SimulationExperimentViewWidget::callCheckSimulationResults);
    

    The rest of my code is exactly the same.

    K Offline
    K Offline
    kshegunov
    Moderators
    wrote on 12 Apr 2018, 08:45 last edited by kshegunov 4 Dec 2018, 08:48
    #17

    https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L199

    Your threading is all jumbled up, you can't just read and modify fields from objects that are in different threads ... if it works, it's the hand of god, if it doesn't work, it's the hand of god as well ... (and that one comes from an atheist)

    To give you a straightforwardly obvious example:
    https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L95

    What's guarding mCurrentPoint?
    I would also imagine you may get a lot of runtime warnings from Qt about objects being created before QApplication (due to singletons) and possibly also warnings about destruction order or destructions from different threads.

    Read and abide by the Qt Code of Conduct

    A 2 Replies Last reply 12 Apr 2018, 10:53
    7
    • K kshegunov
      12 Apr 2018, 08:45

      https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L199

      Your threading is all jumbled up, you can't just read and modify fields from objects that are in different threads ... if it works, it's the hand of god, if it doesn't work, it's the hand of god as well ... (and that one comes from an atheist)

      To give you a straightforwardly obvious example:
      https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L95

      What's guarding mCurrentPoint?
      I would also imagine you may get a lot of runtime warnings from Qt about objects being created before QApplication (due to singletons) and possibly also warnings about destruction order or destructions from different threads.

      A Offline
      A Offline
      agarny
      wrote on 12 Apr 2018, 10:53 last edited by
      #18

      @kshegunov: yes, I think it's starting to become very clear that I am facing a race condition and that I have been pretty lucky these past few years. Ok, I guess I am going to have to check that very carefully. (In the end, it's a good thing that I decided to use the new syntax... (Positive thinking... :))

      1 Reply Last reply
      3
      • K kshegunov
        12 Apr 2018, 08:45

        https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L199

        Your threading is all jumbled up, you can't just read and modify fields from objects that are in different threads ... if it works, it's the hand of god, if it doesn't work, it's the hand of god as well ... (and that one comes from an atheist)

        To give you a straightforwardly obvious example:
        https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L95

        What's guarding mCurrentPoint?
        I would also imagine you may get a lot of runtime warnings from Qt about objects being created before QApplication (due to singletons) and possibly also warnings about destruction order or destructions from different threads.

        A Offline
        A Offline
        agarny
        wrote on 12 Apr 2018, 10:57 last edited by
        #19

        @kshegunov: by the way, no, I am not getting any runtime warnings from Qt.

        K 1 Reply Last reply 12 Apr 2018, 18:37
        0
        • A agarny
          12 Apr 2018, 10:57

          @kshegunov: by the way, no, I am not getting any runtime warnings from Qt.

          K Offline
          K Offline
          kshegunov
          Moderators
          wrote on 12 Apr 2018, 18:37 last edited by
          #20

          a race condition

          More than one, I noticed at least several in that particular file.

          by the way, no, I am not getting any runtime warnings from Qt.

          I said you may, not that you are going to, as I didn't check the whole source. I spotted a place or two where you use the singleton, so that's usually accompanied by such warnings.

          Read and abide by the Qt Code of Conduct

          A 1 Reply Last reply 12 Apr 2018, 19:25
          0
          • K kshegunov
            12 Apr 2018, 18:37

            a race condition

            More than one, I noticed at least several in that particular file.

            by the way, no, I am not getting any runtime warnings from Qt.

            I said you may, not that you are going to, as I didn't check the whole source. I spotted a place or two where you use the singleton, so that's usually accompanied by such warnings.

            A Offline
            A Offline
            agarny
            wrote on 12 Apr 2018, 19:25 last edited by
            #21

            @kshegunov said in QTimer::singleShot()'s syntax:

            a race condition

            More than one, I noticed at least several in that particular file.

            Would you mind letting me know (via MP, if you want) those you noticed?

            by the way, no, I am not getting any runtime warnings from Qt.

            I said you may, not that you are going to, as I didn't check the whole source. I spotted a place or two where you use the singleton, so that's usually accompanied by such warnings.

            Yes, I know what you said. I was merely pointing out that, in my particular case, I am not getting runtime warnings.

            Otherwise, when it comes to my singletons, I believe they are always used in the main thread. This being said, I am going to double check and also make sure that they are thread safe. So, thanks for the reminder.

            K 1 Reply Last reply 12 Apr 2018, 19:37
            0
            • A agarny
              12 Apr 2018, 19:25

              @kshegunov said in QTimer::singleShot()'s syntax:

              a race condition

              More than one, I noticed at least several in that particular file.

              Would you mind letting me know (via MP, if you want) those you noticed?

              by the way, no, I am not getting any runtime warnings from Qt.

              I said you may, not that you are going to, as I didn't check the whole source. I spotted a place or two where you use the singleton, so that's usually accompanied by such warnings.

              Yes, I know what you said. I was merely pointing out that, in my particular case, I am not getting runtime warnings.

              Otherwise, when it comes to my singletons, I believe they are always used in the main thread. This being said, I am going to double check and also make sure that they are thread safe. So, thanks for the reminder.

              K Offline
              K Offline
              kshegunov
              Moderators
              wrote on 12 Apr 2018, 19:37 last edited by
              #22

              @agarny said in QTimer::singleShot()'s syntax:

              https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L207
              https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L214
              https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L215
              https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L217
              https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L235
              https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L236
              https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L237
              https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L244

              And so on ... the list is very, very long.

              As far as I could see only the SimulationWorker object is moved to a separate thread, so you should focus your efforts there. For one don't pass it objects that are in different threads (e.g. Simulation class's mSimulation), as it gets quite alluring to just call methods on them (which is a race condition). Instead, move the setters of SimulationWorker as slots and emit signals when any of the private/calculated data has changed. Then you can connect those signals and slots from the outside and Qt will take care of the access serialization for you.

              Read and abide by the Qt Code of Conduct

              A 1 Reply Last reply 12 Apr 2018, 20:15
              4
              • K kshegunov
                12 Apr 2018, 19:37

                @agarny said in QTimer::singleShot()'s syntax:

                https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L207
                https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L214
                https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L215
                https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L217
                https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L235
                https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L236
                https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L237
                https://github.com/opencor/opencor/blob/master/src/plugins/support/SimulationSupport/src/simulationworker.cpp#L244

                And so on ... the list is very, very long.

                As far as I could see only the SimulationWorker object is moved to a separate thread, so you should focus your efforts there. For one don't pass it objects that are in different threads (e.g. Simulation class's mSimulation), as it gets quite alluring to just call methods on them (which is a race condition). Instead, move the setters of SimulationWorker as slots and emit signals when any of the private/calculated data has changed. Then you can connect those signals and slots from the outside and Qt will take care of the access serialization for you.

                A Offline
                A Offline
                agarny
                wrote on 12 Apr 2018, 20:15 last edited by
                #23

                @kshegunov: thanks, I appreciate the heads-up.

                FWIW, the purpose of my SimulationWorker class is, as you probably gathered, to compute some mathematical model, so I don't want this work to overload the main thread (and therefore "freeze" my GUI), hence I indeed decided to move it to a separate thread.

                Regarding the Simulation object I pass to my SimulationWorker object, it is used to retrieve some information about my simulation (which have been set before running the worker and that don't get changed during the worker's lifespan), as well as add to it the results of the worker (i.e. simulation results). Then, my main thread (and the reason I originally decided to have that QTimer::singleSlot() calls) checks whether new results are available. So, no writing there, just fetching.

                Anyway, I appreciate that it could be improved when it comes thread safety, and I will make sure that it is. FWIW, I did, at some point, rely on the signal/slot mechanism for my worker, but it slowed things down quite a bit, hence I went for the approach I have just described above.

                JKSHJ 1 Reply Last reply 12 Apr 2018, 23:22
                0
                • A agarny
                  12 Apr 2018, 20:15

                  @kshegunov: thanks, I appreciate the heads-up.

                  FWIW, the purpose of my SimulationWorker class is, as you probably gathered, to compute some mathematical model, so I don't want this work to overload the main thread (and therefore "freeze" my GUI), hence I indeed decided to move it to a separate thread.

                  Regarding the Simulation object I pass to my SimulationWorker object, it is used to retrieve some information about my simulation (which have been set before running the worker and that don't get changed during the worker's lifespan), as well as add to it the results of the worker (i.e. simulation results). Then, my main thread (and the reason I originally decided to have that QTimer::singleSlot() calls) checks whether new results are available. So, no writing there, just fetching.

                  Anyway, I appreciate that it could be improved when it comes thread safety, and I will make sure that it is. FWIW, I did, at some point, rely on the signal/slot mechanism for my worker, but it slowed things down quite a bit, hence I went for the approach I have just described above.

                  JKSHJ Offline
                  JKSHJ Offline
                  JKSH
                  Moderators
                  wrote on 12 Apr 2018, 23:22 last edited by
                  #24

                  @agarny said in QTimer::singleShot()'s syntax:

                  Anyway, I appreciate that it could be improved when it comes thread safety, and I will make sure that it is. FWIW, I did, at some point, rely on the signal/slot mechanism for my worker, but it slowed things down quite a bit, hence I went for the approach I have just described above.

                  See http://doc.qt.io/qt-5/threads-synchronizing.html It sounds like the high-level approach slows things down noticeably for you, so go with the low-level ones instead.

                  Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                  A 1 Reply Last reply 13 Apr 2018, 01:02
                  1
                  • JKSHJ JKSH
                    12 Apr 2018, 23:22

                    @agarny said in QTimer::singleShot()'s syntax:

                    Anyway, I appreciate that it could be improved when it comes thread safety, and I will make sure that it is. FWIW, I did, at some point, rely on the signal/slot mechanism for my worker, but it slowed things down quite a bit, hence I went for the approach I have just described above.

                    See http://doc.qt.io/qt-5/threads-synchronizing.html It sounds like the high-level approach slows things down noticeably for you, so go with the low-level ones instead.

                    A Offline
                    A Offline
                    agarny
                    wrote on 13 Apr 2018, 01:02 last edited by
                    #25

                    @JKSH said in QTimer::singleShot()'s syntax:

                    See http://doc.qt.io/qt-5/threads-synchronizing.html It sounds like the high-level approach slows things down noticeably for you, so go with the low-level ones instead.

                    Yes, I am already using low-level synchronization primitives in parts of my code, and this is the approach I am thinking of taking here too.

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      agarny
                      wrote on 13 Apr 2018, 06:37 last edited by
                      #26

                      Ok, on further investigation, the symptom described in my original message is not the result of a race condition. I agree that it is not to say that my code is free of race conditions, although I am relatively confident that it is. Not so much because of the quality of my code, but rather because of the way it is used. Now, I know it's not great, but that's the compromise I had to make for my code to be as fast as possible, something that is important for my application.

                      Anyway, among other things, my application can "run" mathematical models and, until recently, it could only render one run at a time. Recently, I have modified my application so that it could render multiple runs and this is where the problem was. I wasn't properly handling multiple runs and because of the low overhead associated with the new QTimer::singleShot syntax (compared with the old syntax), my application didn't render the end of some runs. I now "properly" handle multiple runs and everything works as expected (see here for those who had a look at my code before).

                      So, thanks all for your feedback, it was much appreciated. (Thanks @VRonin for your std::bind() suggestion, which I now use.)

                      aha_1980A 1 Reply Last reply 13 Apr 2018, 07:23
                      0
                      • A agarny
                        13 Apr 2018, 06:37

                        Ok, on further investigation, the symptom described in my original message is not the result of a race condition. I agree that it is not to say that my code is free of race conditions, although I am relatively confident that it is. Not so much because of the quality of my code, but rather because of the way it is used. Now, I know it's not great, but that's the compromise I had to make for my code to be as fast as possible, something that is important for my application.

                        Anyway, among other things, my application can "run" mathematical models and, until recently, it could only render one run at a time. Recently, I have modified my application so that it could render multiple runs and this is where the problem was. I wasn't properly handling multiple runs and because of the low overhead associated with the new QTimer::singleShot syntax (compared with the old syntax), my application didn't render the end of some runs. I now "properly" handle multiple runs and everything works as expected (see here for those who had a look at my code before).

                        So, thanks all for your feedback, it was much appreciated. (Thanks @VRonin for your std::bind() suggestion, which I now use.)

                        aha_1980A Offline
                        aha_1980A Offline
                        aha_1980
                        Lifetime Qt Champion
                        wrote on 13 Apr 2018, 07:23 last edited by
                        #27

                        @agarny said in QTimer::singleShot()'s syntax:

                        Now, I know it's not great, but that's the compromise I had to make for my code to be as fast as possible, something that is important for my application.

                        Are you really going to say that fast code must be buggy?

                        Good luck with newer versions of your project. It may work more or less now, but when you add functionality sooner or later all uncleanliness hits back.

                        Qt has to stay free or it will die.

                        A 1 Reply Last reply 13 Apr 2018, 08:03
                        3
                        • VRoninV Offline
                          VRoninV Offline
                          VRonin
                          wrote on 13 Apr 2018, 07:31 last edited by
                          #28

                          Mathematical model + race condition = quantum model I guess 🙂

                          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                          ~Napoleon Bonaparte

                          On a crusade to banish setIndexWidget() from the holy land of Qt

                          1 Reply Last reply
                          5
                          • aha_1980A aha_1980
                            13 Apr 2018, 07:23

                            @agarny said in QTimer::singleShot()'s syntax:

                            Now, I know it's not great, but that's the compromise I had to make for my code to be as fast as possible, something that is important for my application.

                            Are you really going to say that fast code must be buggy?

                            Good luck with newer versions of your project. It may work more or less now, but when you add functionality sooner or later all uncleanliness hits back.

                            A Offline
                            A Offline
                            agarny
                            wrote on 13 Apr 2018, 08:03 last edited by
                            #29

                            @aha_1980 said in QTimer::singleShot()'s syntax:

                            @agarny said in QTimer::singleShot()'s syntax:

                            Now, I know it's not great, but that's the compromise I had to make for my code to be as fast as possible, something that is important for my application.

                            Are you really going to say that fast code must be buggy?

                            No, this is not what I am going to say otherwise I would have already said it.

                            I merely said that to get the speed I was after I felt the need to make some compromises and that I am aware of their limitations, hence I have done my best to ensure that my code doesn't result in a race condition, etc. Should I ever find a solution that is "cleaner" and as fast as my current solution, then I will clearly implement it.

                            (Thanks for the sarcasm.)

                            K 1 Reply Last reply 13 Apr 2018, 08:09
                            0
                            • A agarny
                              13 Apr 2018, 08:03

                              @aha_1980 said in QTimer::singleShot()'s syntax:

                              @agarny said in QTimer::singleShot()'s syntax:

                              Now, I know it's not great, but that's the compromise I had to make for my code to be as fast as possible, something that is important for my application.

                              Are you really going to say that fast code must be buggy?

                              No, this is not what I am going to say otherwise I would have already said it.

                              I merely said that to get the speed I was after I felt the need to make some compromises and that I am aware of their limitations, hence I have done my best to ensure that my code doesn't result in a race condition, etc. Should I ever find a solution that is "cleaner" and as fast as my current solution, then I will clearly implement it.

                              (Thanks for the sarcasm.)

                              K Offline
                              K Offline
                              kshegunov
                              Moderators
                              wrote on 13 Apr 2018, 08:09 last edited by kshegunov
                              #30

                              @aha_1980's point is that you're building a house of cards here. Even if you don't see the effects now it is going to bite you in the a$$ sometime along the road. Remember what I wrote before: "If it works, it's the hand of god", well that's what he and I both mean. It's your code in the end and you can conduct your business as you like, we just felt it's a rather weak argument to ignore the simmering reality because you couldn't get enough speed at the time. In the end the speed would not matter if you don't get correct results, would it?

                              Read and abide by the Qt Code of Conduct

                              A 1 Reply Last reply 13 Apr 2018, 08:37
                              3
                              • K kshegunov
                                13 Apr 2018, 08:09

                                @aha_1980's point is that you're building a house of cards here. Even if you don't see the effects now it is going to bite you in the a$$ sometime along the road. Remember what I wrote before: "If it works, it's the hand of god", well that's what he and I both mean. It's your code in the end and you can conduct your business as you like, we just felt it's a rather weak argument to ignore the simmering reality because you couldn't get enough speed at the time. In the end the speed would not matter if you don't get correct results, would it?

                                A Offline
                                A Offline
                                agarny
                                wrote on 13 Apr 2018, 08:37 last edited by agarny
                                #31

                                @kshegunov: I do hear what you are both saying, believe it or not (see above my comment about ever finding a "cleaner" solution).

                                J 1 Reply Last reply 13 Apr 2024, 15:04
                                0
                                • A agarny
                                  13 Apr 2018, 08:37

                                  @kshegunov: I do hear what you are both saying, believe it or not (see above my comment about ever finding a "cleaner" solution).

                                  J Offline
                                  J Offline
                                  Joe von Habsburg
                                  wrote on 13 Apr 2024, 15:04 last edited by Joe von Habsburg
                                  #32

                                  @agarny @JonB @aha_1980 @J-Hilk @JKSH @kshegunov @mrjj @VRonin

                                  I would like to add condition to singleshot like that

                                  bool youCanRun = true;
                                  
                                  timer.singleShot(1000, this, &MyClass::mySlot, youCanRun );
                                  
                                  // if youCanRun == true => singleshot will work
                                  // else singleshot won't work
                                  
                                  

                                  Note : "youCanRun" could be changed in singleshot waiting time

                                  Is there any syntax or methot I could use?

                                  JKSHJ 1 Reply Last reply 13 Apr 2024, 15:35
                                  0
                                  • J Joe von Habsburg
                                    13 Apr 2024, 15:04

                                    @agarny @JonB @aha_1980 @J-Hilk @JKSH @kshegunov @mrjj @VRonin

                                    I would like to add condition to singleshot like that

                                    bool youCanRun = true;
                                    
                                    timer.singleShot(1000, this, &MyClass::mySlot, youCanRun );
                                    
                                    // if youCanRun == true => singleshot will work
                                    // else singleshot won't work
                                    
                                    

                                    Note : "youCanRun" could be changed in singleshot waiting time

                                    Is there any syntax or methot I could use?

                                    JKSHJ Offline
                                    JKSHJ Offline
                                    JKSH
                                    Moderators
                                    wrote on 13 Apr 2024, 15:35 last edited by
                                    #33

                                    @Joe-von-Habsburg said in QTimer::singleShot()'s syntax:

                                    @agarny @JonB @aha_1980 @J-Hilk @JKSH @kshegunov @mrjj @VRonin

                                    I would like to add condition to singleshot like that

                                    bool youCanRun = true;
                                    
                                    timer.singleShot(1000, this, &MyClass::mySlot, youCanRun );
                                    
                                    // if youCanRun == true => singleshot will work
                                    // else singleshot won't work
                                    
                                    

                                    Note : "youCanRun" could be changed in singleshot waiting time

                                    Is there any syntax or methot I could use?

                                    Use a lambda. Check the value of youCanRun and call your slot if it is true.

                                    bool youCanRun = true; // NOTE: This variable must not go out-of-scope before the timer is triggered
                                    
                                    QTimer::singleShot(1000, this, [&]{
                                        if (youCanRun)
                                            this->mySlot();
                                        else
                                            qDebug("You cannot run!");
                                    });
                                    

                                    Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                                    J 1 Reply Last reply 13 Apr 2024, 15:37
                                    5
                                    • JKSHJ JKSH
                                      13 Apr 2024, 15:35

                                      @Joe-von-Habsburg said in QTimer::singleShot()'s syntax:

                                      @agarny @JonB @aha_1980 @J-Hilk @JKSH @kshegunov @mrjj @VRonin

                                      I would like to add condition to singleshot like that

                                      bool youCanRun = true;
                                      
                                      timer.singleShot(1000, this, &MyClass::mySlot, youCanRun );
                                      
                                      // if youCanRun == true => singleshot will work
                                      // else singleshot won't work
                                      
                                      

                                      Note : "youCanRun" could be changed in singleshot waiting time

                                      Is there any syntax or methot I could use?

                                      Use a lambda. Check the value of youCanRun and call your slot if it is true.

                                      bool youCanRun = true; // NOTE: This variable must not go out-of-scope before the timer is triggered
                                      
                                      QTimer::singleShot(1000, this, [&]{
                                          if (youCanRun)
                                              this->mySlot();
                                          else
                                              qDebug("You cannot run!");
                                      });
                                      
                                      J Offline
                                      J Offline
                                      Joe von Habsburg
                                      wrote on 13 Apr 2024, 15:37 last edited by
                                      #34

                                      @JKSH thank you :)

                                      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