Lenses

Differences between revisions 19 and 28 (spanning 9 versions)
Revision 19 as of 2011-09-09 18:01:15
Size: 16020
Editor: 87-194-53-170
Comment:
Revision 28 as of 2013-11-25 15:37:55
Size: 48
Editor: dholbach
Comment:
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
## page was renamed from Unity/Places
[[Unity]] > [[Lenses]]

''''' This is referring to the 11.04 Lenses, the 11.10 documentation will be uploaded shortly '''''


= Unity Lenses Architecture =

/!\ Lenses used to be known as Places. When referring to code and APIs we still use the term Places, but the user-visible name is Lenses. The Places name will be retired in 11.10.

<<TableOfContents()>>

This page summarizes the Unity Lenses architecture as agreed by Neil and Mikkel.

== Glossary ==

To minimize the confusion we might want to explain what a lens actually is but instead let's all try and stick to the following glossary ([[attachment:unity-glossary.svg|.svg source]]):

{{attachment:unity-glossary.png}}

== Introduction ==

Neil has created a presentation/introduction for developers.

{{attachment:Unity_Places_Developer_Guide.pdf}}

Here are some [[Unity/Places/Ideas/|ideas]] we have for Unity places.

=== Plan for Natty ===

Lenses are something that we can put in extras.ubuntu.com since they're small and can be quick moving and we want people making lots of them. This gives us the rest of the development cycle and Natty's lifecycle for people to submit Places that people can run on their stable release without digging around for PPAs.

 * Quickly needs to be adapted for /opt-like things, after feature freeze: Didrocks

== Place Daemons ==

=== Lens Daemons from 1000 Feet ===
A lens daemon expose a list of place entries over DBus. Each entry holds enough data and metadata for Unity to render it. Each place entry has it's own icon in the places bar.

Each lens has a DBus API that exposes it's sections, groups, and core datamodel. It also defines which rendering mode Unity must use to render each group. Rendering modes includes can include fx. tiled, cover flow, and how many rows to show.

