~unity-team/unity-lens-sample/trunk

« back to all changes in this revision

Viewing changes to src/daemon.vala

  • Committer: Michal Hruby
  • Date: 2012-01-30 22:06:04 UTC
  • Revision ID: michal.mhr@gmail.com-20120130220604-vs5dwe3j2y7v8vqi
Update for libunity 5.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
using Gee;
8
8
using Config;
9
9
 
10
 
namespace Unity.SamplePlace {
11
 
  
12
 
  /* Absolute path to custom icons */
13
 
  const string ICON_PATH = Config.DATADIR + "/icons/unity-icon-theme/places/svg/";
14
 
  
15
 
  /* DBus name for the place. Must match out .place file */
16
 
  const string BUS_NAME = "com.canonical.Unity.SamplePlace";
 
10
/* Developer docs: */
 
11
/*                 */
 
12
/*   https://wiki.ubuntu.com/Unity/Lenses */
 
13
/*   http://developer.ubuntu.com/api/ubuntu-12.04/python/Unity-5.0.html */
 
14
 
 
15
namespace Unity.SampleLens {
 
16
  
 
17
  /* DBus name for the lens. Must match out .lens file */
 
18
  const string BUS_NAME = "com.canonical.Unity.SampleLens";
17
19
 
18
20
  /**
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
22
 
   * .place file.
23
 
   *
 
21
   * The Daemon class implements all of the logic for the lens.
24
22
   */
25
 
  public class Daemon : GLib.Object, Unity.Activation
 
23
  public class Daemon : GLib.Object
26
24
  {
27
 
    private Unity.PlaceController control;
28
 
    private Unity.PlaceEntryInfo place_entry;
 
25
    private Unity.Lens lens;
 
26
    private Unity.Scope scope;
29
27
 
30
28
    construct
31
29
    {
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
34
 
       * schemas.vala */
35
 
      var sections_model = new Dee.SharedModel(BUS_NAME + ".SectionsModel");
36
 
      sections_model.set_schema ("s", "s");
37
 
 
38
 
      var groups_model = new Dee.SharedModel(BUS_NAME + ".GroupsModel");
39
 
      groups_model.set_schema ("s", "s", "s");
40
 
 
41
 
      var global_groups_model = new Dee.SharedModel(BUS_NAME + ".GlobalGroupsModel");
42
 
      global_groups_model.set_schema ("s", "s", "s");
43
 
 
44
 
      var results_model = new Dee.SharedModel(BUS_NAME + ".ResultsModel");
45
 
      results_model.set_schema ("s", "s", "u", "s", "s", "s");
46
 
 
47
 
      var global_results_model = new Dee.SharedModel(BUS_NAME + ".GlobalResultsModel");
48
 
      global_results_model.set_schema ("s", "s", "u", "s", "s", "s");
49
 
      
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.
53
 
       *
54
 
       * Object path of the PlaceEntryInfo must match the one defined in the
55
 
       * the place entry in the place .place file
56
 
       */
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;
63
 
 
64
 
      populate_sections ();
65
 
      populate_groups ();
66
 
 
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";
70
 
 
71
 
      /* Listen for section changes and start updating our results model
72
 
       * accordingly */
73
 
      place_entry.notify["active-section"].connect (update_entry_results_model);
74
 
 
75
 
      /* Listen for changes to the place entry search */
76
 
      place_entry.notify["active-search"].connect (update_entry_results_model);
77
 
 
78
 
      /* Listen for changes to the global search */
79
 
      place_entry.notify["active-global-search"].connect (update_global_results_model);
80
 
      
81
 
      /* Listen for when the place is hidden/shown by the Unity Shell */
82
 
      place_entry.notify["active"].connect (
83
 
        (obj, pspec) => {
84
 
          debug (@"Activated: $(place_entry.active)");
85
 
        }
86
 
      );          
87
 
 
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);
95
 
      
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;
101
 
 
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");
 
33
      lens.visible = true;
 
34
      lens.search_in_global = true;
 
35
 
 
36
      populate_categories ();
 
37
      populate_filters ();
 
38
 
 
39
      /* Create a scope so we can add results to the lens */
 
40
      scope = new Unity.Scope ("/com/canonical/unity/samplelens/samplescope");
 
41
 
 
42
      /* Let's ignore searches where only the leading or trailing whitespace
 
43
       * changes */
 
44
      scope.generate_search_key.connect ((lens_search) =>
 
45
      {
 
46
        return lens_search.search_string.strip ();
 
47
      });
 
48
      
 
49
      /* Listen for search changes */
 
50
      scope.search_changed.connect (on_search_changed);
 
51
 
 
52
      /* Re-do the search if the filters changed */
 
53
      scope.filters_changed.connect (() =>
 
54
      {
 
55
        scope.queue_search_changed (SearchType.DEFAULT);
 
56
      });
 
57
 
 
58
      /* Register the scope we created as local */
 
59
      lens.add_local_scope (scope);
 
60
 
 
61
      /* Export the lens on the bus. Unity can see us past this point */
103
62
      try {
104
 
        control.export ();
 
63
        lens.export ();
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);
108
67
      }
109
68
    }
110
69
 
111
 
