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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*
 * Copyright (C) 2010 Canonical Ltd
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authored by Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>
 *
 */
using DBus;
using Dee;
using Gee;
using Unity.Place;
using Config;

namespace Unity.SamplePlace {
  
  /* Absolute path to custom icons */
  const string ICON_PATH = Config.DATADIR + "/icons/unity-icon-theme/places/svg/";
  
  /* DBus name for the place. Must match out .place file */
  const string BUS_NAME = "com.canonical.Unity.SamplePlace";

  /**
   * The Daemon class implements all of the logic for the place.
   * It implements the Unity.Place.Activation interface in order to
   * do custom activation of the URI and Mime patterns defined in the
   * .place file.
   *
   */
  public class Daemon : GLib.Object, Unity.Place.Activation
  {
    private Unity.Place.Controller control;
    private Unity.Place.EntryInfo place_entry;

    construct
    {
      /* Create all the models we need to share with the Unity shell.
       * The model column schemas must align with what we defined in
       * schemas.vala */
      var sections_model = new Dee.SharedModel(BUS_NAME + ".SectionsModel",
                                               2, typeof (string), typeof (string));

      var groups_model = new Dee.SharedModel(
                                 BUS_NAME + ".GroupsModel",
                                 3, typeof (string), typeof (string),
                                 typeof (string));

      var global_groups_model = new Dee.SharedModel(
                                 BUS_NAME + ".GlobalGroupsModel",
                                 3, typeof (string), typeof (string),
                                 typeof (string));

      var results_model = new Dee.SharedModel(
                                 BUS_NAME + ".ResultsModel",
                                 6, typeof (string), typeof (string),
                                 typeof (uint), typeof (string),
                                 typeof (string), typeof (string));

      var global_results_model = new Dee.SharedModel(
                                 BUS_NAME + ".GlobalResultsModel",
                                 6, typeof (string), typeof (string),
                                 typeof (uint), typeof (string),
                                 typeof (string), typeof (string));

      /* Create an EntryInfo. The properties of the EntryInfo is automatically
       * mapped back and forth over the bus, and removes most DBusisms from
       * the place daemon code.
       *
       * Object path of the EntryInfo must match the one defined in the
       * the place entry in the place .place file
       */
      place_entry = new EntryInfo ("/com/canonical/unity/sampleplace/stuff");
      place_entry.sections_model = sections_model;
      place_entry.entry_renderer_info.groups_model = groups_model;
      place_entry.entry_renderer_info.results_model = results_model;
      place_entry.global_renderer_info.groups_model = global_groups_model;
      place_entry.global_renderer_info.results_model = global_results_model;

      populate_sections ();
      populate_groups ();

      /* Unity preloads the icon defined in the .place file even before the
       * place daemon is running - when we come up it will ratify the icon */
      place_entry.icon = @"$(Config.PREFIX)/share/unity/files.png";

      /* Listen for section changes and start updating our results model
       * accordingly */
      place_entry.notify["active-section"].connect (update_entry_results_model);

      /* Listen for changes to the place entry search */
      place_entry.notify["active-search"].connect (update_entry_results_model);

      /* Listen for changes to the global search */
      place_entry.notify["active-global-search"].connect (update_global_results_model);
      
      /* Listen for when the place is hidden/shown by the Unity Shell */
      place_entry.notify["active"].connect (
        (obj, pspec) => {
          debug (@"Activated: $(place_entry.active)");
        }
      );
      
      /* Export all our Dee.SharedModels on the bus */
      sections_model.connect ();
      groups_model.connect ();
      global_groups_model.connect ();
      results_model.connect ();
      global_results_model.connect ();            

      /* The last thing we do is export the controller. Once that is up,
       * clients will expect the Dee.SharedModels to work.
       * The 'place' EntryInfo is exported for Unity to show by adding it to
       * the controller. You can add more than one EntryInfo here if you have
       * more than one place entry to export from the same place daemon */
      control = new Unity.Place.Controller ("/com/canonical/unity/sampleplace");
      control.add_entry (place_entry);
      
      /* Since the Daemon class implements the Unity.Place.Activation interface
       * we can override the default activation handler on the controller.
       * We need to do that to properly handle the activation patternts we
       * registered in the .place file  */
      control.activation = this;

      /* Export the controller on the bus. Unity can see us past this point */
      try {
        control.export ();
      } catch (DBus.Error error) {
        critical ("Failed to export DBus service for '%s': %s",
                  control.dbus_path, error.message);
      }
    }

