Homerun sources and Plasma runners

Aurélien Gâteau agateau at kde.org
Mon Nov 26 16:38:04 UTC 2012


Le jeudi 22 novembre 2012 13:29:06 Aaron J. Seigo a écrit :

> > Homerun AbstractSource class is not a model. It inherits from QObject and
> > provide virtual methods to create models. A source must implement at
> > least:
> > "QAbstractItemModel *createModelFromConfigGroup(const KConfigGroup
> > &group)"
> > and optionally:
> > "QAbstractItemModel *createModelFromArguments(const QVariantMap &args)"
> 
> yes, AbstractSource is essentially a factory. the API is very questionable
> imho, however.
> 
> what are the args?
args are documented in homerunmodel.dox. They are used when a source model 
wants Homerun to show a model from another source, through the 
openSourceRequested signal.

> the config group?

Config group is managed by Homerun: there is one config group per source model. 
When homerun starts up, it calls createModel on the source with the 
appropriate config group.

> when are they written? restored?

They are written by SourceConfigurationWidget::save. They are restored when 
Homerun starts up or when it recreates the model after the user edited the 
source configuration.

> what
> standards are there for this? it's all very add-hoc.

Not sure what you mean here. The config group is the source private area: it 
can store whatever configuration it wants to store there. For example the Dir 
source stores the url of the dir to show and what title to use.

> 
> who owns the model pointers? can i have more than one model? can i share the
> models creatd for the same args?

That part is indeed not documented. If the returned model is parentless, 
Homerun takes ownership of it. If it already has a parent, Homerun does not 
takes ownership of it, making it possible for sources to reuse models. This is 
used for the FavoriteApps and FavoritePlaces sources.

> it's not the sort of API i'd like to see re-used due to this.

I think all those issues can be addressed with better documentation. You may 
want to read the documentation from homerunmodel.dox, which hopefully gives a 
more higher view of the topic. But of course it is a bit difficult for me to 
tell if the doc is clear enough.

> however, the API that is there works and is maintainable. what it needs is
> some additions, such as the ability to update matches and perhaps some match
> caching.
> 
> > Trying to map the way sources work to runners, instead of having a runner
> > calling RunnerContext::addMatches(), a runner would have a createModel()
> > method which would be called by RunnerContext or RunnerManager to reach
> > the
> > runner data.
> 
> how would this be thread safe? or change on query updates?

Regarding thread safety, I believe multi-process is a safer solution.
A source model can expose a "query" property, which is then used to update 
itself without having to instantiate a new one.
 
> > This gives runners the ability to use whatever model class is more
> > appropriate: a model inheriting QAbstractListModel, or a simple
> > QStandardItemModel, or maybe a proxy model on top of an existing model
> > provided by a library, etc.
> 
> the time i can see this being of benefit is when proxying another model.
> otherwise, there's no benefit to be had as the results need to be uniform
> *anyways*.

Sorry, I don't understand what you mean with "results need to be uniform 
anyways".

> given how few runners proxy models, this seems to be a non-issue.

Homerun sources already use proxy models on top of kdelibs models for two 
sources (Dir and FavoritePlaces). I expect it to happen with other sources, as 
exposing data as models is more and more common. For example a source to 
display contacts or 10 last emails from Akonadi could use 
Akonadi::EntityTreeModel.

> > > > Considering prior art, Kickoff and Folder View are not built on top of
> > > > runners either (true, Kickoff uses runners to implement searching, but
> > > > not
> > > > for browsing), so I am not sure why runners would be appropriate for
> > > > Homerun but not for them?
> > > 
> > > you picked two of the oldest plasmoids which also happen to have the
> > > most
> > > complex internal implementations.
> > 
> > Well, I picked the ones which have similar features as Homerun, but fair
> > enough, history often gets in the way of the simplest solution.
> 
> the ones most similar to homerun are Search and Launch and Plasma Active's
> Contour. both of which use runners.

I haven't checked Plasma Active Contour, but Search and Launch does not use 
runners to list installed applications. It builds a model from 
KServiceGroup::root().