=== Registration ===
Places are registered in Unity by adding a special {{{.place}}}-file into {{{$prefix/share/unity/places}}}. The {{{.place}}} file is a keyfile that contains the following
{{{
[Place]
DBusName=Well known bus name the place can be found under
DBusObjectPath=DBus object path the place object lives at

[Entry:Stuff]
DBusObjectPath=DBus path for the place entry (must be a direct child of Places' DBusPath)
Icon=Icon for the place entry
Name=Display name for the entry
Description=Short description of what the entry provides. Suitable for display as tooltip or other
SearchHint=Message that will be displayed in the search box
ShowGlobal=true|false (defaults to true)
ShowEntry=true|false (defaults to true)
Shortcut=a


[Entry:OtherStuff]
...
}}}

The contents of the {{{.place}}}-file allows Unity to draw an icon in the places bar. The actual place daemon will be started lazily.

The {{{[Place]}}} group in the key file contains the basic info necessary for DBus-activating the place daemon.

Each {{{[Entry:*]}}} group contains the info necessary for Unity to render an icon in the places bar. Note that it can not be guaranteed this entry info is precise. When the daemon comes up some entries may be added or removed compared to this info.

/!\ Show`Global determines whether the Lens shows up in the user's Dash or not. Currently we don't have a method for allowing users to determine this, so we recommend that all Lens authors set this to false so as not to clutter a user's Dash with all the places they have installed. We'll sort this out in 11.10.

A place that requires {{{ShowEntry=False}}} is the Control Center place which is searchable from the home screen, but not otherwise displayed. The {{{Shortcut}}} key defines which keyboard key you must press together with {{{<super>}}} to open the place. In the example above the user must press {{{<super>-a}}} to activate the place. The {{{<super>}}} key to launch apps shortcut is defined in compiz itself.

=== Example Code ===
You can find a full working example of a place implementation in [[https://launchpad.net/unity-place-sample|launchpad.net/unity-place-sample]].

The full source code for the files- and applications places can be found on [[https://launchpad.net/unity-place-files|launchpad.net/unity-place-files]] and [[https://launchpad.net/unity-place-applications|launchpad.net/unity-place-applications]]. These are quite a lot more complex than the sample above, but exercises the full feature set described in this specification if you would like to see working examples.

== Renderers ==
Each group is rendered by some specific "renderer" inside the Unity shell. The renderer is defined with a !CamelCased namespaced type string, ala GLib GTypes, eg. {{{UnityDefaultRenderer}}}. If the renderer type is the empty string the group or entry should not be displayed.

Each place entry has a default renderer specified (in its {{{renderer_info.default_renderer}}} property). This may be overridden on a per-group basis by the groups model specified (in its {{{renderer_info.groups_model}}}).

Examples of renderers could include the default tiled rendering, coverflow, or a webkit-backed HTML renderer. At some point we will also make renderers a pluggable part of the Unity shell.

==== UnityDefaultRenderer ====
Renders rows in the results model using the {{{icon_hint}}} column with the {{{display_name}}} column underneath it. The icon should be a serialized GIcon (using {{{g_icon_to_string()}}}). Falls back to using the icon for the {{{mimetype}}} column if the {{{icon_hint}}} is not set. Renders one row of icons by default. FIXME: We need a way to set a hint for showing {{{N}}} rows or all rows.

==== UnityEmptySectionRenderer ====
Used to convey to the user that the current section is empty. The first row of the results model contains the message to the user in the {{{display_name}}} column. Any subsequent rows contain optional alternative actions the user may activate. These actions are URI encoded, so fx. a ''Try searching for 'pony' on Google''-alternative might be encoded with {{{http://www.google.com/#q=pony}}} in the {{{uri}}} column of the second row and the string {{{"Try searching for <i>pony</i> on Google"}}} in the {{{display_name}}} column.

==== UnityEmptySearchRenderer ====
Used exactly like {{{UnityEmptySectionRenderer}}} but informs the user that the current search did not match anything.

==== UnityShowcaseRenderer ====
Used for the {{{Most Used}}} category in the applications place. Has a slightly larger icon than the default renderer.

==== UnityFileInfoRenderer ====
Used in files place to show search results. Expects a valid URI, and will show extra information such as the parent folder and whatever data is in the comment column of the results.

== DBus API for Place Daemons ==

=== Data Structures ===

<<Anchor(RendererInfo)>>
==== RendererInfo ====
There are a few datastructures we pass over the wire. Firstly we have {{{RendererInfo}}} struct with signature {{{(sss{ss})}}}. We use {{{R}}} as shorthand for this struct:
{{{
  string default_renderer (name defining the default rendering mode for this place entry)
  string groups_model (DBus name of a Dee.Model)
  string results_model (DBus name of a Dee.Model)
  map<string,string> renderer_hints
}}}

 (!) If the entry wide renderer needs to be changed (fx. after the view calls {{{SetActiveSection()}}} to have a specialized "photo collection view" or something) the entry emits the {{{RendererInfoChanged}}} signal with the updated renderer info.

If {{{default_renderer}}} is the empty string then the contents of the entry should be ignored by the Unity shell. This way place entries can control whether they appear in the global search and/xor/nor in the places bar. This behaviour reflects the {{{ShowGlobal}}} and {{{ShowEntry}}} keys in the {{{Entry}}} group of the {{{.place}}} file.

<<Anchor(RendererInfoHints)>>
==== RendererInfo Hints ====
You can specify the following hints to a renderer:

 * {{{ExpandedGroups}}} - a space separated list of integer values specifying a set of group ids for groups which should always by fully expanded (ie all rows rendered). Fx {{{"0 3 4"}}} would mean that group ids 0, 3, and 4 should always have all their members visible.

<<Anchor(PlaceEntryInfo)>>
==== PlaceEntryInfo ====
And a {{{PlaceEntryInfo}}} struct with signature {{{(sssuasbs{ss}RR)}}}. We use {{{P}}} as a shorthand signature:
{{{
  string dbus_path, (DBus path to the Entry object)
  string name,
  string icon,
  uint position, (the position to render the entry at in the places bar)
  string[] mimetypes, (mimetypes accepted for drag-n-drop)
  bool sensitive,
  string sections_model (DBus name of a Dee.Model)
  map<string,string> hints,
  RendererInfo entry_renderer_info
  RendererInfo global_renderer_info
}}}
<<Anchor(PlaceEntryInfoHints)>>
==== PlaceEntryInfo Hints ====
 . The following hints are defined for the {{{PlaceEntryInfo}}}
  * {{{UnitySectionStyle}}} - if set to {{{"breadcrumb"}}} the {{{sections_model}}} should be displayed as a breadcrumb trail instead of as separate buttons
  * {{{UnityPlaceBrowserPath}}} - if set, will contain a DBus object path pointing to an object on the place daemon implementing the interface [[#com.canonical.Unity.PlaceBrowser|com.canonical.Unity.PlaceBrowser]]
  * {{{UnityActiveSection}}} - optionally indicates which section the place daemon is currently showing. The value is the section id encoded in a string, eg {{{"3"}}}.This is used when returning from browsing mode to a particular section. This hint is not set when the section changes because of a call to {{{SetActiveSection()}}}.
  * {{{UnityExtraAction}}} - contains a string serialized {{{GIcon}}} which should be rendered as a button. When clicked Unity should call {{{com.canonical.Unity.Activation.Active()}}} with the argument being the string {{{"."}}}. An example usage is a "Browse This Folder in Nautilus" button rendered at the right of the path bar when in folder browsing mode. ''FIXME: This is an oversimplified way of extending the model with capabilities, designed this way to keep wire compatibility. We should definitely revisit this for Natty''
 
=== com.canonical.Unity.Place ===
The place daemon exposes the interface {{{com.canonical.Unity.Place}}} on the advertised {{{DBusName}}} and {{{DBusObjectPath}}} found in its {{{.place}}} file:
{{{
  method GetEntries (out aP)
  signal EntryAdded (out P)
  signal EntryRemoved (out s) (the DBus path to the Entry object)
}}}

=== com.canonical.Unity.PlaceEntry ===
Each listed entry exposes the interface {{{com.canonical.Unity.PlaceEntry}}}

{{{
  /* Global search from the home screen. Populates the models
   * defined in EntryInfo.entry_renderer_info */
  method SetGlobalSearch (in s search_string,
                          in {ss} hints,
                          out u hit_count)

  /* Set whether or not this section is currently being displayed */
  method SetActive (in b active);

  /* Search withing the currently active section */
  method SetSearch (in s search_string,
                    in {ss} hints);

  /* Request that a given section be represented in the model
   * defined by EntryInfo.entry_renderer_info */
  method SetActiveSection (in u active_section_id); (defaults to 0)

  signal EntryRendererInfoChanged (R renderer_info);

  signal GlobalRendererInfoChanged (R renderer_info);

  /* Emitted fx. when the hints change or the name of the sections model change.
   * Both may occur fx. when browsing into a folder.
   * The included struct is the fields of the PlaceEntryInfo struct, but
   * without the two RenderingInfo structs */
  signal PlaceEntryInfoChanged (in (sssuasbs{ss}) place_entry_info);

  /* Optionally emitted by a place entry once it has completed all operations for
   * a SetSearch, SetGlobalSearch, or SetActiveSection request and fully updated
   * the result model(s) accordingly. Places are not required to emit this signal
   * and the Unity shell must assume that they do */
  signal SearchFinished (in u section, in s search, in a{ss} hints)
}}}

=== Results Model ===
The value defined in {{{PlaceEntryInfo.results_model}}} is the bus name of a {{{Dee.Model}}} that holds the live results to be displayed in the main view. ''The columns of this model are specific for the renderer_name defined in the [[#RendererInfo|RendererInfo]] struct''. The column types for the {{{"UnityDefaultRenderer"}}} is:
{{{
  s uri
  s icon_hint
  u group_id
  s mimetype
  s display_name
  s comment
}}}

=== Groups Model ===
The bus name of the groups model is defined in {{{PlaceEntryInfo.groups_model}}}. This is another {{{Dee.Model}}}. It contains the description on how to render the individual group found in the results model.

The ''group_id'' in the results model maps to the row index in the groups model. The columns of the groups model are:
{{{
  s group_renderer (a Unity-specific rendering mode for this group)
  s display_name
  s icon_hint
}}}

=== Sections Model ===
Yet another {{{Dee.Model}}} which is defined by the name in {{{PlaceEntryInfo.sections_model}}}. This model defines the section headers for the entry displayed just below the places bar.

The row index in the model is used as the ''section_id'' - see the {{{PlaceEntry.SetActiveSections}}} method. The default active sections is always section 0.

The model columns are:
{{{
  s display_name
  s icon
}}}

= Activation Hooks =
Places can register "activation hooks" for certain types of URIs and/or mimetypes. This is done by defining a {{{[Activation]}}} group in the {{{.place}}} file like:

{{{
// normal .place stuff

[Activation]
URIPattern=Regex that URIs must match in order to trigger this activation
MimetypePattern=Regex that mimetypes must match in order to trigger this activation
Priority=0 // G_PRIORITY_{LOW,HIGHT,DEFAULT}
}}}

The activation service exposes a {{{com.canonical.Unity.Activation}}} interface on the same bus name and object path as the place service specified in the {{{[Place]}}} group.

=== com.canonical.Unity.Activation ===
{{{
  /**
   * Try to activate a URI
   * @uri: The URI to activate
   *
   * Returns: 0 if the URI was not activated, 1 if it was activated and dash
   * should not hide, and 2 if the URI was activated and the dash
   * should hide
   */
  Activate (in s uri, out u handled)
}}}

= Browsing. Aka Back/Forward =
Browsing buttons can be presented by the Unity rendering shell if the {{{UnityPlaceBrowserPath}}} hint is set on the [[#PlaceEntryInfo|PlaceEntryInfo]] struct. The {{{UnityPlaceBrowserPath}}} hint contains the DBus object path for an object in the place daemon implementing the {{{com.canonical.Unity.PlaceBrowser}}} interfafce.

This hint will be set by the model when you activate a folder (which causes the model to browse into that folder) - in which case also the {{{UnitySectionStyle}}} hint will be set to {{{"breadcrumb"}}}.

When the place daemon leaves browsing mode, it will often return to some specific section. In order to tell the Unity rendering shell which section to highlight the place daemon sets the hint {{{UnityActiveSection}}} to the id of the active section.

=== com.canonical.Unity.PlaceBrowser ===
The browsing is centered around a "states" object represented by a {{{a(bs)}}}. The array consists of two states. The 0th state being the "!GoBack state" and the 1st being the "!GoForward state". The {{{(bs)}}} state struct is interpreted as:

 . '''b''' : Whether or not this state is enabled or not. If False this state should be rendered as "disabled". Fx. when there's nothing in your backwards history.
 . '''s''' : A string optionally used as a tooltip or comment on what happens if you activate that state. Eg. "Go back to http://youtube.com"

{{{
  GoBack (out a(bs) state)
  GoForward (out a(bs) state)
  GetState (out a(bs) state)
}}}
#REFRESH 2 http://developer.ubuntu.com/scopes/

Unity/Lenses (last edited 2013-11-25 15:37:55 by dholbach)