    private void populate_sections ()
112
 
    {
113
 
      var sections = place_entry.sections_model;
114
 
 
115
 
      if (sections.get_n_rows() != 0)
116
 
        {
117
 
          critical ("The sections model should be empty before initial population");
118
 
          sections.clear ();
119
 
        }
120
 
 
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"), "");
125
 
    }
126
 
 
127
 
    private void populate_groups ()
128
 
    {
129
 
      var groups = place_entry.entry_renderer_info.groups_model;
130
 
 
131
 
      if (groups.get_n_rows() != 0)
132
 
        {
133
 
          critical ("The groups model should be empty before initial population");
134
 
          groups.clear ();
135
 
        }
136
 
 
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");
140
 
    }
141
 
    
142
 
    private void update_entry_results_model ()
143
 
    {
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 ()
 
71
    {
 
72
      GLib.List<Unity.Category> categories = new GLib.List<Unity.Category> ();
 
73
 
 
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);
 
84
 
 
85
      lens.categories = categories;
 
86
    }
 
87
 
 
88
    private void populate_filters ()
 
89
    {
 
90
      GLib.List<Unity.Filter> filters = new GLib.List<Unity.Filter> ();
 
91
 
 
92
      var filter = new CheckOptionFilter ("filter1", _("Check filter"));
 
93
      filter.sort_type = Unity.OptionsFilter.SortType.DISPLAY_NAME;
 
94
 
 
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"));
 
99
 
 
100
      filters.append (filter);
 
101
 
 
102
      lens.filters = filters;
 
103
    }
 
104
 
 
105
    private void on_search_changed (Unity.Scope scope,
 
106
                                    Unity.LensSearch search,
 
107
                                    Unity.SearchType search_type,
 
108
                                    Cancellable cancellable)
 
109
    {
 
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);
 
113
    }
 
114
 
 
115
    private async void start_search (Unity.LensSearch search,
 
116
                                     Unity.SearchType search_type,
 
117
                                     Cancellable cancellable)
 
118
    {
 
119
      message ("Started search for %s", search.search_string);
 
120
      
 
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);
 
124
      yield;
 
125
 
 
126
      if (cancellable.is_cancelled ())
 
127
      {
 
128
        /* we got another search meanwhile, let's just end this one */
147
129
        return;
148
 
                    
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;          
153
 
       
154
 
      update_results_model (_results_model, _groups_model,
155
 
                            _search, _section);
156
 
    }
157
 
    
158
 
    private void update_global_results_model ()
159
 
    {
160
 
      /* Unlike update_entry_model() the global model may be updated
161
 
       * even though we are not active */
162
 
    
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 */
167
 
       
168
 
      update_results_model (_results_model, _groups_model,
169
 
                            _search, _section);
170
 
    }
171
 
 
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)
176
 
    {
177
 
      debug ("Rebuilding results model");
178
 
      results_model.clear ();
179
 
      
 
130
      }
 
131
 
 
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;
 
135
      model.clear ();
 
136
 
180
137
      var icon = ContentType.get_icon ("inode/directory");
181
 
      results_model.append ("file:///home",
182
 
                            icon.to_string (), /* Must be a serialized GIcon */
183
 
                            Group.GROUP_ONE,
184
 
                            "inode/directory",
185
 
                            "/home folder",
186
 
                            "Shared user home dir");
187
 
      
188
 
      icon = ContentType.get_icon ("image/png");
189
 
      results_model.append ("file:///usr/share/icons/hicolor/48x48/apps/evolution-mail.png",
190
 
                            icon.to_string (),
191
 
                            Group.GROUP_TWO,
192
 
                            "image/png",
193
 
                            "Evolution icon",
194
 
                            "This is a png with the Evolution icon");
195
 
    }
196
 
 
197
 
    /**
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.
201
 
     *
202
 
     * This method should return a member of the enumeration
203
 
     * Unity.ActivationStatus:
204
 
     *
205
 
     * - ActivationStatus.ACTIVATED_HIDE_DASH
206
 
     * - ActivationStatus.ACTIVATED_SHOW_DASH
207
 
     * - ActivationStatus.NOT_ACTIVATED
208
 
     *
209
 
     */
210
 
    public async uint32 activate (string uri)
211
 
    {
212
 
      debug ("Requested activation of: %s", uri);
213
 
      return ActivationStatus.NOT_ACTIVATED;
214
 
    }
215
 
    
 
138
 
 
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
 
144
                    "",                  // comment
 
145
                    "file:///home/");    // URI for drag and drop
 
146
 
 
147
      /* And one more */
 
148
      var uri = "http://www.google.com/q=%s".printf (search.search_string);
 
149
      model.append (uri,
 
150
                    ContentType.get_icon ("text/html"),
 
151
                    Category.ALL_STUFF,
 
152
                    "text/html",
 
153
                    "\"%s\" on Google".printf (search.search_string),
 
154
                    "",
 
155
                    uri);
 
156
 
 
157
      search.finished ();
 
158
    }
 
159
 
216
160
  } /* End Daemon class */
217
161
 
218
 
} /* End Unity.SamplePlace namespace */
 
162
} /* End Unity.SampleLens namespace */