Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Unix signals and QCharts cause application blocking
Forum Updated to NodeBB v4.3 + New Features

Unix signals and QCharts cause application blocking

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
29 Posts 2 Posters 2.8k 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.
  • T Offline
    T Offline
    tovax
    wrote on 24 Mar 2023, 03:45 last edited by tovax
    #1

    Hi, all
    I want to capture unix signals in qt applications, and this article (Calling Qt Functions From Unix Signal Handlers) has solved my problem very well.
    However, I recently added the charts module and found that applications often get blocked. So, I deleted the unrelated application code and tried to find the cause of the blocking, but failed.
    I uploaded the simple demo code to github (JCDemoDriver), hoping to get some suggestions. Thank you for your responses.

    Best regards.

    1 Reply Last reply
    0
    • T Offline
      T Offline
      tovax
      wrote on 25 Mar 2023, 03:22 last edited by tovax
      #2

      After further testing, the cause of application blocking comes from timer event, not charts module.
      The longer the sleep time in the timerEvent, the more likely it is to cause application blocking.
      github updated: JCDemoDriver

      void JCDemoDriver::timerEvent(QTimerEvent *event)
      {
          if (event->timerId() != mTimerId) {
              qDebug() << __FUNCTION__ << __LINE__;
              return;
          }
      #if 1
          static int = 0;
          qDebug() << __FUNCTION__ << cnt++;
      #endif
          QThread::msleep(100); // causes the application blocking
      }
      
      J 1 Reply Last reply 25 Mar 2023, 08:10
      0
      • T tovax
        25 Mar 2023, 03:22

        After further testing, the cause of application blocking comes from timer event, not charts module.
        The longer the sleep time in the timerEvent, the more likely it is to cause application blocking.
        github updated: JCDemoDriver

        void JCDemoDriver::timerEvent(QTimerEvent *event)
        {
            if (event->timerId() != mTimerId) {
                qDebug() << __FUNCTION__ << __LINE__;
                return;
            }
        #if 1
            static int = 0;
            qDebug() << __FUNCTION__ << cnt++;
        #endif
            QThread::msleep(100); // causes the application blocking
        }
        
        J Online
        J Online
        JonB
        wrote on 25 Mar 2023, 08:10 last edited by
        #3

        @tovax
        Is there a question here, or are you just making a statement? Yes msleep() in the UI thread will cause blocking, do you expect otherwise?

        T 1 Reply Last reply 25 Mar 2023, 09:12
        0
        • J JonB
          25 Mar 2023, 08:10

          @tovax
          Is there a question here, or are you just making a statement? Yes msleep() in the UI thread will cause blocking, do you expect otherwise?

          T Offline
          T Offline
          tovax
          wrote on 25 Mar 2023, 09:12 last edited by
          #4

          @JonB Hi, thank you very much. It's just a statement. msleep() caused the application to freeze forever.

          J 1 Reply Last reply 25 Mar 2023, 09:37
          0
          • T tovax
            25 Mar 2023, 09:12

            @JonB Hi, thank you very much. It's just a statement. msleep() caused the application to freeze forever.

            J Online
            J Online
            JonB
            wrote on 25 Mar 2023, 09:37 last edited by
            #5

            @tovax
            It will certainly block the UI for as long as the parameter. It ought not block it "forever", but I don't know if there is something about the way they are handling Linux signals for which this is problematic.

            T 2 Replies Last reply 25 Mar 2023, 09:42
            0
            • J JonB
              25 Mar 2023, 09:37

              @tovax
              It will certainly block the UI for as long as the parameter. It ought not block it "forever", but I don't know if there is something about the way they are handling Linux signals for which this is problematic.

              T Offline
              T Offline
              tovax
              wrote on 25 Mar 2023, 09:42 last edited by
              #6

              @JonB It does not freeze the application at the beginning, but occurs after running for a few seconds, depending on the frequency of the signal sent from the Linux driver.

              1 Reply Last reply
              0
              • J JonB
                25 Mar 2023, 09:37

                @tovax
                It will certainly block the UI for as long as the parameter. It ought not block it "forever", but I don't know if there is something about the way they are handling Linux signals for which this is problematic.

                T Offline
                T Offline
                tovax
                wrote on 25 Mar 2023, 09:48 last edited by
                #7

                @JonB
                I have updated github and added a simple driver.
                JCDemoDriver
                Both the application and driver have been tested on Ubuntu.
                The previous version was tested on IMX6U+Linux, and is the same as the Ubuntu platform, with applications permanently frozen.

                J 1 Reply Last reply 25 Mar 2023, 09:52
                0
                • T tovax
                  25 Mar 2023, 09:48

                  @JonB
                  I have updated github and added a simple driver.
                  JCDemoDriver
                  Both the application and driver have been tested on Ubuntu.
                  The previous version was tested on IMX6U+Linux, and is the same as the Ubuntu platform, with applications permanently frozen.

                  J Online
                  J Online
                  JonB
                  wrote on 25 Mar 2023, 09:52 last edited by JonB
                  #8

                  @tovax
                  Your timer times out every 100ms, and in the slot you sleep for 100ms. This may not be a good combination. This implies it will be close to permanently sleeping: as soon the sleep terminates the next timer timeout will occur and go back into sleep more or less immediately. BTW, if you expect the timer timeout to only start counting again after the sleep, that's not the way it works. I suggest any sleep needs at least to be for a lesser period than the repeated time outs, e.g. no more than 50 for a timeout of 100?

                  T 2 Replies Last reply 25 Mar 2023, 10:17
                  0
                  • J JonB
                    25 Mar 2023, 09:52

                    @tovax
                    Your timer times out every 100ms, and in the slot you sleep for 100ms. This may not be a good combination. This implies it will be close to permanently sleeping: as soon the sleep terminates the next timer timeout will occur and go back into sleep more or less immediately. BTW, if you expect the timer timeout to only start counting again after the sleep, that's not the way it works. I suggest any sleep needs at least to be for a lesser period than the repeated time outs, e.g. no more than 50 for a timeout of 100?

                    T Offline
                    T Offline
                    tovax
                    wrote on 25 Mar 2023, 10:17 last edited by
                    #9

                    @JonB
                    According to your suggestion, I retested it. Without a driver, there is no problem that the sleep time is greater than the timer period. For example, a timer cycle of 100 milliseconds and a sleep period of 200 milliseconds do not cause freezing. This causes the timerEvent to be counted every 200 milliseconds.

                    J 1 Reply Last reply 25 Mar 2023, 10:25
                    0
                    • T tovax
                      25 Mar 2023, 10:17

                      @JonB
                      According to your suggestion, I retested it. Without a driver, there is no problem that the sleep time is greater than the timer period. For example, a timer cycle of 100 milliseconds and a sleep period of 200 milliseconds do not cause freezing. This causes the timerEvent to be counted every 200 milliseconds.

                      J Online
                      J Online
                      JonB
                      wrote on 25 Mar 2023, 10:25 last edited by JonB
                      #10

                      @tovax
                      I would start by seeing whether in your case the activated() signals are being emitted and whether the handleSig...() slots are getting called at all.
                      And with judicious placement of qDebug() statements you may be able to find where it is "freezing".

                      T 1 Reply Last reply 25 Mar 2023, 10:32
                      0
                      • J JonB
                        25 Mar 2023, 10:25

                        @tovax
                        I would start by seeing whether in your case the activated() signals are being emitted and whether the handleSig...() slots are getting called at all.
                        And with judicious placement of qDebug() statements you may be able to find where it is "freezing".

                        T Offline
                        T Offline
                        tovax
                        wrote on 25 Mar 2023, 10:32 last edited by
                        #11

                        @JonB
                        I can only make sure that the driver is working correctly at the time of the freeze, and I don't know what state the socket is in. Can you give me some guidance? The thread pool was tested yesterday, and the sub threads did not output when it was frozen.

                        J 1 Reply Last reply 25 Mar 2023, 10:41
                        0
                        • T tovax
                          25 Mar 2023, 10:32

                          @JonB
                          I can only make sure that the driver is working correctly at the time of the freeze, and I don't know what state the socket is in. Can you give me some guidance? The thread pool was tested yesterday, and the sub threads did not output when it was frozen.

                          J Online
                          J Online
                          JonB
                          wrote on 25 Mar 2023, 10:41 last edited by JonB
                          #12

                          @tovax
                          Put regular qDebug() statements into unixSignalHandler() & qtSignalHandler(), and also in timerEvent(), say between every line, and see what the last output you get was.

                          T 1 Reply Last reply 25 Mar 2023, 10:46
                          0
                          • J JonB
                            25 Mar 2023, 09:52

                            @tovax
                            Your timer times out every 100ms, and in the slot you sleep for 100ms. This may not be a good combination. This implies it will be close to permanently sleeping: as soon the sleep terminates the next timer timeout will occur and go back into sleep more or less immediately. BTW, if you expect the timer timeout to only start counting again after the sleep, that's not the way it works. I suggest any sleep needs at least to be for a lesser period than the repeated time outs, e.g. no more than 50 for a timeout of 100?

                            T Offline
                            T Offline
                            tovax
                            wrote on 25 Mar 2023, 10:41 last edited by
                            #13

                            @JonB said in Unix signals and QCharts cause application blocking:

                            @tovax
                            Your timer times out every 100ms, and in the slot you sleep for 100ms. This may not be a good combination. This implies it will be close to permanently sleeping: as soon the sleep terminates the next timer timeout will occur and go back into sleep more or less immediately. BTW, if you expect the timer timeout to only start counting again after the sleep, that's not the way it works. I suggest any sleep needs at least to be for a lesser period than the repeated time outs, e.g. no more than 50 for a timeout of 100?

                            In the case of driving working, it is indeed a critical value for sleep time to be equal to the timing period. When the sleep time is less than the timing period, the test is no problem. When the sleep time is greater than or equal to the timing period, it can cause the application to freeze forever.

                            When the driver is not working, the sleep time is independent of the timing cycle, and the application works normally.

                            J 1 Reply Last reply 25 Mar 2023, 10:45
                            0
                            • T tovax
                              25 Mar 2023, 10:41

                              @JonB said in Unix signals and QCharts cause application blocking:

                              @tovax
                              Your timer times out every 100ms, and in the slot you sleep for 100ms. This may not be a good combination. This implies it will be close to permanently sleeping: as soon the sleep terminates the next timer timeout will occur and go back into sleep more or less immediately. BTW, if you expect the timer timeout to only start counting again after the sleep, that's not the way it works. I suggest any sleep needs at least to be for a lesser period than the repeated time outs, e.g. no more than 50 for a timeout of 100?

                              In the case of driving working, it is indeed a critical value for sleep time to be equal to the timing period. When the sleep time is less than the timing period, the test is no problem. When the sleep time is greater than or equal to the timing period, it can cause the application to freeze forever.

                              When the driver is not working, the sleep time is independent of the timing cycle, and the application works normally.

                              J Online
                              J Online
                              JonB
                              wrote on 25 Mar 2023, 10:45 last edited by
                              #14

                              @tovax
                              The QTimer you are using is not precisely "accurate". If you rely on it being exactly 100ms that is not good.

                              If I were you I would still want to know where/why the "freeze" occurs.

                              T 1 Reply Last reply 25 Mar 2023, 10:50
                              0
                              • J JonB
                                25 Mar 2023, 10:41

                                @tovax
                                Put regular qDebug() statements into unixSignalHandler() & qtSignalHandler(), and also in timerEvent(), say between every line, and see what the last output you get was.

                                T Offline
                                T Offline
                                tovax
                                wrote on 25 Mar 2023, 10:46 last edited by
                                #15

                                @JonB said in Unix signals and QCharts cause application blocking:

                                @tovax
                                Put regular qDebug() statements into unixSignalHandler() & qtSignalHandler(), and also in timerEvent(), say between every line, and see what the last output you get was.

                                void PanelDriver::unixSignalHandler(int)
                                {
                                    qDebug() << __FUNCTION__ << 0;
                                    char a = 1;
                                    ::write(mSocketFd[0], &a, sizeof(a));
                                    qDebug() << __FUNCTION__ << 1;
                                }
                                
                                void PanelDriver::qtSignalHandler()
                                {
                                    qDebug() << __FUNCTION__ << 0;
                                    mSocketNotifier->setEnabled(false);
                                    qDebug() << __FUNCTION__ << 1;
                                    char tmp;
                                    ::read(mSocketFd[1], &tmp, sizeof(tmp));
                                    qDebug() << __FUNCTION__ << 2;
                                
                                    // do Qt stuff
                                    static int cnt = 0;
                                    qDebug() << __FUNCTION__ << cnt++;
                                    emit panelChanged();
                                    qDebug() << __FUNCTION__ << 3;
                                
                                    mSocketNotifier->setEnabled(true);
                                    qDebug() << __FUNCTION__ << 4;
                                }
                                

                                debug output:

                                unixSignalHandler 0
                                unixSignalHandler 1
                                unixSignalHandler 0
                                unixSignalHandler 1
                                timerEvent QTime("18:43:29.352")
                                qtSignalHandler 0
                                qtSignalHandler 1
                                qtSignalHandler 2
                                qtSignalHandler 56
                                qtSignalHandler 3
                                qtSignalHandler 4
                                unixSignalHandler 0
                                unixSignalHandler 1
                                unixSignalHandler 0
                                unixSignalHandler 1
                                unixSignalHandler 0
                                unixSignalHandler 0
                                unixSignalHandler 0
                                unixSignalHandler 0
                                unixSignalHandler 0
                                

                                From the debugging output, the possible problem is:

                                 :: write (mSocketFd [0],&a, sizeof (a));
                                
                                J 1 Reply Last reply 25 Mar 2023, 10:56
                                0
                                • J JonB
                                  25 Mar 2023, 10:45

                                  @tovax
                                  The QTimer you are using is not precisely "accurate". If you rely on it being exactly 100ms that is not good.

                                  If I were you I would still want to know where/why the "freeze" occurs.

                                  T Offline
                                  T Offline
                                  tovax
                                  wrote on 25 Mar 2023, 10:50 last edited by
                                  #16

                                  @JonB said in Unix signals and QCharts cause application blocking:

                                  @tovax
                                  The QTimer you are using is not precisely "accurate". If you rely on it being exactly 100ms that is not good.

                                  If I were you I would still want to know where/why the "freeze" occurs.

                                  Yes, I particularly want to know why this abnormal freezing occurs.

                                  1 Reply Last reply
                                  0
                                  • T tovax
                                    25 Mar 2023, 10:46

                                    @JonB said in Unix signals and QCharts cause application blocking:

                                    @tovax
                                    Put regular qDebug() statements into unixSignalHandler() & qtSignalHandler(), and also in timerEvent(), say between every line, and see what the last output you get was.

                                    void PanelDriver::unixSignalHandler(int)
                                    {
                                        qDebug() << __FUNCTION__ << 0;
                                        char a = 1;
                                        ::write(mSocketFd[0], &a, sizeof(a));
                                        qDebug() << __FUNCTION__ << 1;
                                    }
                                    
                                    void PanelDriver::qtSignalHandler()
                                    {
                                        qDebug() << __FUNCTION__ << 0;
                                        mSocketNotifier->setEnabled(false);
                                        qDebug() << __FUNCTION__ << 1;
                                        char tmp;
                                        ::read(mSocketFd[1], &tmp, sizeof(tmp));
                                        qDebug() << __FUNCTION__ << 2;
                                    
                                        // do Qt stuff
                                        static int cnt = 0;
                                        qDebug() << __FUNCTION__ << cnt++;
                                        emit panelChanged();
                                        qDebug() << __FUNCTION__ << 3;
                                    
                                        mSocketNotifier->setEnabled(true);
                                        qDebug() << __FUNCTION__ << 4;
                                    }
                                    

                                    debug output:

                                    unixSignalHandler 0
                                    unixSignalHandler 1
                                    unixSignalHandler 0
                                    unixSignalHandler 1
                                    timerEvent QTime("18:43:29.352")
                                    qtSignalHandler 0
                                    qtSignalHandler 1
                                    qtSignalHandler 2
                                    qtSignalHandler 56
                                    qtSignalHandler 3
                                    qtSignalHandler 4
                                    unixSignalHandler 0
                                    unixSignalHandler 1
                                    unixSignalHandler 0
                                    unixSignalHandler 1
                                    unixSignalHandler 0
                                    unixSignalHandler 0
                                    unixSignalHandler 0
                                    unixSignalHandler 0
                                    unixSignalHandler 0
                                    

                                    From the debugging output, the possible problem is:

                                     :: write (mSocketFd [0],&a, sizeof (a));
                                    
                                    J Online
                                    J Online
                                    JonB
                                    wrote on 25 Mar 2023, 10:56 last edited by
                                    #17

                                    @tovax
                                    The fact that you show many unixSignalHandler 0 in a row with no alternating unixSignalHandler 1 in between (like it does to start out with) means that you keep re-entering unixSignalHandler(), writing a byte, and then not even completing the write() because you don't see the 1 output.

                                    I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the write() will complete and the Qt handler will read() after each write() before the next one. Which for whatever reason is not happening in your case.

                                    T 3 Replies Last reply 25 Mar 2023, 11:17
                                    0
                                    • J JonB
                                      25 Mar 2023, 10:56

                                      @tovax
                                      The fact that you show many unixSignalHandler 0 in a row with no alternating unixSignalHandler 1 in between (like it does to start out with) means that you keep re-entering unixSignalHandler(), writing a byte, and then not even completing the write() because you don't see the 1 output.

                                      I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the write() will complete and the Qt handler will read() after each write() before the next one. Which for whatever reason is not happening in your case.

                                      T Offline
                                      T Offline
                                      tovax
                                      wrote on 25 Mar 2023, 11:17 last edited by
                                      #18

                                      @JonB said in Unix signals and QCharts cause application blocking:

                                      @tovax
                                      The fact that you show many unixSignalHandler 0 in a row with no alternating unixSignalHandler 1 in between (like it does to start out with) means that you keep re-entering unixSignalHandler(), writing a byte, and then not even completing the write() because you don't see the 1 output.

                                      I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the write() will complete and the Qt handler will read() after each write() before the next one. Which for whatever reason is not happening in your case.

                                      Based on your analysis and debugging output, I added a mutex, but the result is the same. I cannot understand it.

                                      void PanelDriver::unixSignalHandler(int)
                                      {
                                          qDebug() << __FUNCTION__ << 0;
                                      
                                          QMutexLocker locker(&mMutex);
                                      
                                          char a = 1;
                                          ::write(mSocketFd[0], &a, sizeof(a));
                                          qDebug() << __FUNCTION__ << 1;
                                      }
                                      

                                      debug output:

                                      unixSignalHandler 0
                                      unixSignalHandler 1
                                      unixSignalHandler 0
                                      unixSignalHandler 1
                                      unixSignalHandler 0
                                      unixSignalHandler 1
                                      timerEvent QTime("19:13:56.243")
                                      qtSignalHandler 0
                                      qtSignalHandler 1
                                      qtSignalHandler 2
                                      qtSignalHandler 63
                                      qtSignalHandler 3
                                      qtSignalHandler 4
                                      unixSignalHandler 0
                                      unixSignalHandler 1
                                      unixSignalHandler 0
                                      unixSignalHandler 1
                                      unixSignalHandler 0
                                      unixSignalHandler 1
                                      unixSignalHandler 0
                                      unixSignalHandler 1
                                      unixSignalHandler 0
                                      unixSignalHandler 0
                                      unixSignalHandler 0
                                      unixSignalHandler 0
                                      unixSignalHandler 0
                                      
                                      1 Reply Last reply
                                      0
                                      • J JonB
                                        25 Mar 2023, 10:56

                                        @tovax
                                        The fact that you show many unixSignalHandler 0 in a row with no alternating unixSignalHandler 1 in between (like it does to start out with) means that you keep re-entering unixSignalHandler(), writing a byte, and then not even completing the write() because you don't see the 1 output.

                                        I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the write() will complete and the Qt handler will read() after each write() before the next one. Which for whatever reason is not happening in your case.

                                        T Offline
                                        T Offline
                                        tovax
                                        wrote on 25 Mar 2023, 11:22 last edited by
                                        #19

                                        @JonB said in Unix signals and QCharts cause application blocking:

                                        @tovax
                                        The fact that you show many unixSignalHandler 0 in a row with no alternating unixSignalHandler 1 in between (like it does to start out with) means that you keep re-entering unixSignalHandler(), writing a byte, and then not even completing the write() because you don't see the 1 output.

                                        I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the write() will complete and the Qt handler will read() after each write() before the next one. Which for whatever reason is not happening in your case.

                                        Using the enable flag has the same result.

                                        void PanelDriver::unixSignalHandler(int)
                                        {
                                            qDebug() << __FUNCTION__ << 0;
                                        
                                        #if 0
                                            QMutexLocker locker(&mMutex);
                                        #else
                                            static bool enable = true;
                                            if (!enable)
                                                return;
                                        #endif
                                        
                                            enable = false;
                                            char a = 1;
                                            ::write(mSocketFd[0], &a, sizeof(a));
                                            enable = true;
                                        
                                            qDebug() << __FUNCTION__ << 1;
                                        }
                                        
                                        1 Reply Last reply
                                        0
                                        • J JonB
                                          25 Mar 2023, 10:56

                                          @tovax
                                          The fact that you show many unixSignalHandler 0 in a row with no alternating unixSignalHandler 1 in between (like it does to start out with) means that you keep re-entering unixSignalHandler(), writing a byte, and then not even completing the write() because you don't see the 1 output.

                                          I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the write() will complete and the Qt handler will read() after each write() before the next one. Which for whatever reason is not happening in your case.

                                          T Offline
                                          T Offline
                                          tovax
                                          wrote on 25 Mar 2023, 11:32 last edited by
                                          #20

                                          @JonB said in Unix signals and QCharts cause application blocking:

                                          @tovax
                                          The fact that you show many unixSignalHandler 0 in a row with no alternating unixSignalHandler 1 in between (like it does to start out with) means that you keep re-entering unixSignalHandler(), writing a byte, and then not even completing the write() because you don't see the 1 output.

                                          I don't know why that is, and why you get so many signals in a row. It seems to me their sample code approach assumes the write() will complete and the Qt handler will read() after each write() before the next one. Which for whatever reason is not happening in your case.

                                          It is also a failure, and continuous output "unixSignalHandler 0" after freezing.

                                          void PanelDriver::unixSignalHandler(int)
                                          {
                                              qDebug() << __FUNCTION__ << 0;
                                          
                                          #if 0
                                              QMutexLocker locker(&mMutex);
                                          #else
                                              if (!enable)
                                                  return;
                                          #endif
                                          
                                              enable = false;
                                          
                                              char a = 1;
                                              ::write(mSocketFd[0], &a, sizeof(a));
                                          
                                              qDebug() << __FUNCTION__ << 1;
                                          }
                                          
                                          void PanelDriver::qtSignalHandler()
                                          {
                                              qDebug() << __FUNCTION__ << 0;
                                              mSocketNotifier->setEnabled(false);
                                              qDebug() << __FUNCTION__ << 1;
                                              char tmp;
                                              ::read(mSocketFd[1], &tmp, sizeof(tmp));
                                              qDebug() << __FUNCTION__ << 2;
                                          
                                              // do Qt stuff
                                              static int cnt = 0;
                                              qDebug() << __FUNCTION__ << cnt++;
                                              emit panelChanged();
                                              qDebug() << __FUNCTION__ << 3;
                                          
                                              mSocketNotifier->setEnabled(true);
                                              qDebug() << __FUNCTION__ << 4;
                                          
                                              enable = true;
                                          }
                                          
                                          1 Reply Last reply
                                          0

                                          5/29

                                          25 Mar 2023, 09:37

                                          topic:navigator.unread, 24
                                          • Login

                                          • Login or register to search.
                                          5 out of 29
                                          • First post
                                            5/29
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved