~ubuntu-branches/ubuntu/saucy/indicator-appmenu/saucy-updates

« back to all changes in this revision

Viewing changes to src/huddbusmenucollector.c

  • Committer: Package Import Robot
  • Author(s): Automatic PS uploader, Mathieu Trudel-Lapierre, Automatic PS uploader
  • Date: 2013-02-20 09:41:54 UTC
  • mfrom: (1.1.40)
  • Revision ID: package-import@ubuntu.com-20130220094154-zrxsx0vgay436wyt
Tags: 13.01.0daily13.02.20-0ubuntu1
[ Mathieu Trudel-Lapierre ]
* Artificially bump upstream major version to please hud.

[ Automatic PS uploader ]
* Automatic snapshot from revision 234

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2012 Canonical Ltd.
3
 
 *
4
 
 * This program is free software: you can redistribute it and/or modify it
5
 
 * under the terms of the GNU General Public License version 3, as
6
 
 * published by the Free Software Foundation.
7
 
 *
8
 
 * This program is distributed in the hope that it will be useful, but
9
 
 * WITHOUT ANY WARRANTY; without even the implied warranties of
10
 
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11
 
 * PURPOSE.  See the GNU General Public License for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU General Public License along
14
 
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 
 *
16
 
 * Authors: Ryan Lortie <desrt@desrt.ca>
17
 
 *          Ted Gould <ted@canonical.com>
18
 
 */
19
 
 
20
 
#define G_LOG_DOMAIN "huddbusmenucollector"
21
 
 
22
 
#include "huddbusmenucollector.h"
23
 
 
24
 
#include <libdbusmenu-glib/client.h>
25
 
#include <string.h>
26
 
 
27
 
#include "hudappmenuregistrar.h"
28
 
#include "hudresult.h"
29
 
#include "hudsource.h"
30
 
 
31
 
/**
32
 
 * SECTION:huddbusmenucollector
33
 
 * @title: HudDbusmenuCollector
34
 
 * @short_description: a #HudSource that collects #HudItems from
35
 
 *   Dbusmenu
36
 
 *
37
 
 * The #HudDbusmenuCollector collects menu items from a #DbusmenuClient.
38
 
 *
39
 
 * There are two modes of operation.
40
 
 *
41
 
 * In the simple mode, the collector is created with a specified
42
 
 * endpoint using hud_dbusmenu_collector_new_for_endpoint().  A
43
 
 * #DbusmenuClient is constructed using this endpoint and the collector
44
 
 * constructs #HudItems for the contents of the menu found there.  This
45
 
 * mode is intended for use with indicators.
46
 
 *
47
 
 * For menus associated with application windows (ie: menubars), we must
48
 
 * consult the AppMenu registrar in order to discover the endpoint to
49
 
 * use.  This second mode of the collector is used by calling
50
 
 * hud_dbusmenu_collector_new_for_window().
51
 
 **/
52
 
 
53
 
/**
54
 
 * HudDbusmenuCollector:
55
 
 *
56
 
 * This is an opaque structure type.
57
 
 **/
58
 
 
59
 
typedef struct
60
 
{
61
 
  HudItem parent_instance;
62
 
 
63
 
  DbusmenuMenuitem *menuitem;
64
 
  gboolean is_opened;
65
 
} HudDbusmenuItem;
66
 
 
67
 
typedef HudItemClass HudDbusmenuItemClass;
68
 
 
69
 
G_DEFINE_TYPE (HudDbusmenuItem, hud_dbusmenu_item, HUD_TYPE_ITEM)
70
 
 
71
 
static void
72
 
hud_dbusmenu_item_activate (HudItem  *hud_item,
73
 
                            GVariant *platform_data)
74
 
{
75
 
  HudDbusmenuItem *item = (HudDbusmenuItem *) hud_item;
76
 
  const gchar *startup_id;
77
 
  guint32 timestamp = 0;
78
 
 
79
 
  if (g_variant_lookup (platform_data, "desktop-startup-id", "&s", &startup_id))
80
 
    {
81
 
      const gchar *time_tag;
82
 
 
83
 
      if ((time_tag = strstr (startup_id, "_TIME")))
84
 
        {
85
 
          gint64 result;
86
 
 
87
 
          result = g_ascii_strtoll (time_tag + 5, NULL, 10);
88
 
 
89
 
          if (0 <= result && result <= G_MAXINT32)
90
 
           timestamp = result;
91
 
        }
92
 
    }
93
 
 
94
 
  dbusmenu_menuitem_handle_event(item->menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, NULL, timestamp);
95
 
}
96
 
 
97
 
