[Kde-pim] Tomboy resource: Questions to the usage of KIO::KJob

Daniel Vrátil dvratil at kde.org
Sat Jun 18 23:57:08 BST 2016


On Saturday, June 18, 2016 11:44:37 PM CEST Stefan Staeglich wrote:
> Hello Dan,

Hi,

> 
> I have now implemented the classes like you suggested. But the Jobs don't
> seems to be started. What could be the problem?

First thing: you have to call job->start() manually to start the job. Sorry if 
I forgot to mention that - Akonadi jobs are started automatically, so I tend 
to forget you need to start pure KJobs manually :-)

Second thing, the idea of KJobs is that in your start() implementation you 
start an *async* operation, and then connect to a signal that notifies you 
when the async operation is finished, and you handle the result in a slot. 
Looking at your TomboyItemDownloadJob, you are doing things synchronously:

// This method won't return until response is retrieved and result parsed
void Tomboy....Job::start()
{
	...
	// Creates request
	 QNetworkRequest request(userURL + "/note/" + resultItem.remoteId());
	// Get pending reply
	 QNetworkReply *reply = requestor->get(request, requestParams);
	// reply->readAll() will block until all data are received
	QJsonDocument document = QJsonDocument::fromJson(reply->readAll(), 
Q_NULLPTR);
	...
	emitResult();
}


The right way to do this is

// This will start a network request and return immediately
void Tomboy.....Job::start()
{
	...
	// Create request
	QNetworkRequest request(.....);
	// Get pending reply
	mReply = requestor->get(....);
	// connect to reply's "finished" signal
	connect(mReply, &QNetworkReply::finished,
        	         this, &Tomboy....Job::onRequestFinished);
	// we are done here
}

// This will be called once the request is finished. You process the response
// and emitResult(), to which your code in the resource will react.
void Tomboy...Job::onRequestFinished()
{
	// TODO: check mReply->error()

	// Now you can "readAll()" without blocking, the data have already been 
	// downloaded asynchronously
	QJsonDocument document = QJsonDocument::fromJson(mReply->readAll()); 
Q_NULLPTR);
	...
	...
	// Tell the listeners that the job has finished
	emitResult();
}

Hope I explained it well, feel free to ask if something is unclear.

Dan


