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