static void
98
 
hud_dbusmenu_item_finalize (GObject *object)
99
 
{
100
 
  HudDbusmenuItem *item = (HudDbusmenuItem *) object;
101
 
 
102
 
  g_object_unref (item->menuitem);
103
 
 
104
 
  G_OBJECT_CLASS (hud_dbusmenu_item_parent_class)
105
 
    ->finalize (object);
106
 
}
107
 
 
108
 
static void
109
 
hud_dbusmenu_item_init (HudDbusmenuItem *item)
110
 
{
111
 
}
112
 
 
113
 
static void
114
 
hud_dbusmenu_item_class_init (HudDbusmenuItemClass *class)
115
 
{
116
 
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
117
 
 
118
 
  gobject_class->finalize = hud_dbusmenu_item_finalize;
119
 
  class->activate = hud_dbusmenu_item_activate;
120
 
}
121
 
 
122
 
static const gchar *
123
 
hud_dbusmenu_item_get_label_property (const gchar *type)
124
 
{
125
 
  static const gchar * const property_table[][2] =
126
 
  {
127
 
    { DBUSMENU_CLIENT_TYPES_DEFAULT,                 DBUSMENU_MENUITEM_PROP_LABEL                         },
128
 
    /* Indicator Messages */
129
 
    { "application-item",                            DBUSMENU_MENUITEM_PROP_LABEL                         },
130
 
    { "indicator-item",                              "indicator-label"                                    },
131
 
    /* Indicator Datetime */
132
 
    { "appointment-item",                            "appointment-label"                                  },
133
 
    { "timezone-item",                               "timezone-name"                                      },
134
 
    /* Indicator Sound */
135
 
    { "x-canonical-sound-menu-player-metadata-type", "x-canonical-sound-menu-player-metadata-player-name" },
136
 
    { "x-canonical-sound-menu-mute-type",            DBUSMENU_MENUITEM_PROP_LABEL                         },
137
 
    /* Indicator User */
138
 
    { "x-canonical-user-item",                       "user-item-name"                                     }
139
 
  };
140
 
  static GHashTable *property_hash;
141
 
 
142
 
  if G_UNLIKELY (property_hash == NULL)
143
 
    {
144
 
      gint i;
145
 
 
146
 
      property_hash = g_hash_table_new (g_str_hash, g_str_equal);
147
 
 
148
 
      for (i = 0; i < G_N_ELEMENTS (property_table); i++)
149
 
        g_hash_table_insert (property_hash, (gpointer) property_table[i][0], (gpointer) property_table[i][1]);
150
 
    }
151
 
 
152
 
  if (type == NULL)
153
 
    return DBUSMENU_MENUITEM_PROP_LABEL;
154
 
 
155
 
  return g_hash_table_lookup (property_hash, type);
156
 
}
157
 
 
158
 
 
159
 
static HudDbusmenuItem *
160
 
hud_dbusmenu_item_new (HudStringList    *context,
161
 
                       const gchar      *desktop_file,
162
 
                       const gchar      *icon,
163
 
                       DbusmenuMenuitem *menuitem)
164
 
{
165
 
  HudStringList *tokens;
166
 
  HudDbusmenuItem *item;
167
 
  const gchar *type;
168
 
  const gchar *prop;
169
 
  gboolean enabled;
170
 
 
171
 
  type = dbusmenu_menuitem_property_get (menuitem, DBUSMENU_MENUITEM_PROP_TYPE);
172
 
  prop = hud_dbusmenu_item_get_label_property (type);
173
 
 
174
 
  if (prop && dbusmenu_menuitem_property_exist (menuitem, prop))
175
 
    {
176
 
      const gchar *label;
177
 
 
178
 
      label = dbusmenu_menuitem_property_get (menuitem, prop);
179
 
      tokens = hud_string_list_cons_label (label, context);
180
 
      enabled = TRUE;
181
 
    }
182
 
  else
183
 
    {
184
 
      tokens = hud_string_list_ref (context);
185
 
      enabled = FALSE;
186
 
    }
187
 
 
188
 
  if (enabled)
189
 
    enabled &= !dbusmenu_menuitem_property_exist (menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE) ||
190
 
               dbusmenu_menuitem_property_get_bool (menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE);
191
 
 
192
 
  if (enabled)
193
 
    enabled &= !dbusmenu_menuitem_property_exist (menuitem, DBUSMENU_MENUITEM_PROP_ENABLED) ||
194
 
               dbusmenu_menuitem_property_get_bool (menuitem, DBUSMENU_MENUITEM_PROP_ENABLED);
195
 
 
196
 
  if (enabled)
197
 
    enabled &= !dbusmenu_menuitem_property_exist (menuitem, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY);
198
 
 
199
 
  item = hud_item_construct (hud_dbusmenu_item_get_type (), tokens, desktop_file, icon, enabled);
200
 
  item->menuitem = g_object_ref (menuitem);
201
 
 
202
 
  hud_string_list_unref (tokens);
203
 
 
204
 
  return item;
205
 
}
206
 
 
207
 