    private void populate_sections ()
    {
      var sections = place_entry.sections_model;

      if (sections.get_n_rows() != 0)
        {
          critical ("The sections model should be empty before initial population");
          sections.clear ();
        }

      /* The row offsets should match those from the Section enum */
      sections.append (SectionsColumn.DISPLAY_NAME, _("All Stuff"),
                       SectionsColumn.ICON_HINT, "", -1);
      sections.append (SectionsColumn.DISPLAY_NAME, _("My Stuff"),
                       SectionsColumn.ICON_HINT, "", -1);
      sections.append (SectionsColumn.DISPLAY_NAME, _("Your Stuff"),
                       SectionsColumn.ICON_HINT, "", -1);
    }

    private void populate_groups ()
    {
      var groups = place_entry.entry_renderer_info.groups_model;

      if (groups.get_n_rows() != 0)
        {
          critical ("The groups model should be empty before initial population");
          groups.clear ();
        }

      /* The row offsets should match those from the Group enum */
      groups.append (GroupsColumn.RENDERER, "UnityDefaultRenderer",
                     GroupsColumn.DISPLAY_NAME, _("Group One"),
                     GroupsColumn.ICON_HINT, ICON_PATH + "group-mostused.svg", -1);
      groups.append (GroupsColumn.RENDERER, "UnityDefaultRenderer",
                     GroupsColumn.DISPLAY_NAME, _("Group Two"),
                     GroupsColumn.ICON_HINT, ICON_PATH + "group-recent.svg", -1);
    }
    
    private void update_entry_results_model ()
    {
      /* If we're not active just ignore anything Unity tells us to do
       * it's not gonna show on the screen anyway */
      if (!place_entry.active)
        return;
                    
      var _results_model = place_entry.entry_renderer_info.results_model;
      var _groups_model = place_entry.entry_renderer_info.groups_model;
      var _search = place_entry.active_search;
      var _section = (Section)place_entry.active_section;          
       
      update_results_model (_results_model, _groups_model,
                            _search, _section);
    }
    
    private void update_global_results_model ()
    {
      /* Unlike update_entry_model() the global model may be updated
       * even though we are not active */
    
      var _results_model = place_entry.global_renderer_info.results_model;
      var _groups_model = place_entry.global_renderer_info.groups_model;
      var _search = place_entry.active_global_search;
      var _section = Section.ALL_STUFF; /* We have no active section in global mode */
       
      update_results_model (_results_model, _groups_model,
                            _search, _section);
    }

    /* Generic method to update a results model. We do it like this to minimize
     * code dup between updating the global- and the entry results model */
    private void update_results_model (Dee.Model results_model, Dee.Model groups_model,
                                       Search? search, Section section)
    {
    
    }

    /**
     * Override of the default activation handler. Unity will ask the
     * place daemon for activation of the URI pattern and mime type pattern
     * defined in the .place file.
     *
     * This method should return a member of the enumeration
     * Unity.Place.ActivationStatus:
     *
     * - ActivationStatus.ACTIVATED_HIDE_DASH
     * - ActivationStatus.ACTIVATED_SHOW_DASH
     * - ActivationStatus.NOT_ACTIVATED
     *
     */
    public async uint32 activate (string uri)
    {
      return ActivationStatus.NOT_ACTIVATED;
    }
    
  } /* End Daemon class */

} /* End Unity.SamplePlace namespace */