~golfish/netbook-remix-launcher/desktop

« back to all changes in this revision

Viewing changes to src/launcher-menu.c

  • Committer: Neil J. Patel
  • Date: 2008-04-16 11:31:15 UTC
  • Revision ID: njpatel@gmail.com-20080416113115-ztljg0qms79anijd
* Inital import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2007 Intel
 
3
 * Copyright (C) 2008 Canonical Ltd
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public
 
16
 * License along with this library; if not, write to the
 
17
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
 * Boston, MA 02111-1307, USA.
 
19
 *
 
20
 * Authored by Neil Jagdish Patel <njp@o-hand.com>
 
21
 *             Neil Jagdish Patel <neil.patel@canonical.com>
 
22
 *
 
23
 */
 
24
 
 
25
#include <glib.h>
 
26
 
 
27
#include <stdio.h>
 
28
#include <string.h>
 
29
 
 
30
#define GMENU_I_KNOW_THIS_IS_UNSTABLE 1
 
31
#include <gmenu-tree.h>
 
32
 
 
33
#include <libwnck/window.h>
 
34
 
 
35
#include <clutter/clutter.h>
 
36
 
 
37
#include "launcher-defines.h"
 
38
#include "launcher-menu.h"
 
39
 
 
40
G_DEFINE_TYPE (LauncherMenu, launcher_menu, G_TYPE_OBJECT)
 
41
 
 
42
#define LAUNCHER_MENU_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE(obj, \
 
43
        LAUNCHER_TYPE_MENU, LauncherMenuPrivate))
 
44
 
 
45
struct _LauncherMenuPrivate
 
46
{
 
47
  GList      *categories;
 
48
  GList      *menu_apps;
 
49
  GMenuTree *app_tree;
 
50
  GMenuTree *sys_tree;
 
51
 
 
52
  guint      tag;
 
53
 
 
54
  gboolean   refresh;
 
55
  GList     *old_cats;
 
56
  GList     *old_apps;
 
57
};
 
58
 
 
59
struct _LauncherMenuCategory
 
60
{
 
61
  GList *applications;
 
62
  GdkPixbuf *pixbuf;
 
63
 
 
64
  gchar *name;
 
65
  gchar *comment;
 
66
  gchar *icon;
 
67
};
 
68
 
 
69
struct _LauncherMenuApplication
 
70
{
 
71
  LauncherMenuCategory *category;
 
72
  GdkPixbuf *pixbuf;
 
73
  ClutterActor *actor;
 
74
 
 
75
  gchar *name;
 
76
  gchar *comment;
 
77
  gchar *icon;
 
78
  gchar *exec;
 
79
  gchar *path;
 
80
 
 
81
  WnckWindow *window;
 
82
  gint pid;
 
83
};
 
84
 
 
85
enum 
 
86
{
 
87
  MENU_CHANGED,
 
88
 
 
89
  LAST_SIGNAL
 
90
};
 
91
 
 
92
static guint _menu_signals[LAST_SIGNAL] = { 0 };
 
93
 
 
94
/* Forwards */
 
95
static void tree_changed (GMenuTree *tree, LauncherMenu *menu);
 
96
 
 
97
/* Utility functions */
 
98
 
 
99
/* From matchbox-desktop */
 
100
static char *
 
101
strip_extension (const char *file)
 
102
{
 
103
        char *stripped, *p;
 
104
 
 
105
        stripped = g_strdup (file);
 
106
 
 
107
        p = strrchr (stripped, '.');
 
108
        if (p &&
 
109
            (!strcmp (p, ".png") ||
 
110
             !strcmp (p, ".svg") ||
 
111
             !strcmp (p, ".xpm")))
 
112
                *p = 0;
 
113
 
 
114
        return stripped;
 
115
}
 
116
 
 
117
/* Gets the pixbuf from a desktop file's icon name. Based on the same function
 
118
 * from matchbox-desktop
 
119
 */
 
120
static GdkPixbuf *
 
121
get_icon (const gchar *name, guint size)
 