struct _HudDbusmenuCollector
208
 
{
209
 
  GObject parent_instance;
210
 
 
211
 
  DbusmenuClient *client;
212
 
  DbusmenuMenuitem *root;
213
 
  gchar *application_id;
214
 
  HudStringList *prefix;
215
 
  gchar *icon;
216
 
  GHashTable *items;
217
 
  guint penalty;
218
 
  guint xid;
219
 
  gboolean alive;
220
 
  gint use_count;
221
 
  gboolean reentrance_check;
222
 
};
223
 
 
224
 
typedef GObjectClass HudDbusmenuCollectorClass;
225
 
 
226
 
static void hud_dbusmenu_collector_iface_init (HudSourceInterface *iface);
227
 
G_DEFINE_TYPE_WITH_CODE (HudDbusmenuCollector, hud_dbusmenu_collector, G_TYPE_OBJECT,
228
 
                         G_IMPLEMENT_INTERFACE (HUD_TYPE_SOURCE, hud_dbusmenu_collector_iface_init))
229
 
 
230
 
static void
231
 
hud_dbusmenu_collector_open_submenu (gpointer key,
232
 
                                     gpointer value,
233
 
                                     gpointer user_data)
234
 
{
235
 
  DbusmenuMenuitem *menuitem = key;
236
 
  HudDbusmenuItem *item = value;
237
 
 
238
 
  if (dbusmenu_menuitem_property_exist (menuitem, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY))
239
 
    {
240
 
      dbusmenu_menuitem_handle_event (menuitem, DBUSMENU_MENUITEM_EVENT_OPENED, NULL, 0);
241
 
      item->is_opened = TRUE;
242
 
    }
243
 
}
244
 
 
245
 
static void
246
 
hud_dbusmenu_collector_close_submenu (gpointer key,
247
 
                                      gpointer value,
248
 
                                      gpointer user_data)
249
 
{
250
 
  DbusmenuMenuitem *menuitem = key;
251
 
  HudDbusmenuItem *item = value;
252
 
 
253
 
  if (item->is_opened)
254
 
    {
255
 
      dbusmenu_menuitem_handle_event (menuitem, DBUSMENU_MENUITEM_EVENT_CLOSED, NULL, 0);
256
 
      item->is_opened = FALSE;
257
 
    }
258
 
}
259
 
 
260
 
static void
261
 
hud_dbusmenu_collector_use (HudSource *source)
262
 
{
263
 
  HudDbusmenuCollector *collector = HUD_DBUSMENU_COLLECTOR (source);
264
 
 
265
 
  collector->reentrance_check = TRUE;
266
 
 
267
 
  if (collector->use_count == 0)
268
 
    g_hash_table_foreach (collector->items, hud_dbusmenu_collector_open_submenu, NULL);
269
 
 
270
 
  collector->use_count++;
271
 
 
272
 
  collector->reentrance_check = FALSE;
273
 
}
274
 
 
275
 
static void
276
 
hud_dbusmenu_collector_unuse (HudSource *source)
277
 
{
278
 
  HudDbusmenuCollector *collector = HUD_DBUSMENU_COLLECTOR (source);
279
 
 
280
 
  g_return_if_fail (collector->use_count > 0);
281
 
 
282
 
  collector->reentrance_check = TRUE;
283
 
 
284
 
  collector->use_count--;
285
 
 
286
 
  if (collector->use_count == 0)
287
 
    g_hash_table_foreach (collector->items, hud_dbusmenu_collector_close_submenu, NULL);
288
 
 
289
 
  collector->reentrance_check = FALSE;
290
 
}
291
 
 
292
 
