Project directory structure
Thiago Macieira
thiago at macieira.org
Wed Apr 3 14:01:36 PDT 2013
On quarta-feira, 3 de abril de 2013, às 13.26.07, you wrote:
> > // in the main window's constructor:
> > // range is [0..100]
> > progress_dialog = new QProgressDialog(_("Downloading..."),
> >
> > _("Stop download"), 0, 100, this);
> >
> > connect(progress_dialog, SIGNAL(canceled()), SLOT(cancel_download());
>
> Actually, there are many more texts… libdivecomputer (and our own Uemis
> downloader) tell the user which dives are currently being downloaded). So
> the texts are not known at compile time but created at run time.
Those two are the title of the dialog and the text of the cancellation button.
QProgressDialog can also show another label, which would be the name or number
of the dive. It would be handled by the update mechanism.
I assumed above that the progress would go from 0 to 100 (percent). Another
way of doing this is to go from 0 to the number of dives. In that case, the
constructor would set a dummy maximum. The real maximum would be set later.
We can make it more complex if we want to, if we need to wait for the thread
to tell us how many dives there are.
> >> And we use the global variables import_thread_cancelled,
> >> import_thread_done progress_bar_text and progress_bar_fraction to
> >> communicate from the download thread to the UI thread.
> >> The stupid timeout mechanism is working around Gtk's inability to do the
> >> updates from a separate thread (I understand the same is true for Qt).
> >
> > Indeed. But the code above neatly works around the issue by using signals
> > and slots. Qt will take care of crossing the thread barrier for you. All
> > slots associated with MainWindow or QProgressDialog will be executed in
> > the main (UI) thread automatically.
>
> So how does the download thread connect to the QProgressDialog to send it
> updates?
See the connect() calls in the code. I made it so that the DownloadJob class
has to define at least three signals:
void progress(int)
void updated_text(const QString &);
void finished();
We might need one more for download failure, or we could roll up in finished.
Some older Qt classes like QHttp have:
void done(bool success);
http://qt-project.org/doc/qt-4.8/qhttp.html#done
But the newer replacement (QNetworkReply) has only a finished() signal and you
have to query the object to know if it failed or not.
> > Even on Windows?
>
> Yep.
General recommendation is to use Win32 on Windows and avoid any POSIX
compatibility layer.
> > If the threading code is inside libdivecomputer, I'd leave it where it is.
> > If it's in Subsurface, I'd recommend wrapping it with that DownloadJob
> > class above. It would create a QThread and provide a few C callbacks for
> > the actual download (written in C). The callbacks would emit the signals
> > I listed.
> It's inside Subsurface. Look at the very end of libdivecomputer.c
Something like:
// these functions are static members
void DownloadJob::finished_callback(void *self)
{
emit static_cast<DownloadJob *>(self)->finished();
}
void DownloadJob::updated_text_callback(void *self)
{
DownloadJob *dj = static_cast<DownloadJob *>(self);
emit dj->updated_text(QString::fromUtf8(download_data->text));
}
(emit is a #defined to empty, it's just an artifice to improve legibility)
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 190 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.hohndel.org/pipermail/subsurface/attachments/20130403/ad6bd624/attachment.sig>
More information about the subsurface
mailing list