122
{
 
123
  static GtkIconTheme *theme = NULL;
 
124
  GdkPixbuf *pixbuf = NULL;
 
125
  GError *error = NULL;
 
126
  gchar *stripped = NULL;
 
127
 
 
128
  gint width, height;
 
129
 
 
130
  if (theme == NULL)
 
131
    theme = gtk_icon_theme_get_default ();
 
132
 
 
133
  if (name == NULL)
 
134
  {
 
135
    pixbuf = gtk_icon_theme_load_icon (theme, "application-x-executable",
 
136
                                       size, 0, NULL);
 
137
    return pixbuf;
 
138
  }
 
139
 
 
140
  if (g_path_is_absolute (name))
 
141
  {
 
142
    if (g_file_test (name, G_FILE_TEST_EXISTS))
 
143
    {
 
144
      pixbuf = gdk_pixbuf_new_from_file_at_scale (name, size, size, 
 
145
                                                  TRUE, &error);
 
146
      if (error)
 
147
      {
 
148
        /*g_warning ("Error loading icon: %s\n", error->message);*/
 
149
        g_error_free (error);
 
150
        error = NULL;
 
151
     }
 
152
      return pixbuf;
 
153
    } 
 
154
  }
 
155
 
 
156
  stripped = strip_extension (name);
 
157
  
 
158
  pixbuf = gtk_icon_theme_load_icon (theme,
 
159
                                     stripped,
 
160
                                     size,
 
161
                                     0, &error);
 
162
  if (error)
 
163
  {   
 
164
    /*g_warning ("Error loading icon: %s\n", error->message);*/
 
165
    g_error_free (error);
 
166
    error = NULL;
 
167
  }
 
168
  
 
169
  /* Always try and send back something */
 
170
  if (pixbuf == NULL)
 
171
    pixbuf = gtk_icon_theme_load_icon (theme, "application-x-executable",
 
172
                                       size, 0, NULL);
 
173
  
 
174
  width = gdk_pixbuf_get_width (pixbuf);
 
175
  height = gdk_pixbuf_get_height (pixbuf);
 
176
 
 
177
  if (width != size || height != size)
 
178
  {
 
179
    GdkPixbuf *temp = pixbuf;
 
180
    pixbuf = gdk_pixbuf_scale_simple (temp, 
 
181
                                      size,
 
182
                                      size,
 
183
                                      GDK_INTERP_HYPER);
 
184
    g_object_unref (temp);
 
185
  }
 
186
 
 
187
  g_free (stripped);
 
188
 
 
189
 return pixbuf;
 
190
}
 
191
 
 
192
/* Public functions */
 
193
GList*
 
194
launcher_menu_get_categories (LauncherMenu *menu)
 
195
{
 
196
  g_return_val_if_fail (LAUNCHER_IS_MENU (menu), NULL);
 
197
  return menu->priv->categories;
 
198
}
 
199
 
 
200
GList*
 
201
launcher_menu_get_applications (LauncherMenu *menu)
 
202
{
 
203
  g_return_val_if_fail (LAUNCHER_IS_MENU (menu), NULL);
 
204
  return menu->priv->menu_apps;
 
205
}
 
206
 
 
207
const gchar *
 
208
launcher_menu_category_get_name (LauncherMenuCategory *category)
 
209
{
 
210
  g_return_val_if_fail (category, NULL);
 
211
 
 
212
  return category->name;
 
213
}
 
214
 
 
215
const gchar *
 
216
launcher_menu_category_get_comment (LauncherMenuCategory *category)
 
217
{
 
218
  g_return_val_if_fail (category, NULL);
 
219
 
 
220
  return category->comment;
 
221
}
 
222
 
 
223
GdkPixbuf*
 
224
launcher_menu_category_get_icon (LauncherMenuCategory *category)
 
225
{
 
226
  g_return_val_if_fail (category, NULL);
 
227
 
 
228
  return launcher_menu_category_get_pixbuf (category, CAT_ICON_SIZE);
 
229
}
 
230
 
 
231
GList*
 
232
launcher_menu_category_get_applications (LauncherMenuCategory *category)
 
233
{
 
234
  g_return_val_if_fail (category, NULL);
 
235
 
 
236
  return category->applications;
 
237
 
 
238
}
 
239
 
 
240
GdkPixbuf *
 
241
launcher_menu_category_get_pixbuf (LauncherMenuCategory *category,
 
242
                                   guint                 size)
 