static void
293
 
hud_dbusmenu_collector_search (HudSource    *source,
294
 
                               GPtrArray    *results_array,
295
 
                               HudTokenList *search_string)
296
 
{
297
 
  HudDbusmenuCollector *collector = HUD_DBUSMENU_COLLECTOR (source);
298
 
  GHashTableIter iter;
299
 
  gpointer item;
300
 
 
301
 
  g_hash_table_iter_init (&iter, collector->items);
302
 
  while (g_hash_table_iter_next (&iter, NULL, &item))
303
 
    {
304
 
      HudResult *result;
305
 
 
306
 
      result = hud_result_get_if_matched (item, search_string, collector->penalty);
307
 
      if (result)
308
 
        g_ptr_array_add (results_array, result);
309
 
    }
310
 
}
311
 
 
312
 
static void
313
 
hud_dbusmenu_collector_add_item (HudDbusmenuCollector *collector,
314
 
                                 HudStringList        *context,
315
 
                                 DbusmenuMenuitem     *menuitem);
316
 
static void
317
 
hud_dbusmenu_collector_remove_item (HudDbusmenuCollector *collector,
318
 
                                    DbusmenuMenuitem     *menuitem);
319
 
 
320
 
static void
321
 
hud_dbusmenu_collector_child_added (DbusmenuMenuitem *menuitem,
322
 
                                    DbusmenuMenuitem *child,
323
 
                                    guint             position,
324
 
                                    gpointer          user_data)
325
 
{
326
 
  HudDbusmenuCollector *collector = user_data;
327
 
  HudStringList *context;
328
 
  HudItem *item;
329
 
 
330
 
  g_assert (!collector->reentrance_check);
331
 
 
332
 
  item = g_hash_table_lookup (collector->items, menuitem);
333
 
  g_assert (item != NULL);
334
 
 
335
 
  context = hud_item_get_tokens (item);
336
 
 
337
 
  hud_dbusmenu_collector_add_item (collector, context, child);
338
 
}
339
 
 
340
 
static void
341
 
hud_dbusmenu_collector_child_removed (DbusmenuMenuitem *menuitem,
342
 
                                      DbusmenuMenuitem *child,
343
 
                                      gpointer          user_data)
344
 
{
345
 
  HudDbusmenuCollector *collector = user_data;
346
 
 
347
 
  g_assert (!collector->reentrance_check);
348
 
 
349
 
  hud_dbusmenu_collector_remove_item (collector, child);
350
 
}
351
 
 
352
 
static void
353
 
hud_dbusmenu_collector_property_changed (DbusmenuMenuitem *menuitem,
354
 
                                         const gchar      *property_name,
355
 
                                         GVariant         *new_value,
356
 
                                         gpointer          user_data)
357
 
{
358
 
  HudDbusmenuCollector *collector = user_data;
359
 
  DbusmenuMenuitem *parent;
360
 
  HudStringList *context;
361
 
  HudDbusmenuItem *item;
362
 
  gboolean was_open;
363
 
 
364
 
  g_assert (!collector->reentrance_check);
365
 
 
366
 
  parent = dbusmenu_menuitem_get_parent (menuitem);
367
 
 
368
 
  if (parent)
369
 
    {
370
 
      HudItem *parentitem;
371
 
 
372
 
      parentitem = g_hash_table_lookup (collector->items, parent);
373
 
      context = hud_item_get_tokens (parentitem);
374
 
    }
375
 
  else
376
 
    context = collector->prefix;
377
 
 
378
 
  item = g_hash_table_lookup (collector->items, menuitem);
379
 
  was_open = item->is_opened;
380
 
  g_hash_table_remove (collector->items, menuitem);
381
 
 
382
 
  item = hud_dbusmenu_item_new (context, collector->application_id, collector->icon, menuitem);
383
 
 
384
 
  if (collector->use_count && !was_open && dbusmenu_menuitem_property_exist (menuitem, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY))
385
 
    {
386
 
      dbusmenu_menuitem_handle_event (menuitem, DBUSMENU_MENUITEM_EVENT_OPENED, NULL, 0);
387
 
      item->is_opened = TRUE;
388
 
    }
389
 
 
390
 
  g_hash_table_insert (collector->items, menuitem, item);
391
 
 
392
 
  hud_source_changed (HUD_SOURCE (collector));
393
 
}
394
 
 
395
 
static void
396
 
