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