243
{
 
244
  const gchar *name;
 
245
 
 
246
  g_return_val_if_fail (category, NULL);
 
247
 
 
248
  name = category->icon;
 
249
 
 
250
  if (!GDK_IS_PIXBUF (category->pixbuf))
 
251
    category->pixbuf = get_icon (name, CAT_ICON_SIZE);
 
252
 
 
253
  return category->pixbuf;
 
254
}
 
255
  
 
256
const gchar *
 
257
launcher_menu_application_get_name (LauncherMenuApplication *application)
 
258
{
 
259
  g_return_val_if_fail (application, NULL);
 
260
 
 
261
  return application->name;
 
262
}
 
263
 
 
264
 
 
265
const gchar *
 
266
launcher_menu_application_get_comment (LauncherMenuApplication *application)
 
267
{
 
268
  g_return_val_if_fail (application, NULL);
 
269
 
 
270
  return application->comment;
 
271
}
 
272
 
 
273
GdkPixbuf*
 
274
launcher_menu_application_get_icon (LauncherMenuApplication *application)
 
275
{
 
276
  g_return_val_if_fail (application, NULL);
 
277
 
 
278
  if (application->pixbuf)
 
279
    return application->pixbuf;
 
280
 
 
281
  return launcher_menu_application_get_pixbuf (application, APP_ICON_SIZE);
 
282
}
 
283
 
 
284
LauncherMenuCategory*
 
285
launcher_menu_application_get_category (LauncherMenuApplication *application)
 
286
{
 
287
  g_return_val_if_fail (application, NULL);
 
288
 
 
289
  return application->category;
 
290
}
 
291
 
 
292
GdkPixbuf *
 
293
launcher_menu_application_get_pixbuf (LauncherMenuApplication *application,
 
294
                                      guint                    size)
 
295
{
 
296
  const gchar *name;
 
297
 
 
298
  g_return_val_if_fail (application, NULL);
 
299
 
 
300
  name = application->icon;
 
301
 
 
302
  if (!GDK_IS_PIXBUF (application->pixbuf))
 
303
    application->pixbuf = get_icon (name, APP_ICON_SIZE);
 
304
 
 
305
  return application->pixbuf;
 
306
}
 
307
 
 
308
ClutterActor *
 
309
launcher_menu_application_get_actor (LauncherMenuApplication *application)
 
310
{
 
311
  g_return_val_if_fail (application, NULL);
 
312
 
 
313
  /*FIXME: */
 
314
  //application->actor = launcher_item_app_new (application);
 
315
 
 
316
  return application->actor;
 
317
}
 
318
 
 
319
const gchar*
 
320
launcher_menu_application_get_exec (LauncherMenuApplication *application)
 
321
{
 
322
  g_return_val_if_fail (application, NULL);
 
323
 
 
324
  return application->exec;
 
325
}
 
326
 
 
327
const gchar *
 
328
launcher_menu_application_get_desktop_filename (LauncherMenuApplication *application)
 
329
{
 
330
  g_return_val_if_fail (application, NULL);
 
331
 
 
332
  return application->path;
 
333
}
 
334
 
 
335
gint
 
336
launcher_menu_application_get_pid (LauncherMenuApplication *application)
 
337
{
 
338
  g_return_val_if_fail (application, -1);
 
339
 
 
340
  return application->pid;
 
341
}
 
342
 
 
343
void
 
344
launcher_menu_application_set_pid (LauncherMenuApplication *application,  
 
345
                                   gint                     pid)
 
346
{
 
347
  g_return_if_fail (application);
 
348
 
 
349
  application->pid = pid;
 
350
}
 
351
 
 
352
WnckWindow *
 
353
launcher_menu_application_get_window (LauncherMenuApplication *application)
 
354
{
 
355
  g_return_val_if_fail (application, NULL);
 
356
 
 
357
  return application->window;
 
358
}
 
359
 
 
360
void
 
361
launcher_menu_application_set_window (LauncherMenuApplication *application,
 
362
                                      WnckWindow              *window)
 
363
{
 
364
  g_return_if_fail (application);
 
365
 
 
366
  application->window = window;
 
367
}
 
