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. Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?

Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?

Scheduled Pinned Locked Moved Solved General and Desktop
networkhttpmacos
18 Posts 4 Posters 2.1k 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.
  • S Offline
    S Offline
    Sprezzatura
    wrote on 19 Oct 2020, 14:49 last edited by Sprezzatura
    #1

    I have a function that uses QNetworkAccessManager::post() to run a PHP script that writes some data on my server. The program runs on macOS 10.15.

    This function runs fine when invoked at the beginning of the program, and the data does get written on the server.

    However, when the function is called during QMainWindow::closeEvent(), the script is never run. The post() call returns QNetworkReply::NoError.

    Why is this happening? Is the application shut down at this stage, so it can't send HTTP requests? Is there an earlier point that I can intercept, when the program is shutting down?

    Here is a code snippet:

    QNetworkReply *reply;
    QString urlStr("https://foo.com/bar.php?some&data");
    QUrl url(urlStr);
    if(!url.isValid())
    {	QString urlError = url.errorString();
    	qDebug() << "\n" << urlError << "\n";
    }
    QNetworkRequest *request = new QNetworkRequest(url);
    request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
    QByteArray content = urlStr;
    
    QNetworkAccessManager *nam = new QNetworkAccessManager;
    if(request != NULL && nam != NULL )
    {	reply = nam->post(*request, content);
    	QNetworkReply::NetworkError netret = reply->error();   // QNetworkReply::NoError
    }
    
    P 1 Reply Last reply 19 Oct 2020, 15:02
    0
    • S Sprezzatura
      19 Oct 2020, 14:49

      I have a function that uses QNetworkAccessManager::post() to run a PHP script that writes some data on my server. The program runs on macOS 10.15.

      This function runs fine when invoked at the beginning of the program, and the data does get written on the server.

      However, when the function is called during QMainWindow::closeEvent(), the script is never run. The post() call returns QNetworkReply::NoError.

      Why is this happening? Is the application shut down at this stage, so it can't send HTTP requests? Is there an earlier point that I can intercept, when the program is shutting down?

      Here is a code snippet:

      QNetworkReply *reply;
      QString urlStr("https://foo.com/bar.php?some&data");
      QUrl url(urlStr);
      if(!url.isValid())
      {	QString urlError = url.errorString();
      	qDebug() << "\n" << urlError << "\n";
      }
      QNetworkRequest *request = new QNetworkRequest(url);
      request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
      QByteArray content = urlStr;
      
      QNetworkAccessManager *nam = new QNetworkAccessManager;
      if(request != NULL && nam != NULL )
      {	reply = nam->post(*request, content);
      	QNetworkReply::NetworkError netret = reply->error();   // QNetworkReply::NoError
      }
      
      P Online
      P Online
      Pl45m4
      wrote on 19 Oct 2020, 15:02 last edited by Pl45m4
      #2

      @Sprezzatura

      You can re-implement the closeEvent, wait until your post task is finished and then continue to close your app by accepting the event, if this was your question ;)

      The code you are showing above, is this in your closeEvent or just a random function? You can't expect to get a proper result, when closing your app while your NetMan is still doing some stuff


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

      ~E. W. Dijkstra

      1 Reply Last reply
      0
      • S Offline
        S Offline
        Sprezzatura
        wrote on 19 Oct 2020, 15:17 last edited by Sprezzatura
        #3

        I think that is what we're doing. The function above is named 'xmitStats' and is called from our closeEvent() handler:

        void MainWindow::closeEvent(QCloseEvent *event)
        {
        	// end of session - transmit stats
        	xmitStats();
        	event->accept();
        	QMainWindow::closeEvent(event);
        }
        

        Is this OK? I wonder why is it not working?

        P 1 Reply Last reply 19 Oct 2020, 15:44
        0
        • S Sprezzatura
          19 Oct 2020, 15:17

          I think that is what we're doing. The function above is named 'xmitStats' and is called from our closeEvent() handler:

          void MainWindow::closeEvent(QCloseEvent *event)
          {
          	// end of session - transmit stats
          	xmitStats();
          	event->accept();
          	QMainWindow::closeEvent(event);
          }
          

          Is this OK? I wonder why is it not working?

          P Online
          P Online
          Pl45m4
          wrote on 19 Oct 2020, 15:44 last edited by Pl45m4
          #4

          @Sprezzatura

          This doesn't ensure that NetMan is finished before you accept the event. Use QNetworkAccessManager::finished signal and then continue with your closeEvent.
          You could use a lambda for that purpose.
          Something like

          connect(netMan, &QNetworkAccessManager::finished, [=](QNetworkReply *)
          {
          // Check for reply error or do some other stuff here
          
          }
          
          

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

          ~E. W. Dijkstra

          1 Reply Last reply
          2
          • S Offline
            S Offline
            Sprezzatura
            wrote on 19 Oct 2020, 21:45 last edited by
            #5

            I'm sorry for being slow, but I'm new at Qt.

            I am not versed in Lambdas, so this is what I tried:

            bool bDoneStats = false;
            void doneStats(QNetworkReply *reply)
            {
            	bDoneStats = true;          // never gets here
            	qDebug()<<"doneStats\n";
            }
            
            void MainWindow::closeEvent(QCloseEvent *event)
            {
            	QNetworkReply *reply;
                    QString urlStr("https://foo.com/bar.php?some&data");
            	QUrl url(urlStr);
            	if(!url.isValid())
            	{	QString urlError = url.errorString();
            		qDebug() << "\n" << urlError << "\n";
            	}
            	QNetworkRequest *request = new QNetworkRequest(url);
            	request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
            	QByteArray content = urlStr;
            
            	QNetworkAccessManager *nam = new QNetworkAccessManager;
            	if(request != NULL && nam != NULL )
            	{	reply = nam->post(*request, content);
                           // also tried "SIGNAL(finished(QNetworkReply*))"
            		connect(nam, SIGNAL(nam->finished(QNetworkReply*)), this, SLOT(doneStats(QNetworkReply*)));
            		QNetworkReply::NetworkError netret = reply->error();
            		qDebug() << "\nSuccess " << url << " NetworkError " << netret << "\n";
            	}
            
            	do
            	{} while (!bDoneStats);     // never breaks loop
            
            	event->accept();
            	QMainWindow::closeEvent(event);
            }
            

            It never reaches "doneStats", and goes into an endless loop. If I remove the do/while, it exits the function but nothing is written at the server.

            What am I missing? I really appreciate your help.

            P J 2 Replies Last reply 19 Oct 2020, 23:36
            0
            • S Sprezzatura
              19 Oct 2020, 21:45

              I'm sorry for being slow, but I'm new at Qt.

              I am not versed in Lambdas, so this is what I tried:

              bool bDoneStats = false;
              void doneStats(QNetworkReply *reply)
              {
              	bDoneStats = true;          // never gets here
              	qDebug()<<"doneStats\n";
              }
              
              void MainWindow::closeEvent(QCloseEvent *event)
              {
              	QNetworkReply *reply;
                      QString urlStr("https://foo.com/bar.php?some&data");
              	QUrl url(urlStr);
              	if(!url.isValid())
              	{	QString urlError = url.errorString();
              		qDebug() << "\n" << urlError << "\n";
              	}
              	QNetworkRequest *request = new QNetworkRequest(url);
              	request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
              	QByteArray content = urlStr;
              
              	QNetworkAccessManager *nam = new QNetworkAccessManager;
              	if(request != NULL && nam != NULL )
              	{	reply = nam->post(*request, content);
                             // also tried "SIGNAL(finished(QNetworkReply*))"
              		connect(nam, SIGNAL(nam->finished(QNetworkReply*)), this, SLOT(doneStats(QNetworkReply*)));
              		QNetworkReply::NetworkError netret = reply->error();
              		qDebug() << "\nSuccess " << url << " NetworkError " << netret << "\n";
              	}
              
              	do
              	{} while (!bDoneStats);     // never breaks loop
              
              	event->accept();
              	QMainWindow::closeEvent(event);
              }
              

              It never reaches "doneStats", and goes into an endless loop. If I remove the do/while, it exits the function but nothing is written at the server.

              What am I missing? I really appreciate your help.

              P Online
              P Online
              Pl45m4
              wrote on 19 Oct 2020, 23:36 last edited by
              #6

              @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

              connect(nam, SIGNAL(nam->finished(QNetworkReply*)), this, SLOT(doneStats(QNetworkReply*)));

              This looks wrong (signal part).
              connect(nam, SIGNAL(finished(QNetworkReply*)), this SLOT(doneStats(QNetworkReply*)));

              Or, since you are using Qt5 (I hope so):

              connect(nam, &QNetworkAccessManager::finished, this, &MainWindow::doneStats);


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

              ~E. W. Dijkstra

              1 Reply Last reply
              1
              • S Sprezzatura
                19 Oct 2020, 21:45

                I'm sorry for being slow, but I'm new at Qt.

                I am not versed in Lambdas, so this is what I tried:

                bool bDoneStats = false;
                void doneStats(QNetworkReply *reply)
                {
                	bDoneStats = true;          // never gets here
                	qDebug()<<"doneStats\n";
                }
                
                void MainWindow::closeEvent(QCloseEvent *event)
                {
                	QNetworkReply *reply;
                        QString urlStr("https://foo.com/bar.php?some&data");
                	QUrl url(urlStr);
                	if(!url.isValid())
                	{	QString urlError = url.errorString();
                		qDebug() << "\n" << urlError << "\n";
                	}
                	QNetworkRequest *request = new QNetworkRequest(url);
                	request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
                	QByteArray content = urlStr;
                
                	QNetworkAccessManager *nam = new QNetworkAccessManager;
                	if(request != NULL && nam != NULL )
                	{	reply = nam->post(*request, content);
                               // also tried "SIGNAL(finished(QNetworkReply*))"
                		connect(nam, SIGNAL(nam->finished(QNetworkReply*)), this, SLOT(doneStats(QNetworkReply*)));
                		QNetworkReply::NetworkError netret = reply->error();
                		qDebug() << "\nSuccess " << url << " NetworkError " << netret << "\n";
                	}
                
                	do
                	{} while (!bDoneStats);     // never breaks loop
                
                	event->accept();
                	QMainWindow::closeEvent(event);
                }
                

                It never reaches "doneStats", and goes into an endless loop. If I remove the do/while, it exits the function but nothing is written at the server.

                What am I missing? I really appreciate your help.

                J Offline
                J Offline
                JonB
                wrote on 20 Oct 2020, 08:23 last edited by
                #7

                @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

                do
                {} while (!bDoneStats);     // never breaks loop
                

                When you get your code compiling (as per @Pl45m4's comment), what is this code about?? You won't want any such tight loop....

                S 2 Replies Last reply 20 Oct 2020, 13:53
                0
                • S Offline
                  S Offline
                  Sprezzatura
                  wrote on 20 Oct 2020, 13:49 last edited by Sprezzatura
                  #8

                  This is the revised code. It still does not call 'doneStats', and does not write to the server.

                  I am using Qt 5.12, because I need to be compatible with older versions of macOS.

                  void MainWindow::doneStats(QNetworkReply *reply)
                  {
                  	bDoneStats = true;		// member of MainWindow
                  	qDebug()<<"doneStats\n";
                  }
                  
                  void MainWindow::closeEvent(QCloseEvent *event)
                  {
                  	bDoneStats = false;
                  	QNetworkReply *reply;
                  	const char *urlStr("https://foo.com/bar.php?some&data");
                  	QUrl url(urlStr);
                  	if(!url.isValid())
                  	{	QString urlError = url.errorString();
                  		qDebug() << "\n" << urlError << "\n";
                  	}
                  	QNetworkRequest *request = new QNetworkRequest(url);
                  	request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
                  	QByteArray content(urlStr);
                  
                  	QNetworkAccessManager *nam = new QNetworkAccessManager;
                  	if(request != NULL && nam != NULL )
                  	{	reply = nam->post(*request, content);
                  		connect(nam, &QNetworkAccessManager::finished, this, &MainWindow::doneStats);
                  		QNetworkReply::NetworkError netret = reply->error();	// QNetworkReply::NoError
                  		qDebug() << "\nSuccess " << url << " NetworkError " << netret << "\n";
                  	}
                  
                  	event->accept();
                  	QMainWindow::closeEvent(event);
                  }
                  
                  1 Reply Last reply
                  0
                  • J JonB
                    20 Oct 2020, 08:23

                    @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

                    do
                    {} while (!bDoneStats);     // never breaks loop
                    

                    When you get your code compiling (as per @Pl45m4's comment), what is this code about?? You won't want any such tight loop....

                    S Offline
                    S Offline
                    Sprezzatura
                    wrote on 20 Oct 2020, 13:53 last edited by
                    #9
                    This post is deleted!
                    1 Reply Last reply
                    0
                    • J JonB
                      20 Oct 2020, 08:23

                      @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

                      do
                      {} while (!bDoneStats);     // never breaks loop
                      

                      When you get your code compiling (as per @Pl45m4's comment), what is this code about?? You won't want any such tight loop....

                      S Offline
                      S Offline
                      Sprezzatura
                      wrote on 20 Oct 2020, 13:54 last edited by
                      #10

                      @JonB said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

                      @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

                      do
                      {} while (!bDoneStats);     // never breaks loop
                      

                      When you get your code compiling (as per @Pl45m4's comment), what is this code about?? You won't want any such tight loop....

                      I am expecting 'bDoneStats' to be set to true by the callback or SLOT function, thus breaking the loop.

                      J 1 Reply Last reply 20 Oct 2020, 17:38
                      0
                      • S Offline
                        S Offline
                        Sprezzatura
                        wrote on 20 Oct 2020, 15:02 last edited by Sprezzatura
                        #11

                        @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

                        I just realized I called 'connect' after the post, I will change the order and try again.

                        1 Reply Last reply
                        0
                        • S Sprezzatura
                          20 Oct 2020, 13:54

                          @JonB said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

                          @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

                          do
                          {} while (!bDoneStats);     // never breaks loop
                          

                          When you get your code compiling (as per @Pl45m4's comment), what is this code about?? You won't want any such tight loop....

                          I am expecting 'bDoneStats' to be set to true by the callback or SLOT function, thus breaking the loop.

                          J Offline
                          J Offline
                          JonB
                          wrote on 20 Oct 2020, 17:38 last edited by JonB
                          #12

                          @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

                          I am expecting 'bDoneStats' to be set to true by the callback or SLOT function, thus breaking the loop.

                          This absolutely will not happen. Rather, your program will use up CPU time forever here, contributing to the entropy of The Universe :)

                          There are no multiple threads threads here. No signals or slots will fire while your loop executes. You will need a "wait for" event loop here instead, because you don't want to accept the original close event until this has completed. Look at QEventLoop::exec(). I don't know if there are consequences of calling this while inside MainWindow::closeEvent().

                          1 Reply Last reply
                          0
                          • S Offline
                            S Offline
                            Sprezzatura
                            wrote on 20 Oct 2020, 18:28 last edited by
                            #13

                            I've removed the do/while loop, I have re-ordered these statements:

                              connect(nam, &QNetworkAccessManager::finished, this, &MainWindow::doneStats);
                              reply = nam->post(*request, content);
                            

                            This is part of an application that otherwise runs fine. 'exec' is called in another part of the program (main.cpp).

                            The code works if invoked at the beginning of the program. It only seems to fail when it is called at the end of a session.

                            What do I need to do to get it to work?

                            J 1 Reply Last reply 20 Oct 2020, 18:38
                            0
                            • S Offline
                              S Offline
                              SGaist
                              Lifetime Qt Champion
                              wrote on 20 Oct 2020, 18:35 last edited by
                              #14

                              Hi,

                              One way is to use a local QEventLoop to wait for the request to complete. However, does it really make sense to do it there ? It sounds rather like something that should be done in the main method at application end.

                              In any case, there's no need to allocate QNetworkRequest on the heap.

                              Interested in AI ? www.idiap.ch
                              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                              S 1 Reply Last reply 20 Oct 2020, 19:26
                              1
                              • S Sprezzatura
                                20 Oct 2020, 18:28

                                I've removed the do/while loop, I have re-ordered these statements:

                                  connect(nam, &QNetworkAccessManager::finished, this, &MainWindow::doneStats);
                                  reply = nam->post(*request, content);
                                

                                This is part of an application that otherwise runs fine. 'exec' is called in another part of the program (main.cpp).

                                The code works if invoked at the beginning of the program. It only seems to fail when it is called at the end of a session.

                                What do I need to do to get it to work?

                                J Offline
                                J Offline
                                JonB
                                wrote on 20 Oct 2020, 18:38 last edited by JonB
                                #15

                                @Sprezzatura said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

                                'exec' is called in another part of the program (main.cpp).

                                I was talking about you putting an event loop here in your code:

                                QEventLoop loop;
                                loop.exec();
                                

                                That's how you have to do a "wait for", when you really need to, in Qt stuff.

                                1 Reply Last reply
                                0
                                • S SGaist
                                  20 Oct 2020, 18:35

                                  Hi,

                                  One way is to use a local QEventLoop to wait for the request to complete. However, does it really make sense to do it there ? It sounds rather like something that should be done in the main method at application end.

                                  In any case, there's no need to allocate QNetworkRequest on the heap.

                                  S Offline
                                  S Offline
                                  Sprezzatura
                                  wrote on 20 Oct 2020, 19:26 last edited by
                                  #16

                                  @SGaist said in Does QNetworkAccessManager::post() work in QMainWindow::closeEvent()?:

                                  Hi,

                                  One way is to use a local QEventLoop to wait for the request to complete. However, does it really make sense to do it there ? It sounds rather like something that should be done in the main method at application end.

                                  YES! That's one of the solutions I tried to do, but couldn't figure out where to do it. Where, in the code, can I intercept an application 'quit', prior to closeEvent?

                                  1 Reply Last reply
                                  0
                                  • S Offline
                                    S Offline
                                    Sprezzatura
                                    wrote on 20 Oct 2020, 19:50 last edited by Sprezzatura
                                    #17

                                    OK, here is the final, working solution. I am new to Qt and am not familiar with QEventLoop. I needed to see how the whole thing fitted together in order to understand.

                                    void MainWindow::closeEvent(QCloseEvent *event)
                                    {
                                    	QNetworkReply *reply;
                                    	QUrl url("https://foo.com/bar.php?some&data");
                                    	if(!url.isValid())
                                    	{	QString urlError = url.errorString();
                                    		qDebug() << "\n" << urlError << "\n";
                                    	}
                                    	QNetworkRequest *request = new QNetworkRequest(url);
                                    	request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
                                    	QByteArray content = "https://foo.com/bar.php?some&data";
                                    	QNetworkAccessManager *nam = new QNetworkAccessManager;
                                    
                                    	if(request != NULL && nam != NULL )
                                    	{	QEventLoop loop;
                                    		// https://www.codeproject.com/Questions/1196636/Qnetworkaccesmanager-doesn-t-emit-finished-signal
                                    		connect (nam, SIGNAL(finished(QNetworkReply*)), &loop, SLOT(quit()), Qt::DirectConnection);
                                    		reply = nam->post(*request, content);
                                    		loop.exec();
                                    
                                    		QNetworkReply::NetworkError netret = reply->error();
                                    		qDebug() << "\nSuccess " << url << " NetworkError " << netret << "\n";
                                    		QList<QByteArray> headers = reply->rawHeaderList();
                                    		QList<QByteArray>::iterator hit;
                                    		for(hit = headers.begin(); hit != headers.end(); hit++)	// is empty if failed
                                    			qDebug() << *hit << reply->rawHeader(*hit);
                                    	}
                                    
                                    	event->accept();
                                    
                                    	QMainWindow::closeEvent(event);
                                    }
                                    

                                    Thank you profusely @Pl45m4, @JonB and @SGaist .

                                    J 1 Reply Last reply 20 Oct 2020, 20:44
                                    0
                                    • S Sprezzatura
                                      20 Oct 2020, 19:50

                                      OK, here is the final, working solution. I am new to Qt and am not familiar with QEventLoop. I needed to see how the whole thing fitted together in order to understand.

                                      void MainWindow::closeEvent(QCloseEvent *event)
                                      {
                                      	QNetworkReply *reply;
                                      	QUrl url("https://foo.com/bar.php?some&data");
                                      	if(!url.isValid())
                                      	{	QString urlError = url.errorString();
                                      		qDebug() << "\n" << urlError << "\n";
                                      	}
                                      	QNetworkRequest *request = new QNetworkRequest(url);
                                      	request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
                                      	QByteArray content = "https://foo.com/bar.php?some&data";
                                      	QNetworkAccessManager *nam = new QNetworkAccessManager;
                                      
                                      	if(request != NULL && nam != NULL )
                                      	{	QEventLoop loop;
                                      		// https://www.codeproject.com/Questions/1196636/Qnetworkaccesmanager-doesn-t-emit-finished-signal
                                      		connect (nam, SIGNAL(finished(QNetworkReply*)), &loop, SLOT(quit()), Qt::DirectConnection);
                                      		reply = nam->post(*request, content);
                                      		loop.exec();
                                      
                                      		QNetworkReply::NetworkError netret = reply->error();
                                      		qDebug() << "\nSuccess " << url << " NetworkError " << netret << "\n";
                                      		QList<QByteArray> headers = reply->rawHeaderList();
                                      		QList<QByteArray>::iterator hit;
                                      		for(hit = headers.begin(); hit != headers.end(); hit++)	// is empty if failed
                                      			qDebug() << *hit << reply->rawHeader(*hit);
                                      	}
                                      
                                      	event->accept();
                                      
                                      	QMainWindow::closeEvent(event);
                                      }
                                      

                                      Thank you profusely @Pl45m4, @JonB and @SGaist .

                                      J Offline
                                      J Offline
                                      JonB
                                      wrote on 20 Oct 2020, 20:44 last edited by
                                      #18

                                      @Sprezzatura
                                      I think this looks better :)

                                      Your code as it stands presumably leaks QNetworkRequest *request = new QNetworkRequest(url); and QNetworkAccessManager *nam = new QNetworkAccessManager;. You could put these on the stack (no pointers, no new). And I think you're supposed to deleteLater() the QNetworkReply *reply = nam->post(*request, content);.

                                      You can get away without, but one day when you want examine your code for memory leaks with e.g. valgrind it will be better.

                                      1 Reply Last reply
                                      1

                                      10/18

                                      20 Oct 2020, 13:54

                                      • Login

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