Homerun sources and Plasma runners

Aaron J. Seigo aseigo at kde.org
Sat Nov 17 11:56:13 UTC 2012


On Friday, November 16, 2012 17:04:04 Aurélien Gâteau wrote:
> A preliminary subject is API compatibility: I don't think it is possible
> to extend the current AbstractRunner interface in a BC way to meet our
> needs. Would you be ready to create a new runner interface?
> 
> This would require:
> - Defining and implementing this new interface (let's call it
>    AbstractRunner2 for now)
> - Implementing an adapter to load old AbstractRunner-based runners
> - Porting KRunner to use AbstractRunner2 and the adapter
> - Progressively porting runners shipped in KDE SC to AbstractRunner2

this should be unnecessary. first, we can look at what API is missing or needs 
adjusting. 

assuming changes are needed, we can prototype this in homerun (and so homerun 
can benefit from the improvements sooner) with an AbstratRunner subclass there 
which runners built for homerun can utilize. this API would then go directly 
into libplasma2 and Plasma Desktop 2 would include a krunner that uses this 
new API. 

> Sources features missing in Runners:
> - model-based => more QML friendly

as with Marco, i don't see any real need to have this in the libplasma API, 
but if we do want this in the libplasma API, we don't need to expose it from 
AbstractRunner .. 

RunnerManager could provide access to a model. in libplasma2 it could even 
become a model itself. right now, the runner model in kde-runtime is 
essentially exactly that -> it provides access to setting the query (just 
forwards that call to its internal RunnerManager), etc. so RunnerManager could 
simply become a model libplasma2 .. and in libplasma1 we can continue to use 
the model-on-top-of-RunnerManager.

so .. question is how best to implement that kind of model and that brings us 
to the next point:

> - can update matches

matches have id()s which can be used to reference them. what would be needed 
is for RunnerContext (which colates the matches from all the runners via 
addMatches) to check the id of matches and replace them.

implementation detail: this could be done using a hash to keep lookup fast. 
since id's are not guaranteed to be unique, this would need to be a multihash, 
or possibly a hash of lists.

then there are two possibilities: 

a) RunnerContext gets a new updateMatches(const QList<QueryMatch> &matches) 
method which would add the matches and update matches with the same id. 
(implementation: it could actually just remove the old match(es) and add the 
new ones; as long as there is a model tracking the row<->match correlation 
properly, these updates could be communicated via dataChanged signals)

b) RunnerContext::addMatches treats all calls as updates, so if a runner calls 
addMatches more than once and there are matches with the same id's, they'd get 
replaced. this could be problematic, however, as it would create a change in 
behaviour for runners that call addMatches multiple times in their match 
method and don't call setData or setId on the matches explicitly. for this 
reason, i prefer (a)

note that both changes above are source and binary compatible!

> - "standardized" favoriteIds

because it uses strings and relies on parsing of them, i really dislike this 
mechanism. it's too easy to get wrong (e.g. a runner that by chance uses one 
of the prefix strings in a match id) and makes it unecessarily difficult to 
change in future.

RunnerContext has this enum in it:

        enum Type {
            None = 0,
            UnknownType = 1,
            Directory = 2,
            File = 4,
            NetworkLocation = 8,
            Executable = 16,
            ShellCommand = 32,
            Help = 64,
            FileSystem = Directory | File | Executable | ShellCommand
        };

this could be used in QueryMatch as well .. and then knowing what kind of 
favourite it creates is a simple matter of checking this attribute. there is 
already a type property in QueryMatch used with the QueryMatch::Type enum.
so perhaps:

	void QueryMatch::setCategory(RunnerContext::Type category)
	RunnerContext::Type QueryMatch::category() const

this means one more int stored for each QueryMatch and using RunnerContext's 
header in QueryMatch (though in practice this is a complete non-issue since 
almost everything that touches a QueryMatch also uses RunnerContext's API and 
they are linked functionality-wise)

> - browsing support (as in: entering/leaving folders, application
>    groups...) by invoking the source with named arguments

this is already possible -> simply run the result of QueryMatch as a new 
query. this is close to how InformationalMatches are treated already, in fact.

so a runner that wants to list some directory structure could return a list of 
matches, some of which represents folders which when selected would be used as 
the new query. this would not work for viewing entire trees at once, unless a 
different RunnerContext was used for each new "sub-"query of the runner. 
however, i don't think viewing trees is a valid requirement for runners, so 
this is imho a non-issue.

to make this easier and less hacky, a new value could be added to 
QueryMatch::Type; e.g. QueryMatch. then items that can be re-used to query the 
source runner can be marked with that type. voila.

> - future need: reorder items

can you describe the needs here more clearly? because i think this is already 
possible given that sorting is done by the visualization anyways.

> If we create an interface which uses a Qt model to expose its items,
> this issue will become much easier to solve: we could create a model
> which groups all runner output models as a tree, then KRunner could use
> a KDescendantsProxyModel [1] on top of it to recreate a flat model, or
> just display all elements of the tree unindented.

accessing tree models in QML sucks. as in "unless you work around the 
limitations of QML, you can't." i really still do not understand the need for 
a tree at all.

if the requirement is to have a model per set of results (e.g. one model for 
each runner's matches) that can be accomplished with a filter model on top of 
the base model.

> This assumes we can make QML do what we want with that tree model, which
> may not be possible. 

bingo.

> In that case we can always fallback to what
> Homerun::RunnerModel does: a "flat" model with one row per runner, each
> runner row exposing a "model" role 

yes, that can work easily enough .. 

something that is not covered here which would actually be very useful is 
results paging. so a runner would return at most N results (so for a set of M 
runners, the maximum number of returned matches would be N*M) but then could 
be requested to get anothe rset of N results.

this would be very, very handy for runners that can return large datasets, 
such as music player listings, nepomuk searches, etc.

that is something that is probably easiest to add directly to libplasma2 and 
should not be targetted for libplasma1 in any way.

-- 
Aaron J. Seigo
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: <http://mail.kde.org/pipermail/plasma-devel/attachments/20121117/8f9f349e/attachment-0001.sig>


More information about the Plasma-devel mailing list