368
 
 
369
/* Private */
 
370
 
 
371
static LauncherMenuCategory*
 
372
make_category (LauncherMenu *menu, GMenuTreeDirectory *dir)
 
373
{
 
374
  LauncherMenuPrivate *priv = menu->priv;
 
375
  LauncherMenuCategory *category = NULL;
 
376
 
 
377
  /* if we are refreshing, try searching for the category */
 
378
  if (priv->refresh)
 
379
  {
 
380
    GList *l;
 
381
    const gchar *name = gmenu_tree_directory_get_name (dir);
 
382
    for (l = priv->old_cats; l; l = l->next)
 
383
    {
 
384
      LauncherMenuCategory *cat = l->data;
 
385
      if (strcmp (name, cat->name) == 0)
 
386
      {
 
387
        category = cat;
 
388
        break;
 
389
      }
 
390
    }
 
391
    if (category)
 
392
    {
 
393
      g_list_free (category->applications);
 
394
      category->applications = NULL;
 
395
      priv->categories = g_list_append (priv->categories, (gpointer)category);
 
396
 
 
397
      priv->old_cats = g_list_remove (priv->old_cats, category);
 
398
      return category;
 
399
    }
 
400
  }
 
401
 
 
402
  category = g_slice_new0 (LauncherMenuCategory);
 
403
  category->name = g_strdup (gmenu_tree_directory_get_name (dir));
 
404
  category->comment = g_strdup (gmenu_tree_directory_get_comment (dir));
 
405
  category->icon = g_strdup (gmenu_tree_directory_get_icon (dir));
 
406
  category->applications = NULL;
 
407
 
 
408
  priv->categories = g_list_append (priv->categories, (gpointer)category);
 
409
 
 
410
  g_print ("+%s\n", category->name);
 
411
 
 
412
  return category;
 
413
 
414
 
 
415
/*
 
416
 * Each application has a pointer to its category, and gets added to the 
 
417
 * categories application list and the main applicaton list 
 
418
 */
 
419
static void
 
420
make_application (LauncherMenu *menu, 
 
421
                  GMenuTreeEntry *entry, 
 
422
                  LauncherMenuCategory *category)
 
423
{
 
424
  LauncherMenuPrivate *priv = menu->priv;
 
425
  LauncherMenuApplication *app = NULL;
 
426
 
 
427
  /* if we are refreshing, try searching for the category */
 
428
  if (priv->refresh)
 
429
  {
 
430
    GList *a;
 
431
    const gchar *name = gmenu_tree_entry_get_name (entry);
 
432
 
 
433
    LauncherMenuApplication *application;
 
434
    for (a = priv->old_apps; a; a = a->next)
 
435
    {
 
436
      application = a->data;
 
437
      if (strcmp (name, application->name) == 0)
 
438
      {
 
439
        app = application;
 
440
        break;
 
441
      }
 
442
    }
 
443
    if (app)
 
444
    {
 
445
      app->category = category;
 
446
      category->applications = g_list_append (category->applications, app);
 
447
      priv->menu_apps = g_list_append (priv->menu_apps, app);
 
448
 
 
449
      priv->old_apps = g_list_remove (priv->old_apps, app);
 
450
      return;
 
451
    }    
 
452
  }
 
453
    
 
454
 
 
455
  app = g_slice_new0 (LauncherMenuApplication);
 
456
  app->name = g_strdup (gmenu_tree_entry_get_name (entry));
 
457
  app->comment = g_strdup (gmenu_tree_entry_get_comment (entry));
 
458
  app->icon = g_strdup (gmenu_tree_entry_get_icon (entry));
 
459
  app->exec = g_strdup (gmenu_tree_entry_get_exec (entry));
 
460
  app->path = g_strdup (gmenu_tree_entry_get_desktop_file_path (entry));
 
461
  app->category = category;
 
462
  app->pid = -1;
 
463
  app->window = NULL;
 
464
 
 
465
  category->applications = g_list_append (category->applications,
 
466
                                          (gpointer)app);
 
467
  priv->menu_apps = g_list_append (priv->menu_apps, (gpointer)app);
 
468
 
 
469
  g_print ("\t-%s\n", app->name);
 
470
 
471
 
 
472
/* 
 
473
 * Traverse through the root tree, treating each directory as a category, and
 
474
 * each entry as an application. We only want 1st tier categories, so we pass
 
475
 * a 'category' variable to the function, which, if present, blocks the
 
476
 * 2nd tier directory from becoming a new category, and uses it's parent as the
 
477
 * category.
 
478
 */
 
479
static void
 
480
load_menu_from_directory (LauncherMenu *menu, 
 
481
                          GMenuTreeDirectory *dir,
 
482
                          LauncherMenuCategory *category)
 
483
{
 
484
  GSList *list, *l;
 
485
  LauncherMenuCategory *root = NULL;
 
486
 
 
487
  if (dir == NULL)
 
488
    return;
 
489
 
 
490
  list = gmenu_tree_directory_get_contents (dir);
 
491
  for (l = list; l; l = l->next)
 
492
  {
 
493
    GMenuTreeItem *item = (GMenuTreeItem*)l->data;
 
494
 
 
495
    switch (gmenu_tree_item_get_type (item))
 
496
    {
 
497
      case GMENU_TREE_ITEM_DIRECTORY:
 
498
        
 
499
        if (!category)
 
500
        {
 
501
          load_menu_from_directory (menu, 
 
502
                                   GMENU_TREE_DIRECTORY (item),
 
503
                                   make_category (menu,
 
504
                                                  GMENU_TREE_DIRECTORY (item)));
 
505
 
 
506
        }
 
507
        else
 
508
          load_menu_from_directory (menu, 
 
509
                                    GMENU_TREE_DIRECTORY (item), category);
 
510
        break;
 
511
      case GMENU_TREE_ITEM_ENTRY:
 
512
        if (category)
 
513
          make_application (menu, GMENU_TREE_ENTRY (item), category);
 
514
        else
 
515
        {
 
516
          if (root == NULL)
 
517
            root = make_category (menu, dir);
 
518
          make_application (menu, GMENU_TREE_ENTRY (item), root);        
 
519
        }
 
520
 
 
521
        break;
 
522
        
 
523
      default:
 
524
        break;
 
525
    }
 
526
    gmenu_tree_item_unref (item);
 
527
  }  
 
528
  g_slist_free (list);
 
529
}
 
530
 
 
531
static GMenuTree *
 
532
load_menu_from_tree (LauncherMenu *menu, const gchar *name)
 
533
{
 
534
  LauncherMenuPrivate *priv;
 
535
  GMenuTreeDirectory *root = NULL;
 
536
  GMenuTree *tree = NULL;
 
537
 
 
538
  g_return_val_if_fail (LAUNCHER_IS_MENU (menu), NULL);
 
539
  priv = menu->priv;
 
540
 
 
541
  tree = gmenu_tree_lookup (name, GMENU_TREE_FLAGS_NONE);
 
542
  if (!tree)
 
543
  {
 
544
    g_warning ("Unable to find %s", name);
 
545
    return NULL;
 
546
  }
 
547
  root = gmenu_tree_get_root_directory (tree);
 
548
  load_menu_from_directory (menu, root, NULL); 
 
549
  gmenu_tree_item_unref (root);
 
550
 
 
551
  gmenu_tree_add_monitor (tree, (GMenuTreeChangedFunc)tree_changed, menu);
 
552
 
 
553
  return tree;
 
554
}
 
555
 
 
556
static gboolean
 
557
_poor_mans_garbage_collection (GList *pixbufs)
 
558
{
 
559
  GList *p;
 
560
 
 
561
  for (p = pixbufs; p; p = p->next)
 
562
  {
 
563
    while (G_IS_OBJECT (p->data))
 
564
    {
 
565
      g_debug ("PMGC: Swept one up");
 
566
      g_object_unref (p->data);
 
567
    }
 
568
  }
 
569
  g_list_free (pixbufs);
 
570
 
 
571
  return FALSE;
 
572
}
 
573
 
 
574
static void
 
575
free_menu (LauncherMenu *menu)
 
576
{
 
577
  LauncherMenuPrivate *priv;
 
578
  GList *l;
 
579
  GList *pixbufs = NULL;
 
580
 
 
581
  g_return_if_fail (LAUNCHER_IS_MENU (menu));
 
582
  priv = menu->priv;
 
583
 
 
584
  for (l = priv->old_apps; l; l = l->next)
 
585
  {
 
586
    LauncherMenuApplication *app = l->data;
 
587
    
 
588
    g_free (app->name);
 
589
    g_free (app->comment);
 
590
    g_free (app->icon);
 
591
    g_free (app->exec);
 
592
    g_free (app->path);
 
593
    
 
594
    if (G_IS_OBJECT (app->pixbuf))
 
595
    {
 
596
      if (G_OBJECT (app->pixbuf)->ref_count >1)
 
597
        g_object_unref (app->pixbuf);
 
598
      else
 
599
        pixbufs = g_list_append (pixbufs, app->pixbuf);
 
600
    }
 
601
    g_slice_free (LauncherMenuApplication, app);
 
602
    app = NULL;
 
603
  }
 
604
  g_list_free (priv->old_apps);
 
605
  priv->old_apps = NULL;
 
606
 
 
607
  for (l = priv->old_cats; l; l = l->next)
 
608
  {
 
609
    LauncherMenuCategory *cat = l->data;
 
610
    
 
611
    g_free (cat->name);
 
612
    g_free (cat->comment);
 
613
    g_free (cat->icon);
 
614
    g_list_free (cat->applications);
 
615
 
 
616
    if (G_IS_OBJECT (cat->pixbuf))
 
617
    {
 
618
      if (G_OBJECT (cat->pixbuf)->ref_count >1)
 
619
        g_object_unref (cat->pixbuf);
 
620
      else
 
621
        pixbufs = g_list_append (pixbufs, cat->pixbuf);
 
622
    }
 
623
    g_slice_free (LauncherMenuCategory, cat);
 
624
    cat = NULL;
 
625
  }
 
626
  g_list_free (priv->old_cats);
 
627
  priv->old_cats = NULL;
 
628
 
 
629
  g_timeout_add (1000, (GSourceFunc)_poor_mans_garbage_collection, pixbufs);
 
630
}
 
631
 
 
632
static gboolean
 
633
list_changed (LauncherMenu *menu)
 
634
{
 
635
  LauncherMenuPrivate *priv;
 
636
  GMenuTreeDirectory *root;
 
637
  
 
638
  g_return_val_if_fail (LAUNCHER_IS_MENU (menu), FALSE);
 
639
  priv = menu->priv;
 
640
 
 
641
  g_debug ("menu changed\n");
 
642
 
 
643
  priv->old_cats = priv->categories;
 
644
  priv->old_apps = priv->menu_apps;
 
645
  priv->categories = priv->menu_apps = NULL;
 
646
 
 
647
  priv->refresh = TRUE;
 
648
 
 
649
  root = gmenu_tree_get_root_directory (priv->app_tree);
 
650
  load_menu_from_directory (menu, root, NULL);
 
651
  gmenu_tree_item_unref (root);
 
652
 
 
653
  priv->refresh = FALSE;
 
654
 
 
655
  free_menu (menu);
 
656
 
 
657
  /*
 
658
  root = gmenu_tree_get_root_directory (priv->sys_tree);
 
659
  load_menu_from_directory (menu, root, NULL);
 
660
  gmenu_tree_item_unref (root);
 
661
  */
 
662
  g_signal_emit (menu, _menu_signals[MENU_CHANGED], 0);
 
663
  menu->priv->tag = 0;  
 
664
  
 
665
  return FALSE;
 
666
}
 
667
 
 
668
/*
 
669
 * FIXME: The tree changing should not be destructive. Find a way to make it
 
670
 * work without re-creating the entire menu again.
 
671
 */
 
672
static void
 
673
tree_changed (GMenuTree *tree, LauncherMenu *menu)
 
674
{
 
675
  LauncherMenuPrivate *priv;
 
676
  GMenuTreeDirectory *root;
 
677
  
 
678
  g_return_if_fail (LAUNCHER_IS_MENU (menu));
 
679
  priv = menu->priv;
 
680
 
 
681
  root = gmenu_tree_get_root_directory (tree);
 
682
  gmenu_tree_item_unref (root);  
 
683
  
 
684
  if (priv->tag)
 
685
  {
 
686
    return;
 
687
  }
 
688
  priv->tag = g_timeout_add (500, (GSourceFunc)list_changed, menu);
 
689
}
 
690
 
 
691
static void
 
692
on_theme_changed (GtkIconTheme *theme, LauncherMenu *menu)
 
693
{
 
694
  LauncherMenuPrivate *priv;
 
695
  GMenuTreeDirectory *root;
 
696
  
 
697
  g_return_if_fail (LAUNCHER_IS_MENU (menu));
 
698
  priv = menu->priv;
 
699
 
 
700
  root = gmenu_tree_get_root_directory (priv->app_tree);
 
701
  gmenu_tree_item_unref (root);  
 
702
  
 
703
  if (priv->tag)
 
704
  {
 
705
    return;
 
706
  }
 
707
  priv->tag = g_timeout_add (500, (GSourceFunc)list_changed, menu);
 
708
}
 
709
 
 
710
/* GObject functions */
 
711
static void
 
712
launcher_menu_dispose (GObject *object)
 
713
{
 
714
  free_menu (LAUNCHER_MENU (object));
 
715
 
 
716
  G_OBJECT_CLASS (launcher_menu_parent_class)->dispose (object);
 
717
}
 
718
 
 
719
static void
 
720
launcher_menu_finalize (GObject *menu)
 
721
{
 
722
  LauncherMenuPrivate *priv;
 
723
  
 
724
  g_return_if_fail (LAUNCHER_IS_MENU (menu));
 
725
  priv = LAUNCHER_MENU (menu)->priv;
 
726
 
 
727
  G_OBJECT_CLASS (launcher_menu_parent_class)->finalize (menu);
 
728
}
 
729
 
 
730
 
 
731
static void
 
732
launcher_menu_class_init (LauncherMenuClass *klass)
 
733
{
 
734
  GObjectClass *obj_class = G_OBJECT_CLASS (klass);
 
735
 
 
736
  obj_class->finalize = launcher_menu_finalize;
 
737
  obj_class->dispose = launcher_menu_dispose;
 
738
 
 
739
   _menu_signals[MENU_CHANGED] = 
 
740
      g_signal_new ("menu-changed",
 
741
                  G_OBJECT_CLASS_TYPE (obj_class),
 
742
                  G_SIGNAL_RUN_LAST,
 
743
                  G_STRUCT_OFFSET (LauncherMenuClass, menu_changed),
 
744
                  NULL, NULL,
 
745
                  g_cclosure_marshal_VOID__VOID,
 
746
                  G_TYPE_NONE, 0);
 
747
 
 
748
 
 
749
  g_type_class_add_private (obj_class, sizeof (LauncherMenuPrivate)); 
 
750
}
 
751
 
 
752
static void
 
753
launcher_menu_init (LauncherMenu *menu)
 
754
{
 
755
  LauncherMenuPrivate *priv;
 
756
  GtkIconTheme *theme;
 
757
    
 
758
  priv = menu->priv = LAUNCHER_MENU_GET_PRIVATE (menu);
 
759
 
 
760
  priv->categories = NULL;
 
761
  priv->menu_apps = NULL;
 
762
  priv->tag = 0;
 
763
  priv->refresh = FALSE;
 
764
 
 
765
  /*priv->app_tree = load_menu_from_tree (menu, "applications.menu");*/
 
766
  /*priv->sys_tree = load_menu_from_tree (menu, "settings.menu");*/
 
767
  priv->app_tree = load_menu_from_tree (menu, PKGDATADIR"/applications.menu");
 
768
 
 
769
  /* React to theme-changed signals */
 
770
  theme = gtk_icon_theme_get_default ();
 
771
  g_signal_connect (theme, "changed",
 
772
                    G_CALLBACK (on_theme_changed), menu);
 
773
}
 
774
 
 
775
LauncherMenu*
 
776
launcher_menu_get_default (void)
 
777
{
 
778
  static LauncherMenu *menu = NULL;
 
779
  
 
780
  if (menu == NULL)
 
781
    menu = g_object_new (LAUNCHER_TYPE_MENU, 
 
782
                         NULL);
 
783
 
 
784
  return menu;
 
785
}