hud_dbusmenu_collector_add_item (HudDbusmenuCollector *collector,
397
 
                                 HudStringList        *context,
398
 
                                 DbusmenuMenuitem     *menuitem)
399
 
{
400
 
  HudDbusmenuItem *item;
401
 
  GList *child;
402
 
 
403
 
  item = hud_dbusmenu_item_new (context, collector->application_id, collector->icon, menuitem);
404
 
  context = hud_item_get_tokens (HUD_ITEM (item));
405
 
 
406
 
  g_signal_connect (menuitem, "property-changed", G_CALLBACK (hud_dbusmenu_collector_property_changed), collector);
407
 
  g_signal_connect (menuitem, "child-added", G_CALLBACK (hud_dbusmenu_collector_child_added), collector);
408
 
  g_signal_connect (menuitem, "child-removed", G_CALLBACK (hud_dbusmenu_collector_child_removed), collector);
409
 
 
410
 
  /* If we're actively being queried and we add a new submenu item, open it. */
411
 
  if (collector->use_count && dbusmenu_menuitem_property_exist (menuitem, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY))
412
 
    {
413
 
      dbusmenu_menuitem_handle_event (menuitem, DBUSMENU_MENUITEM_EVENT_OPENED, NULL, 0);
414
 
      item->is_opened = TRUE;
415
 
    }
416
 
 
417
 
  g_hash_table_insert (collector->items, menuitem, item);
418
 
 
419
 
  for (child = dbusmenu_menuitem_get_children (menuitem); child; child = child->next)
420
 
    hud_dbusmenu_collector_add_item (collector, context, child->data);
421
 
 
422
 
  if (collector->alive)
423
 
    hud_source_changed (HUD_SOURCE (collector));
424
 
}
425
 
 
426
 
static void
427
 
hud_dbusmenu_collector_remove_item (HudDbusmenuCollector *collector,
428
 
                                    DbusmenuMenuitem     *menuitem)
429
 
{
430
 
  GList *child;
431
 
 
432
 
  g_signal_handlers_disconnect_by_func (menuitem, hud_dbusmenu_collector_property_changed, collector);
433
 
  g_signal_handlers_disconnect_by_func (menuitem, hud_dbusmenu_collector_child_added, collector);
434
 
  g_signal_handlers_disconnect_by_func (menuitem, hud_dbusmenu_collector_child_removed, collector);
435
 
  g_hash_table_remove (collector->items, menuitem);
436
 
 
437
 
  for (child = dbusmenu_menuitem_get_children (menuitem); child; child = child->next)
438
 
    hud_dbusmenu_collector_remove_item (collector, child->data);
439
 
 
440
 
  if (collector->alive)
441
 
    hud_source_changed (HUD_SOURCE (collector));
442
 
}
443
 
 
444
 
static void
445
 
hud_dbusmenu_collector_setup_root (HudDbusmenuCollector *collector,
446
 
                                   DbusmenuMenuitem     *root)
447
 
{
448
 
  if (collector->root)
449
 
    {
450
 
      /* If the collector has the submenus opened, close them before we
451
 
       * remove them all.  The use_count being non-zero will cause them
452
 
       * to be reopened as they are added back below (if they will be).
453
 
       */
454
 
      if (collector->use_count > 0)
455
 
        g_hash_table_foreach (collector->items, hud_dbusmenu_collector_close_submenu, NULL);
456
 
 
457
 
      hud_dbusmenu_collector_remove_item (collector, collector->root);
458
 
      g_clear_object (&collector->root);
459
 
    }
460
 
 
461
 
  if (root)
462
 
    {
463
 
      hud_dbusmenu_collector_add_item (collector, collector->prefix, root);
464
 
      collector->root = g_object_ref (root);
465
 
    }
466
 
}
467
 
 
468
 
static void
469
 
hud_dbusmenu_collector_root_changed (DbusmenuClient   *client,
470
 
                                     DbusmenuMenuitem *root,
471
 
                                     gpointer          user_data)
472
 
{
473
 
  HudDbusmenuCollector *collector = user_data;
474
 
 
475
 
  g_assert (!collector->reentrance_check);
476
 
 
477
 
  hud_dbusmenu_collector_setup_root (collector, root);
478
 
}
479
 
 
480
 
static void
481
 
hud_dbusmenu_collector_setup_endpoint (HudDbusmenuCollector *collector,
482
 
                                       const gchar          *bus_name,
483
 
                                       const gchar          *object_path)
