10
namespace Unity.SamplePlace {
12
/* Absolute path to custom icons */
13
const string ICON_PATH = Config.DATADIR + "/icons/unity-icon-theme/places/svg/";
15
/* DBus name for the place. Must match out .place file */
16
const string BUS_NAME = "com.canonical.Unity.SamplePlace";
12
/* https://wiki.ubuntu.com/Unity/Lenses */
13
/* http://developer.ubuntu.com/api/ubuntu-12.04/python/Unity-5.0.html */
15
namespace Unity.SampleLens {
17
/* DBus name for the lens. Must match out .lens file */
18
const string BUS_NAME = "com.canonical.Unity.SampleLens";
19
* The Daemon class implements all of the logic for the place.
20
* It implements the Unity.Activation interface in order to
21
* do custom activation of the URI and Mime patterns defined in the
21
* The Daemon class implements all of the logic for the lens.
25
public class Daemon : GLib.Object, Unity.Activation
23
public class Daemon : GLib.Object
27
private Unity.PlaceController control;
28
private Unity.PlaceEntryInfo place_entry;
25
private Unity.Lens lens;
26
private Unity.Scope scope;
32
/* Create all the models we need to share with the Unity shell.
33
* The model column schemas must align with what we defined in
35
var sections_model = new Dee.SharedModel(BUS_NAME + ".SectionsModel");
36
sections_model.set_schema ("s", "s");
38
var groups_model = new Dee.SharedModel(BUS_NAME + ".GroupsModel");
39
groups_model.set_schema ("s", "s", "s");
41
var global_groups_model = new Dee.SharedModel(BUS_NAME + ".GlobalGroupsModel");
42
global_groups_model.set_schema ("s", "s", "s");
44
var results_model = new Dee.SharedModel(BUS_NAME + ".ResultsModel");
45
results_model.set_schema ("s", "s", "u", "s", "s", "s");
47
var global_results_model = new Dee.SharedModel(BUS_NAME + ".GlobalResultsModel");
48
global_results_model.set_schema ("s", "s", "u", "s", "s", "s");
50
/* Create a PlaceEntryInfo. The properties of the PlaceEntryInfo is
51
* automatically mapped back and forth over the bus, and removes most
52
* DBusisms from the place daemon code.
54
* Object path of the PlaceEntryInfo must match the one defined in the
55
* the place entry in the place .place file
57
place_entry = new PlaceEntryInfo ("/com/canonical/unity/sampleplace/stuff");
58
place_entry.sections_model = sections_model;
59
place_entry.entry_renderer_info.groups_model = groups_model;
60
place_entry.entry_renderer_info.results_model = results_model;
61
place_entry.global_renderer_info.groups_model = global_groups_model;
62
place_entry.global_renderer_info.results_model = global_results_model;
67
/* Unity preloads the icon defined in the .place file even before the
68
* place daemon is running - when we come up it will ratify the icon */
69
place_entry.icon = @"$(Config.PREFIX)/share/unity/sample-place-icon.png";
71
/* Listen for section changes and start updating our results model
73
place_entry.notify["active-section"].connect (update_entry_results_model);
75
/* Listen for changes to the place entry search */
76
place_entry.notify["active-search"].connect (update_entry_results_model);
78
/* Listen for changes to the global search */
79
place_entry.notify["active-global-search"].connect (update_global_results_model);
81
/* Listen for when the place is hidden/shown by the Unity Shell */
82
place_entry.notify["active"].connect (
84
debug (@"Activated: $(place_entry.active)");
88
/* The last thing we do is export the controller. Once that is up,
89
* clients will expect the Dee.SharedModels to work.
90
* The 'place' EntryInfo is exported for Unity to show by adding it to
91
* the controller. You can add more than one EntryInfo here if you have
92
* more than one place entry to export from the same place daemon */
93
control = new Unity.PlaceController ("/com/canonical/unity/sampleplace");
94
control.add_entry (place_entry);
96
/* Since the Daemon class implements the Unity.PlaceActivation interface
97
* we can override the default activation handler on the controller.
98
* We need to do that to properly handle the activation patternts we
99
* registered in the .place file */
100
control.activation = this;
102
/* Export the controller on the bus. Unity can see us past this point */
30
/* Set up the lens object (make sure it matches info in the .lens file */
31
lens = new Unity.Lens ("/com/canonical/unity/samplelens", "samplelens");
32
lens.search_hint = _("Search Stuff");
34
lens.search_in_global = true;
36
populate_categories ();
39
/* Create a scope so we can add results to the lens */
40
scope = new Unity.Scope ("/com/canonical/unity/samplelens/samplescope");
42
/* Let's ignore searches where only the leading or trailing whitespace
44
scope.generate_search_key.connect ((lens_search) =>
46
return lens_search.search_string.strip ();
49
/* Listen for search changes */
50
scope.search_changed.connect (on_search_changed);
52
/* Re-do the search if the filters changed */
53
scope.filters_changed.connect (() =>
55
scope.queue_search_changed (SearchType.DEFAULT);
58
/* Register the scope we created as local */
59
lens.add_local_scope (scope);
61
/* Export the lens on the bus. Unity can see us past this point */
105
64
} catch (IOError error) {
106
65
critical ("Failed to export DBus service for '%s': %s",
107
control.dbus_path, error.message);
66
lens.dbus_path, error.message);
111
private void populate_sections ()
113
var sections = place_entry.sections_model;
115
if (sections.get_n_rows() != 0)
117
critical ("The sections model should be empty before initial population");
121
/* The row offsets should match those from the Section enum */
122
sections.append (_("All Stuff"), "");
123
sections.append (_("My Stuff"), "");
124
sections.append (_("Your Stuff"), "");
127
private void populate_groups ()
129
var groups = place_entry.entry_renderer_info.groups_model;
131
if (groups.get_n_rows() != 0)
133
critical ("The groups model should be empty before initial population");
137
/* The row offsets should match those from the Group enum */
138
groups.append ("UnityDefaultRenderer", _("Group One"), ICON_PATH + "group-mostused.svg");
139
groups.append ("UnityDefaultRenderer", _("Group Two"), ICON_PATH + "group-recent.svg");
142
private void update_entry_results_model ()
144
/* If we're not active just ignore anything Unity tells us to do
145
* it's not gonna show on the screen anyway */
146
if (!place_entry.active)
70
private void populate_categories ()
72
GLib.List<Unity.Category> categories = new GLib.List<Unity.Category> ();
74
/* The offsets should match those from the Category enum (schemas.vala) */
75
var cat = new Unity.Category (_("All Stuff"),
76
new ThemedIcon ("web-browser"));
77
categories.append (cat);
78
cat = new Unity.Category (_("My Stuff"),
79
new ThemedIcon ("web-browser"));
80
categories.append (cat);
81
cat = new Unity.Category (_("Your Stuff"),
82
new ThemedIcon ("web-browser"));
83
categories.append (cat);
85
lens.categories = categories;
88
private void populate_filters ()
90
GLib.List<Unity.Filter> filters = new GLib.List<Unity.Filter> ();
92
var filter = new CheckOptionFilter ("filter1", _("Check filter"));
93
filter.sort_type = Unity.OptionsFilter.SortType.DISPLAY_NAME;
95
filter.add_option ("option1", _("Option 1"));
96
filter.add_option ("option2", _("Option 2"));
97
filter.add_option ("option3", _("Option 3"));
98
filter.add_option ("option4", _("Option 4"));
100
filters.append (filter);
102
lens.filters = filters;
105
private void on_search_changed (Unity.Scope scope,
106
Unity.LensSearch search,
107
Unity.SearchType search_type,
108
Cancellable cancellable)
110
/* We can either do the search here, or dispatch it into an async method
111
* if we're going to contact a webservice or do an asynchronous action */
112
start_search.begin (search, search_type, cancellable);
115
private async void start_search (Unity.LensSearch search,
116
Unity.SearchType search_type,
117
Cancellable cancellable)
119
message ("Started search for %s", search.search_string);
121
/* Simulate that this search takes a while to get the results,
122
* you could contact a web service or sweep the disc here etc. */
123
Timeout.add (500, start_search.callback);
126
if (cancellable.is_cancelled ())
128
/* we got another search meanwhile, let's just end this one */
149
var _results_model = place_entry.entry_renderer_info.results_model;
150
var _groups_model = place_entry.entry_renderer_info.groups_model;
151
var _search = place_entry.active_search;
152
var _section = (Section)place_entry.active_section;
154
update_results_model (_results_model, _groups_model,
158
private void update_global_results_model ()
160
/* Unlike update_entry_model() the global model may be updated
161
* even though we are not active */
163
var _results_model = place_entry.global_renderer_info.results_model;
164
var _groups_model = place_entry.global_renderer_info.groups_model;
165
var _search = place_entry.active_global_search;
166
var _section = Section.ALL_STUFF; /* We have no active section in global mode */
168
update_results_model (_results_model, _groups_model,
172
/* Generic method to update a results model. We do it like this to minimize
173
* code dup between updating the global- and the entry results model */
174
private void update_results_model (Dee.Model results_model, Dee.Model groups_model,
175
PlaceSearch? search, Section section)
177
debug ("Rebuilding results model");
178
results_model.clear ();
132
/* We have some results now, let's clear all the old ones and add
133
* the new to the results */
134
var model = search.results_model;
180
137
var icon = ContentType.get_icon ("inode/directory");
181
results_model.append ("file:///home",
182
icon.to_string (), /* Must be a serialized GIcon */
186
"Shared user home dir");
188
icon = ContentType.get_icon ("image/png");
189
results_model.append ("file:///usr/share/icons/hicolor/48x48/apps/evolution-mail.png",
194
"This is a png with the Evolution icon");
198
* Override of the default activation handler. Unity will ask the
199
* place daemon for activation of the URI pattern and mime type pattern
200
* defined in the .place file.
202
* This method should return a member of the enumeration
203
* Unity.ActivationStatus:
205
* - ActivationStatus.ACTIVATED_HIDE_DASH
206
* - ActivationStatus.ACTIVATED_SHOW_DASH
207
* - ActivationStatus.NOT_ACTIVATED
210
public async uint32 activate (string uri)
212
debug ("Requested activation of: %s", uri);
213
return ActivationStatus.NOT_ACTIVATED;
139
model.append ("file:///home/", // URI of the result
140
icon.to_string (), // string representation of an icon
141
Category.ALL_STUFF, // category index
142
"inode/directory", // mime-type of the URI,
143
"Home folder", // display name of the result
145
"file:///home/"); // URI for drag and drop
148
var uri = "http://www.google.com/q=%s".printf (search.search_string);
150
ContentType.get_icon ("text/html"),
153
"\"%s\" on Google".printf (search.search_string),
216
160
} /* End Daemon class */
218
} /* End Unity.SamplePlace namespace */
162
} /* End Unity.SampleLens namespace */