I'm beginner learning Qt, and trying to understand a Qt provided example for download operation. In downloadmanager.cpp, a member function is the following:
void DownloadManager::append(const QUrl &url)
{
if (downloadQueue.isEmpty())
QTimer::singleShot(0, this, SLOT(startNextDownload()));
downloadQueue.enqueue(url);
++totalCount;
}
downloadQueue
is empty, it will need to activate the startNextDownload()
before adding the url. (note that: startNextDownload()
ends the program if the downloadQueue
is empty)QTimer::singleShot(x, y, z)
has been used at all. As I understand it to be, a timer that activates the slot with delay of 0 millisecond.I'm a beginner and in examples like:
statement1;
statement2;
I'm used to seeing statement1
running and finishing before moving on to working on statement2
. But trying to learn Qt and reading the given example, I see the SLOT(startNextDownload())
being activated after downloadQueue.enqueue(url);
has taken place. I am trying to understand why does this work.
Every call to QTimer::singleShot(...)
is executed on the event loop of the thread where it is invoked **. If invoked from the main thread, it'll be the event loop started with app.exec()
.
According to the Qt-Network-Manager-Example, this function is called after the network-manager is filled with the URL's so the single-shot will be processed after the queue has been completely filled. Poorly the qt documentation isn't that clear about this topic yet, so for more information about event processing etc please look here.
Before I start, the timer is for having the download in an extra thread. So the GUI keeps responsive.
The complete downloadNext()
method is recursive. It will be only called once and called till the queue is empty.
See this:
void DownloadManager::append(const QStringList &urlList)
{
foreach (QString url, urlList)
append(QUrl::fromEncoded(url.toLocal8Bit())); //Call for only one URL
...
}
void DownloadManager::append(const QUrl &url)
{
if (downloadQueue.isEmpty())
//I'm only called if the queue is empty! And I will be called after the next line. Not instantly!
QTimer::singleShot(0, this, SLOT(startNextDownload()));
downloadQueue.enqueue(url);
++totalCount;
}
After the queue is empty each method returns and at least the message that the download is done will be printed.
So why does this work? Please see first chapter below.