> 
> Thanks,
> Stefan
> 
> Am Freitag, 3. Juni 2016, 17:19:48 schrieb Daniel Vrátil:
> > On Friday, June 3, 2016 4:37:05 PM CEST Stefan Staeglich wrote:
> > > Hello,
> > 
> > Hi,
> > 
> > > I'm developing a Akonadi resource for Tomboy servers like Grauphel[1]. I
> > > understand the basic stuff now, but in detail it's still complicated.
> > > 
> > > Daniel Vrátil suggested to use the KIO::KJob stuff. I've  tried to study
> > > this, but at the moments it's very complex for me. For now I only want
> > > to
> > > implement the basic things. For this we have the necessary following
> > > actions: - Register at the server
> > > - Retrieve all items (I want to use only one collection)
> > > - Get a specific item (full item data!)
> > > - Add a new item
> > > - Delete a item
> > > - Modify a item
> > > 
> > > My idea was to use the following KJob-Classes:
> > > 
> > > - TomboyJobBase:
> > >   it should provide the full OAuth stuff using the library o2
> > > 
> > > - TomboyServerAuthenticateJob:
> > >   It's needed for the configuration it should do the OAuth registration
> > > 
> > > process getting the client credentials
> > > 
> > > - TomboyItemsDownloadJob:
> > >   It should retrieve all items
> > > 
> > > - TomboyItemDownloadJob:
> > >   It should get the specific item
> > > 
> > > - TomboyItemUploadJob
> > > 
> > >  It should can add, delete and modify a item
> > > 
> > > Eventually the class TomboyItemsDownloadJob needs additional classes for
> > > adding, deleting and modifying items in the Akonadi cache. But I'm not
> > > sure
> > > about this.
> > 
> > Interaction with the Akonadi cache should not happen in the Jobs, but in
> > your TomboyResource (Akonadi::ResourceBase subclass).
> > 
> > > So what do you think about this? What base class should I use? KJob
> > > directly?
> > 
> > You probably want to subclass KCompositeJob, because that allows you to
> > run
> > nested job (i.e. start new KJobs inside your KCompositeJob subclass).
> > 
> > > What features I should use from KJob? So that I can add necessary data,
> > > start the job and can get the result?
> > 
> > The main feature that KJob gives you is simplification of the code as it
> > does lots of work for you behind the scenes.  The only thing you need to
> > care about is to reimplement start(), which is called automatically by
> > KJob
> > when the job starts, and when you want the job to finish, you just call
> > emitResult(), which causes the KJob to emit result(KJob*) signal that you
> > listen to elsewhere. There's also setError() and setErrorText() to report
> > errors that occured in the job.
> > 
> > A supersimplified example of one of your jobs (without the OAuth
> > authentication, error handling etc.)
> > 
> > class TomboyItemsDownloadJob : public TomboyJobBase
> > {
> > public
> > 
> > 	// ctor
> > 	TomboyItemsDownloadJob(QObject *parent);
> > 	
> > 	 // returns the parsed results wrapped in Akonadi::Item, see bellow
> > 	
> > 	Akonadi::Item::List items() const;
> > 
> > protected:
> > 	// automatically called by KJob, here you start the HTTP request using
> > 	// KIO::get (or KIO::stored_get) (see [0]) and connect onResult() (see
> > 	// bellow) to its result() signal
> > 	void start() override;
> > 
> > private Q_SLOTS:
> > 	// called when the KJob your created above via KIO::get finishes.
> > 	// Read the data from the job, parse them, store the results and
> > 	// call emitResult(), which will....well, emit result() signal
> > 	void onResult(KJob *kjob);
> > 
> > };
> > 
> > 
> > The way you use the jobs in your Resource then would be
> > 
> > class TomboyResource : public Akonadi::ResourceBase
> > {
> > 
> > 	void retrieveItems(const Collection &c)
> > 	{
> > 	
> > 		// create the job
> > 		auto job = new TomboyItemsDownloadJob(c.id(), this);
> > 		// connect to its result() signal
> > 		connect(job, &KJob::result,
> > 		
> > 			        this, &TomboyResource::onDownloadFinished);
> > 	
> > 	}
> > 	
> > 	void onDownloadFinished(KJob *kjob)
> > 	{
> > 	
> > 		// get the job
> > 		auto job = qobject_cast<TomboyItemsDownloadJob*>(kjob);
> > 		// pass the items you retrieved to Akonadi
> > 		itemsRetrieved(job->items());
> > 	
> > 	}
> > 
> > }
> > 
> > Passing the Items to ResourceBase (via itemsRetrived, or
> > itemsRetrievedIncremental, if Tomboy has a way to perform incremental
> > sync)
> > is all you have to do, the ResourceBase will take care to store the
> > Akonadi::Items in the Akonadi cache.
> > 
> > I recommend that you take a look at Google Contacts resource [1], which
> > uses the Job pattern heavily, and at LibKGAPI [2], which implements the
> > jobs (LibKGAPI does not use KJob, but the thing is modelled very closely
> > after KJob, so you will get the idea. I will hopefully one day get off my
> > lazy butt and port it to KJob....).
> > 
> > Hope it helps,
> > 
> > Daniel
> > 
> > [0] https://api.kde.org/frameworks/kio/html/namespaceKIO.html
> > [1]
> > https://quickgit.kde.org/?p=kdepim-runtime.git&a=blob&f=resources%2Fgoogle
> > %2Fcontacts%2Fcontactsresource.cpp
> > [2] https://quickgit.kde.org/?p=libkgapi.git&a=tree&f=src%2Fcontacts
> > 
> > > Thanks,
> > > Stefan
> > > 
> > > [1] https://bugs.kde.org/show_bug.cgi?id=362938
> > > _______________________________________________
> > > KDE PIM mailing list kde-pim at kde.org
> > > https://mail.kde.org/mailman/listinfo/kde-pim
> > > KDE PIM home page at http://pim.kde.org/
> 
> _______________________________________________
> KDE PIM mailing list kde-pim at kde.org
> https://mail.kde.org/mailman/listinfo/kde-pim
> KDE PIM home page at http://pim.kde.org/


-- 
Daniel Vrátil
www.dvratil.cz | dvratil at kde.org
IRC: dvratil on Freenode (#kde, #kontact, #akonadi, #fedora-kde)

GPG Key: 0x4D69557AECB13683
Fingerprint: 0ABD FA55 A4E6 BEA9 9A83 EA97 4D69 557A ECB1 3683
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part.
URL: <http://mail.kde.org/pipermail/kde-pim/attachments/20160619/7ae60879/attachment.sig>
-------------- next part --------------
_______________________________________________
KDE PIM mailing list kde-pim at kde.org
https://mail.kde.org/mailman/listinfo/kde-pim
KDE PIM home page at http://pim.kde.org/


More information about the kde-pim mailing list