484
 
{
485
 
  g_debug ("endpoint is %s %s", bus_name, object_path);
486
 
 
487
 
  if (collector->client)
488
 
    {
489
 
      g_signal_handlers_disconnect_by_func (collector->client, hud_dbusmenu_collector_root_changed, collector);
490
 
      hud_dbusmenu_collector_setup_root (collector, NULL);
491
 
      g_clear_object (&collector->client);
492
 
    }
493
 
 
494
 
  if (bus_name && object_path)
495
 
    {
496
 
      collector->client = dbusmenu_client_new (bus_name, object_path);
497
 
      g_signal_connect_object (collector->client, "root-changed",
498
 
                               G_CALLBACK (hud_dbusmenu_collector_root_changed), collector, 0);
499
 
      hud_dbusmenu_collector_setup_root (collector, dbusmenu_client_get_root (collector->client));
500
 
    }
501
 
}
502
 
 
503
 
static void
504
 
hud_dbusmenu_collector_registrar_observer_func (HudAppMenuRegistrar *registrar,
505
 
                                                guint                xid,
506
 
                                                const gchar         *bus_name,
507
 
                                                const gchar         *object_path,
508
 
                                                gpointer             user_data)
509
 
{
510
 
  HudDbusmenuCollector *collector = user_data;
511
 
 
512
 
  hud_dbusmenu_collector_setup_endpoint (collector, bus_name, object_path);
513
 
}
514
 
 
515
 
 
516
 
static void
517
 
hud_dbusmenu_collector_finalize (GObject *object)
518
 
{
519
 
  HudDbusmenuCollector *collector = HUD_DBUSMENU_COLLECTOR (object);
520
 
 
521
 
  if (collector->xid)
522
 
    hud_app_menu_registrar_remove_observer (hud_app_menu_registrar_get (), collector->xid,
523
 
                                            hud_dbusmenu_collector_registrar_observer_func, collector);
524
 
 
525
 
  /* remove all the items without firing change signals */
526
 
  collector->alive = FALSE;
527
 
  hud_dbusmenu_collector_setup_endpoint (collector, NULL, NULL);
528
 
 
529
 
  /* make sure the table is empty before we free it */
530
 
  g_assert (g_hash_table_size (collector->items) == 0);
531
 
  g_hash_table_unref (collector->items);
532
 
 
533
 
  g_free (collector->application_id);
534
 
  g_free (collector->icon);
535
 
 
536
 
  hud_string_list_unref (collector->prefix);
537
 
  g_clear_object (&collector->client);
538
 
 
539
 
  G_OBJECT_CLASS (hud_dbusmenu_collector_parent_class)
540
 
    ->finalize (object);
541
 
}
542
 
 
543
 
static void
544
 
hud_dbusmenu_collector_init (HudDbusmenuCollector *collector)
545
 
{
546
 
  collector->items = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
547
 
}
548
 
 
549
 
static void
550
 
hud_dbusmenu_collector_iface_init (HudSourceInterface *iface)
551
 
{
552
 
  iface->use = hud_dbusmenu_collector_use;
553
 
  iface->unuse = hud_dbusmenu_collector_unuse;
554
 
  iface->search = hud_dbusmenu_collector_search;
555
 
}
556
 
 
557
 
static void
558
 
hud_dbusmenu_collector_class_init (HudDbusmenuCollectorClass *class)
559
 
{
560
 
  class->finalize = hud_dbusmenu_collector_finalize;
561
 
}
562
 
 
563
 
/**
564
 
 * hud_dbusmenu_collector_new_for_endpoint:
565
 
 * @application_id: a unique identifier for the application
566
 
 * @prefix: the title to prefix to all items
567
 
 * @icon: the icon for the appliction
568
 
 * @penalty: the penalty to apply to all results
569
 
 * @bus_name: a D-Bus bus name
570
 
 * @object_path: an object path at the destination given by @bus_name
571
 
 *
572
 
 * Creates a new #HudDbusmenuCollector for the specified endpoint.
573
 
 *
574
 
 * Internally, a #DbusmenuClient is created for this endpoint.  Searches
575
 
 * are performed against the contents of those menus.
576
 
 *
577
 
 * This call is intended to be used for indicators.
578
 
 *
579
 
 * If @prefix is non-%NULL (which, for indicators, it ought to be), then
580
 
 * it is prefixed to every item created by the collector.
581
 
 *
582
 
 * If @penalty is non-zero then all results returned from the collector
583
 
 * have their distance increased by a percentage equal to the penalty.
584
 
 * This allows items from indicators to score lower than they would
585
 
 * otherwise.
586
 
 *
587
 
 * Returns: a new #HudDbusmenuCollector
588
 
 **/