> > > homerun appears to present, predominantly, a set of query results. these
> > > could easily be done with runners.
> > > 
> > > the exception is when it goes to list full directory contents. and as
> > > i've
> > > stated elsewhere, imo this should be done with a KDirModel directly
> > > without
> > > any wrapper around it.
> > > 
> > > with some necessary additions to the runner functinality in libplasma, i
> > > don't see anything in homerun, other than directory listings, that could
> > > not be done as well with runners as it is now.
> > 
> > That would mean different APIs to provide content... I am not sure I want
> > to go in that direction.
> 
> if you want one set of roles from the model in homerun no matter what model
> is being used for the view, then one could:
> 
> * bridge KDirModel + runners as an internal implementation detail to
> homerun; runners remain as they are.
> 
> * put KDirModel behind an API and use that API also for all other listings.
> 
> obviously, homerun is doing the latter right now and it means that we end up
> with sources and runners. sources are not useful for something like
> krunner, so we live with a split.
>
> alternatively, homerun could simply handle directory listing models and
> runner models differently; we do similar things elsewhere with QML and it
> makes it very easy to do so, unlike in C++
> 
> Search and Launch and Active both show that using runners works for listing
> based UIs. while i can certainly imagine a more efficient / direct method
> for listing based UIs, the larger design goal of "having universal
> components for finding these things that works in both search and listing
> environments" trumps that.
> 
> it all depends on what you're optimizing for.
> 
> it appears you are optimizing an API for using kdirmodel with other things
> conforming to that type of model. i'm interested in an API that provides
> heterogeneous listings treated as a specialized case of search, where full
> directory listing is treated as a separate use case to be handled
> separately.

Homerun does not use KDirModel for everything: the only source which uses 
KDirModel is the Dir source. Other sources use different models. That is one of 
the point of Homerun sources: being able to use whatever model class is 
appropriate for the job.

> what makes this less clear is that some things clearly straddle the
> boundaries: bookmarks, for instance.

I don't understand what you mean here: it would be easy to build a Homerun 
source exposing bookmarks.

> other things already have models, so it is tempting to simply proxy them.

Indeed, that is what Homerun do.

> > > this makes very little sense. sources are models which are not written
> > > in
> > > a
> > > threadsafe manner to be used from runners which are built on a threaded
> > > model. behind the scenes they all access similar / the same convenience
> > > API.
> > 
> > I actually don't like the idea of trusting every runner code to be thread-
> > safe. This is all the more dangerous when Homerun is running as a
> > containment because in this case the Homerun process is the Plasma Desktop
> > process.
> 
> when was the last time we saw kickoff going down because of this? it's the
> same issue.
> 
> what would be even worse is having to wait for results in the GUI thread.
> right now, all runners get threading "for free"; they just have to ensure
> that their match() method is thread safe.
> 
> some runners/listers really need to do their work in another thread to
> prevent the UI from stopping for long periods of time. having just finished
> off fixing up some things in the new metadatamodel code, it is clear how
> non-trivial this is to get right.
> 
> which means most people won't even do so, or will do so poorly. and the
> results will be even *worse* -> non-threaded blocking code with horribly
> jittery UI, bugs in thread management code, etc.

Agreed. I don't want that. That is why I believe in running source models in 
other processes.
> 
> > I want to experiment with writing a proxy model which would run
> > its source model in a separate process. Don't know how well it is going to
> > perform, but I am going to give it a try. If it is good enough it would be
> > IMO a safer alternative to having heavily multi-threaded code.
> 
> so in the krunner case where we match during typing we'd spawn a set of
> processes for each keystroke?

No. A source model can update itself to react to query changes, the code would 
only have to place a dbus call with the new query value.
 
> and all the IPC would also be smooth? our experience is that such IPC really
> hinders the fluidity of the UI.

The Unity Dash is made of (too) many processes: scopes (==content sources) run 
in their own processes, lenses (==content filters) run in their own processes. 
Despite this architecture, it is reasonably smooth.

> > > search on sources is implemented apparently by filter models, which
> > > means
> > > having to load entire datasets into the model and then filter based on
> > > the
> > > data .. rather than querying first to pull just the data needed.
> > 
> > That is not correct. A basic source can indeed provide a model which
> > expose
> > all its data, Homerun will then provide a generic filter on top of it. But
> > a source can also provide a model with a "query" property, in which case
> > the model is responsible for implementing searching/filtering itself.
> 
> so models provide properties that differentiate their capability? making
> some searchable, some not, some done way, some another?

To the end users, all sources are filterable/searchable. When implementing a 
simple source with a few items, one can let Homerun provide a generic filter on 
them. If one wants to implement a more efficient filter, or if the source needs 
to actually do "real" searches as opposed to filtering a limited set of 
results, then one can expose the "query" property and implement 
searching/filtering in the source itself.

This is documented in homerunmodel.dox. I should probably push the Doxygen 
output of libhomerun somewhere.

Aurélien


More information about the Plasma-devel mailing list