589
 
HudDbusmenuCollector *
590
 
hud_dbusmenu_collector_new_for_endpoint (const gchar *application_id,
591
 
                                         const gchar *prefix,
592
 
                                         const gchar *icon,
593
 
                                         guint        penalty,
594
 
                                         const gchar *bus_name,
595
 
                                         const gchar *object_path)
596
 
{
597
 
  HudDbusmenuCollector *collector;
598
 
 
599
 
  collector = g_object_new (HUD_TYPE_DBUSMENU_COLLECTOR, NULL);
600
 
  collector->application_id = g_strdup (application_id);
601
 
  collector->icon = g_strdup (icon);
602
 
  if (prefix)
603
 
    collector->prefix = hud_string_list_cons (prefix, NULL);
604
 
  collector->penalty = penalty;
605
 
  hud_dbusmenu_collector_setup_endpoint (collector, bus_name, object_path);
606
 
 
607
 
  collector->alive = TRUE;
608
 
 
609
 
  return collector;
610
 
}
611
 
 
612
 
/**
613
 
 * hud_dbusmenu_collector_new_for_window:
614
 
 * @window: a #BamfWindow
615
 
 *
616
 
 * Creates a new #HudDbusmenuCollector for the endpoint indicated by the
617
 
 * #HudAppMenuRegistrar for @window.
618
 
 *
619
 
 * This call is intended to be used for application menus.
620
 
 *
621
 
 * Returns: a new #HudDbusmenuCollector
622
 
 **/
623
 
HudDbusmenuCollector *
624
 
hud_dbusmenu_collector_new_for_window (BamfWindow  *window,
625
 
                                       const gchar *desktop_file,
626
 
                                       const gchar *icon)
627
 
{
628
 
  HudDbusmenuCollector *collector;
629
 
 
630
 
  collector = g_object_new (HUD_TYPE_DBUSMENU_COLLECTOR, NULL);
631
 
  collector->application_id = g_strdup (desktop_file);
632
 
  collector->icon = g_strdup (icon);
633
 
  collector->xid = bamf_window_get_xid (window);
634
 
  g_debug ("dbusmenu on %d", collector->xid);
635
 
  hud_app_menu_registrar_add_observer (hud_app_menu_registrar_get (), collector->xid,
636
 
                                       hud_dbusmenu_collector_registrar_observer_func, collector);
637
 
 
638
 
  collector->alive = TRUE;
639
 
 
640
 
  return collector;
641
 
}
642
 
 
643
 
/**
644
 
 * hud_dbusmenu_collector_set_prefix:
645
 
 * @collector: a #HudDbusmenuCollector
646
 
 * @prefix: the new prefix to use
647
 
 *
648
 
 * Changes the prefix applied to all items of the collector.
649
 
 *
650
 
 * This will involve destroying all of the items and recreating them
651
 
 * (since each item's prefix has to be changed).
652
 
 **/
653
 
void
654
 
hud_dbusmenu_collector_set_prefix (HudDbusmenuCollector *collector,
655
 
                                   const gchar          *prefix)
656
 
{
657
 
  hud_string_list_unref (collector->prefix);
658
 
  collector->prefix = hud_string_list_cons (prefix, NULL);
659
 
  hud_dbusmenu_collector_setup_root (collector, collector->root);
660
 
}
661
 
 
662
 
/**
663
 
 * hud_dbusmenu_collector_set_icon:
664
 
 * @collector: a #HudDbusmenuCollector
665
 
 * @icon: the application icon
666
 
 *
667
 
 * Changes the application icon used for all items of the collector.
668
 
 *
669
 
 * This will involve destroying all of the items and recreating them
670
 
 * (since each item's icon has to be changed).
671
 
 **/
672
 
void
673
 
hud_dbusmenu_collector_set_icon (HudDbusmenuCollector *collector,
674
 
                                 const gchar          *icon)
675
 
{
676
 
  g_free (collector->icon);
677
 
  collector->icon = g_strdup (icon);
678
 
  hud_dbusmenu_collector_setup_root (collector, collector->root);
679
 
}