~ubuntu-branches/ubuntu/quantal/gnome-menus2/quantal

« back to all changes in this revision

Viewing changes to .pc/23_add_inherited_gnome_session.patch/libmenu/desktop-entries.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2011-08-26 11:43:02 UTC
  • Revision ID: james.westby@ubuntu.com-20110826114302-vgdcyicgxh3xzyzn
Tags: 3.0.1-0ubuntu6
Restore old gnome-menus, the lib still has some rdepends

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2002 - 2004 Red Hat, Inc.
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Lesser General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Lesser General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Lesser General Public
 
15
 * License along with this library; if not, write to the
 
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 */
 
19
 
 
20
#include <config.h>
 
21
 
 
22
#include "desktop-entries.h"
 
23
 
 
24
#include <string.h>
 
25
 
 
26
#include "menu-util.h"
 
27
 
 
28
#define DESKTOP_ENTRY_GROUP     "Desktop Entry"
 
29
#define KDE_DESKTOP_ENTRY_GROUP "KDE Desktop Entry"
 
30
 
 
31
enum
 
32
{
 
33
  DESKTOP_ENTRY_NO_DISPLAY     = 1 << 0,
 
34
  DESKTOP_ENTRY_HIDDEN         = 1 << 1,
 
35
  DESKTOP_ENTRY_SHOW_IN_GNOME  = 1 << 2,
 
36
  DESKTOP_ENTRY_TRYEXEC_FAILED = 1 << 3
 
37
};
 
38
 
 
39
struct DesktopEntry
 
40
{
 
41
  char *path;
 
42
  char *basename;
 
43
 
 
44
  GQuark *categories;
 
45
 
 
46
  char     *name;
 
47
  char     *generic_name;
 
48
  char     *full_name;
 
49
  char     *comment;
 
50
  char     *icon;
 
51
  char     *exec;
 
52
  gboolean terminal;
 
53
 
 
54
  guint type : 2;
 
55
  guint flags : 4;
 
56
  guint refcount : 24;
 
57
};
 
58
 
 
59
struct DesktopEntrySet
 
60
{
 
61
  int         refcount;
 
62
  GHashTable *hash;
 
63
};
 
64
 
 
65
/*
 
66
 * Desktop entries
 
67
 */
 
68
 
 
69
static guint
 
70
get_flags_from_key_file (DesktopEntry *entry,
 
71
                         GKeyFile     *key_file,
 
72
                         const char   *desktop_entry_group)
 
73
{
 
74
  GError    *error;
 
75
  char     **strv;
 
76
  gboolean   no_display;
 
77
  gboolean   hidden;
 
78
  gboolean   show_in_gnome;
 
79
  gboolean   tryexec_failed;
 
80
  char      *tryexec;
 
81
  guint      flags;
 
82
  int        i;
 
83
 
 
84
  error = NULL;
 
85
  no_display = g_key_file_get_boolean (key_file,
 
86
                                       desktop_entry_group,
 
87
                                       "NoDisplay",
 
88
                                       &error);
 
89
  if (error)
 
90
    {
 
91
      no_display = FALSE;
 
92
      g_error_free (error);
 
93
    }
 
94
 
 
95
  error = NULL;
 
96
  hidden = g_key_file_get_boolean (key_file,
 
97
                                   desktop_entry_group,
 
98
                                   "Hidden",
 
99
                                   &error);
 
100
  if (error)
 
101
    {
 
102
      hidden = FALSE;
 
103
      g_error_free (error);
 
104
    }
 
105
 
 
106
  show_in_gnome = TRUE;
 
107
  strv = g_key_file_get_string_list (key_file,
 
108
                                     desktop_entry_group,
 
109
                                     "OnlyShowIn",
 
110
                                     NULL,
 
111
                                     NULL);
 
112
  if (strv)
 
113
    {
 
114
      show_in_gnome = FALSE;
 
115
      for (i = 0; strv[i]; i++)
 
116
        {
 
117
          if (!strcmp (strv[i], "GNOME"))
 
118
            {
 
119
              show_in_gnome = TRUE;
 
120
              break;
 
121
            }
 
122
        }
 
123
    }
 
124
  else
 
125
    {
 
126
      strv = g_key_file_get_string_list (key_file,
 
127
                                         desktop_entry_group,
 
128
                                         "NotShowIn",
 
129
                                         NULL,
 
130
                                         NULL);
 
131
      if (strv)
 
132
        {
 
133
          show_in_gnome = TRUE;
 
134
          for (i = 0; strv[i]; i++)
 
135
            {
 
136
              if (!strcmp (strv[i], "GNOME"))
 
137
                {
 
138
                  show_in_gnome = FALSE;
 
139
                }
 
140
            }
 
141
        }
 
142
    }
 
143
  g_strfreev (strv);
 
144
 
 
145
  tryexec_failed = FALSE;
 
146
  tryexec = g_key_file_get_string (key_file,
 
147
                                   desktop_entry_group,
 
148
                                   "TryExec",
 
149
                                   NULL);
 
150
  if (tryexec)
 
151
    {
 
152
      char *path;
 
153
 
 
154
      path = g_find_program_in_path (g_strstrip (tryexec));
 
155
 
 
156
      tryexec_failed = (path == NULL);
 
157
 
 
158
      g_free (path);
 
159
      g_free (tryexec);
 
160
    }
 
161
 
 
162
  flags = 0;
 
163
  if (no_display)
 
164
    flags |= DESKTOP_ENTRY_NO_DISPLAY;
 
165
  if (hidden)
 
166
    flags |= DESKTOP_ENTRY_HIDDEN;
 
167
  if (show_in_gnome)
 
168
    flags |= DESKTOP_ENTRY_SHOW_IN_GNOME;
 
169
  if (tryexec_failed)
 
170
    flags |= DESKTOP_ENTRY_TRYEXEC_FAILED;
 
171
 
 
172
  return flags;
 
173
}
 
174
 
 
175
static GQuark *
 
176
get_categories_from_key_file (DesktopEntry *entry,
 
177
                              GKeyFile     *key_file,
 
178
                              const char   *desktop_entry_group)
 
179
{
 
180
  GQuark  *retval;
 
181
  char   **strv;
 
182
  gsize    len;
 
183
  int      i;
 
184
 
 
185
  strv = g_key_file_get_string_list (key_file,
 
186
                                     desktop_entry_group,
 
187
                                     "Categories",
 
188
                                     &len,
 
189
                                     NULL);
 
190
  if (!strv)
 
191
    return NULL;
 
192
 
 
193
  retval = g_new0 (GQuark, len + 1);
 
194
 
 
195
  for (i = 0; strv[i]; i++)
 
196
    retval[i] = g_quark_from_string (strv[i]);
 
197
 
 
198
  g_strfreev (strv);
 
199
 
 
200
  return retval;
 
201
}
 
202
 
 
203
static DesktopEntry *
 
204
desktop_entry_load (DesktopEntry *entry)
 
205
{
 
206
  DesktopEntry *retval = NULL;
 
207
  GKeyFile     *key_file;
 
208
  GError       *error;
 
209
  const char   *desktop_entry_group;
 
210
  char         *name_str;
 
211
  char         *type_str;
 
212
 
 
213
  key_file = g_key_file_new ();
 
214
 
 
215
  error = NULL;
 
216
  if (!g_key_file_load_from_file (key_file, entry->path, 0, &error))
 
217
    {
 
218
      menu_verbose ("Failed to load \"%s\": %s\n",
 
219
                    entry->path, error->message);
 
220
      g_error_free (error);
 
221
      goto out;
 
222
    }
 
223
 
 
224
  if (g_key_file_has_group (key_file, DESKTOP_ENTRY_GROUP))
 
225
    {
 
226
      desktop_entry_group = DESKTOP_ENTRY_GROUP;
 
227
    }
 
228
  else
 
229
    {
 
230
      menu_verbose ("\"%s\" contains no \"" DESKTOP_ENTRY_GROUP "\" group\n",
 
231
                    entry->path);
 
232
 
 
233
      if (g_key_file_has_group (key_file, KDE_DESKTOP_ENTRY_GROUP))
 
234
        {
 
235
          desktop_entry_group = KDE_DESKTOP_ENTRY_GROUP;
 
236
          menu_verbose ("\"%s\" contains deprecated \"" KDE_DESKTOP_ENTRY_GROUP "\" group\n",
 
237
                        entry->path);
 
238
        }
 
239
      else
 
240
        {
 
241
          goto out;
 
242
        }
 
243
    }
 
244
 
 
245
  if (!g_key_file_has_key (key_file, desktop_entry_group, "Name", NULL))
 
246
    {
 
247
      menu_verbose ("\"%s\" contains no \"Name\" key\n", entry->path);
 
248
      goto out;
 
249
    }
 
250
 
 
251
  name_str = g_key_file_get_locale_string (key_file, desktop_entry_group, "Name", NULL, NULL);
 
252
  if (!name_str)
 
253
    {
 
254
      menu_verbose ("\"%s\" contains an invalid \"Name\" key\n", entry->path);
 
255
      goto out;
 
256
    }
 
257
 
 
258
  g_free (name_str);
 
259
 
 
260
  type_str = g_key_file_get_string (key_file, desktop_entry_group, "Type", NULL);
 
261
  if (!type_str)
 
262
    {
 
263
      menu_verbose ("\"%s\" contains no \"Type\" key\n", entry->path);
 
264
      goto out;
 
265
    }
 
266
 
 
267
  if ((entry->type == DESKTOP_ENTRY_DESKTOP && strcmp (type_str, "Application") != 0) ||
 
268
      (entry->type == DESKTOP_ENTRY_DIRECTORY && strcmp (type_str, "Directory") != 0))
 
269
    {
 
270
      menu_verbose ("\"%s\" does not contain the correct \"Type\" value\n", entry->path);
 
271
      g_free (type_str);
 
272
      goto out;
 
273
    }
 
274
 
 
275
  g_free (type_str);
 
276
 
 
277
  if (entry->type == DESKTOP_ENTRY_DESKTOP &&
 
278
      !g_key_file_has_key (key_file, desktop_entry_group, "Exec", NULL))
 
279
    {
 
280
      menu_verbose ("\"%s\" does not contain an \"Exec\" key\n", entry->path);
 
281
      goto out;
 
282
    }
 
283
 
 
284
  retval = entry;
 
285
 
 
286
#define GET_LOCALE_STRING(n) g_key_file_get_locale_string (key_file, desktop_entry_group, (n), NULL, NULL)
 
287
 
 
288
  retval->name         = GET_LOCALE_STRING ("Name");
 
289
  retval->generic_name = GET_LOCALE_STRING ("GenericName");
 
290
  retval->full_name    = GET_LOCALE_STRING ("X-GNOME-FullName");
 
291
  retval->comment      = GET_LOCALE_STRING ("Comment");
 
292
  retval->icon         = GET_LOCALE_STRING ("Icon");
 
293
  retval->flags        = get_flags_from_key_file (retval, key_file, desktop_entry_group);
 
294
  retval->categories   = get_categories_from_key_file (retval, key_file, desktop_entry_group);
 
295
 
 
296
  if (entry->type == DESKTOP_ENTRY_DESKTOP)
 
297
    {
 
298
      retval->exec = g_key_file_get_string (key_file, desktop_entry_group, "Exec", NULL);
 
299
      retval->terminal = g_key_file_get_boolean (key_file, desktop_entry_group, "Terminal", NULL);
 
300
    }
 
301
  
 
302
#undef GET_LOCALE_STRING
 
303
 
 
304
  menu_verbose ("Desktop entry \"%s\" (%s, %s, %s, %s, %s) flags: NoDisplay=%s, Hidden=%s, ShowInGNOME=%s, TryExecFailed=%s\n",
 
305
                retval->basename,
 
306
                retval->name,
 
307
                retval->generic_name ? retval->generic_name : "(null)",
 
308
                retval->full_name ? retval->full_name : "(null)",
 
309
                retval->comment ? retval->comment : "(null)",
 
310
                retval->icon ? retval->icon : "(null)",
 
311
                retval->flags & DESKTOP_ENTRY_NO_DISPLAY     ? "(true)" : "(false)",
 
312
                retval->flags & DESKTOP_ENTRY_HIDDEN         ? "(true)" : "(false)",
 
313
                retval->flags & DESKTOP_ENTRY_SHOW_IN_GNOME  ? "(true)" : "(false)",
 
314
                retval->flags & DESKTOP_ENTRY_TRYEXEC_FAILED ? "(true)" : "(false)");
 
315
 
 
316
 out:
 
317
  g_key_file_free (key_file);
 
318
 
 
319
  if (!retval)
 
320
    desktop_entry_unref (entry);
 
321
 
 
322
  return retval;
 
323
}
 
324
 
 
325
DesktopEntry *
 
326
desktop_entry_new (const char *path)
 
327
{
 
328
  DesktopEntryType  type;
 
329
  DesktopEntry     *retval;
 
330
 
 
331
  menu_verbose ("Loading desktop entry \"%s\"\n", path);
 
332
 
 
333
  if (g_str_has_suffix (path, ".desktop"))
 
334
    {
 
335
      type = DESKTOP_ENTRY_DESKTOP;
 
336
    }
 
337
  else if (g_str_has_suffix (path, ".directory"))
 
338
    {
 
339
      type = DESKTOP_ENTRY_DIRECTORY;
 
340
    }
 
341
  else
 
342
    {
 
343
      menu_verbose ("Unknown desktop entry suffix in \"%s\"\n",
 
344
                    path);
 
345
      return NULL;
 
346
    }
 
347
 
 
348
  retval = g_new0 (DesktopEntry, 1);
 
349
 
 
350
  retval->refcount = 1;
 
351
  retval->type     = type;
 
352
  retval->basename = g_path_get_basename (path);
 
353
  retval->path     = g_strdup (path);
 
354
 
 
355
  return desktop_entry_load (retval);
 
356
}
 
357
 
 
358
DesktopEntry *
 
359
desktop_entry_reload (DesktopEntry *entry)
 
360
{
 
361
  g_return_val_if_fail (entry != NULL, NULL);
 
362
 
 
363
  menu_verbose ("Re-loading desktop entry \"%s\"\n", entry->path);
 
364
 
 
365
  g_free (entry->categories);
 
366
  entry->categories = NULL;
 
367
 
 
368
  g_free (entry->name);
 
369
  entry->name = NULL;
 
370
 
 
371
  g_free (entry->generic_name);
 
372
  entry->generic_name = NULL;
 
373
 
 
374
  g_free (entry->full_name);
 
375
  entry->full_name = NULL;
 
376
 
 
377
  g_free (entry->comment);
 
378
  entry->comment = NULL;
 
379
 
 
380
  g_free (entry->icon);
 
381
  entry->icon = NULL;
 
382
 
 
383
  g_free (entry->exec);
 
384
  entry->exec = NULL;
 
385
 
 
386
  entry->terminal = 0;
 
387
  entry->flags = 0;
 
388
 
 
389
  return desktop_entry_load (entry);
 
390
}
 
391
 
 
392
DesktopEntry *
 
393
desktop_entry_ref (DesktopEntry *entry)
 
394
{
 
395
  g_return_val_if_fail (entry != NULL, NULL);
 
396
  g_return_val_if_fail (entry->refcount > 0, NULL);
 
397
 
 
398
  entry->refcount += 1;
 
399
 
 
400
  return entry;
 
401
}
 
402
 
 
403
DesktopEntry *
 
404
desktop_entry_copy (DesktopEntry *entry)
 
405
{
 
406
  DesktopEntry *retval;
 
407
  int           i;
 
408
 
 
409
  menu_verbose ("Copying desktop entry \"%s\"\n",
 
410
                entry->basename);
 
411
 
 
412
  retval = g_new0 (DesktopEntry, 1);
 
413
 
 
414
  retval->refcount     = 1;
 
415
  retval->type         = entry->type;
 
416
  retval->basename     = g_strdup (entry->basename);
 
417
  retval->path         = g_strdup (entry->path);
 
418
  retval->name         = g_strdup (entry->name);
 
419
  retval->generic_name = g_strdup (entry->generic_name);
 
420
  retval->full_name    = g_strdup (entry->full_name);
 
421
  retval->comment      = g_strdup (entry->comment);
 
422
  retval->icon         = g_strdup (entry->icon);
 
423
  retval->exec         = g_strdup (entry->exec);
 
424
  retval->terminal     = entry->terminal;
 
425
  retval->flags        = entry->flags;
 
426
 
 
427
  i = 0;
 
428
  if (entry->categories != NULL)
 
429
    {
 
430
      for (; entry->categories[i]; i++);
 
431
    }
 
432
 
 
433
  retval->categories = g_new0 (GQuark, i + 1);
 
434
 
 
435
  i = 0;
 
436
  if (entry->categories != NULL)
 
437
    {
 
438
      for (; entry->categories[i]; i++)
 
439
        retval->categories[i] = entry->categories[i];
 
440
    }
 
441
 
 
442
  return retval;
 
443
}
 
444
 
 
445
void
 
446
desktop_entry_unref (DesktopEntry *entry)
 
447
{
 
448
  g_return_if_fail (entry != NULL);
 
449
  g_return_if_fail (entry->refcount > 0);
 
450
 
 
451
  entry->refcount -= 1;
 
452
  if (entry->refcount == 0)
 
453
    {
 
454
      g_free (entry->categories);
 
455
      entry->categories = NULL;
 
456
 
 
457
      g_free (entry->name);
 
458
      entry->name = NULL;
 
459
 
 
460
      g_free (entry->generic_name);
 
461
      entry->generic_name = NULL;
 
462
 
 
463
      g_free (entry->full_name);
 
464
      entry->full_name = NULL;
 
465
 
 
466
      g_free (entry->comment);
 
467
      entry->comment = NULL;
 
468
 
 
469
      g_free (entry->icon);
 
470
      entry->icon = NULL;
 
471
 
 
472
      g_free (entry->exec);
 
473
      entry->exec = NULL;
 
474
 
 
475
      g_free (entry->basename);
 
476
      entry->basename = NULL;
 
477
 
 
478
      g_free (entry->path);
 
479
      entry->path = NULL;
 
480
 
 
481
      g_free (entry);
 
482
    }
 
483
}
 
484
 
 
485
DesktopEntryType
 
486
desktop_entry_get_type (DesktopEntry *entry)
 
487
{
 
488
  return entry->type;
 
489
}
 
490
 
 
491
const char *
 
492
desktop_entry_get_path (DesktopEntry *entry)
 
493
{
 
494
  return entry->path;
 
495
}
 
496
 
 
497
const char *
 
498
desktop_entry_get_basename (DesktopEntry *entry)
 
499
{
 
500
  return entry->basename;
 
501
}
 
502
 
 
503
const char *
 
504
desktop_entry_get_name (DesktopEntry *entry)
 
505
{
 
506
  return entry->name;
 
507
}
 
508
 
 
509
const char *
 
510
desktop_entry_get_generic_name (DesktopEntry *entry)
 
511
{
 
512
  return entry->generic_name;
 
513
}
 
514
 
 
515
const char *
 
516
desktop_entry_get_full_name (DesktopEntry *entry)
 
517
{
 
518
  return entry->full_name;
 
519
}
 
520
 
 
521
const char *
 
522
desktop_entry_get_comment (DesktopEntry *entry)
 
523
{
 
524
  return entry->comment;
 
525
}
 
526
 
 
527
const char *
 
528
desktop_entry_get_icon (DesktopEntry *entry)
 
529
{
 
530
  return entry->icon;
 
531
}
 
532
 
 
533
const char *
 
534
desktop_entry_get_exec (DesktopEntry *entry)
 
535
{
 
536
  return entry->exec;
 
537
}
 
538
 
 
539
gboolean
 
540
desktop_entry_get_launch_in_terminal (DesktopEntry *entry)
 
541
{
 
542
  return entry->terminal;
 
543
}
 
544
 
 
545
gboolean
 
546
desktop_entry_get_hidden (DesktopEntry *entry)
 
547
{
 
548
  return (entry->flags & DESKTOP_ENTRY_HIDDEN) != 0;
 
549
}
 
550
 
 
551
gboolean
 
552
desktop_entry_get_no_display (DesktopEntry *entry)
 
553
{
 
554
  return (entry->flags & DESKTOP_ENTRY_NO_DISPLAY) != 0;
 
555
}
 
556
 
 
557
gboolean
 
558
desktop_entry_get_show_in_gnome (DesktopEntry *entry)
 
559
{
 
560
  return (entry->flags & DESKTOP_ENTRY_SHOW_IN_GNOME) != 0;
 
561
}
 
562
 
 
563
gboolean
 
564
desktop_entry_get_tryexec_failed (DesktopEntry *entry)
 
565
{
 
566
  return (entry->flags & DESKTOP_ENTRY_TRYEXEC_FAILED) != 0;
 
567
}
 
568
 
 
569
gboolean
 
570
desktop_entry_has_categories (DesktopEntry *entry)
 
571
{
 
572
  return (entry->categories != NULL && entry->categories[0] != 0);
 
573
}
 
574
 
 
575
gboolean
 
576
desktop_entry_has_category (DesktopEntry *entry,
 
577
                            const char   *category)
 
578
{
 
579
  GQuark quark;
 
580
  int    i;
 
581
 
 
582
  if (entry->categories == NULL)
 
583
    return FALSE;
 
584
 
 
585
  if (!(quark = g_quark_try_string (category)))
 
586
    return FALSE;
 
587
 
 
588
  for (i = 0; entry->categories[i]; i++)
 
589
    {
 
590
      if (quark == entry->categories[i])
 
591
        return TRUE;
 
592
    }
 
593
 
 
594
  return FALSE;
 
595
}
 
596
 
 
597
void
 
598
desktop_entry_add_legacy_category (DesktopEntry *entry)
 
599
{
 
600
  GQuark *categories;
 
601
  int     i;
 
602
 
 
603
  menu_verbose ("Adding Legacy category to \"%s\"\n",
 
604
                entry->basename);
 
605
 
 
606
  i = 0;
 
607
  if (entry->categories != NULL)
 
608
    {
 
609
      for (; entry->categories[i]; i++);
 
610
    }
 
611
 
 
612
  categories = g_new0 (GQuark, i + 2);
 
613
 
 
614
  i = 0;
 
615
  if (entry->categories != NULL)
 
616
    {
 
617
      for (; entry->categories[i]; i++)
 
618
        categories[i] = entry->categories[i];
 
619
    }
 
620
 
 
621
  categories[i] = g_quark_from_string ("Legacy");
 
622
 
 
623
  g_free (entry->categories);
 
624
  entry->categories = categories;
 
625
}
 
626
 
 
627
/*
 
628
 * Entry sets
 
629
 */
 
630
 
 
631
DesktopEntrySet *
 
632
desktop_entry_set_new (void)
 
633
{
 
634
  DesktopEntrySet *set;
 
635
 
 
636
  set = g_new0 (DesktopEntrySet, 1);
 
637
  set->refcount = 1;
 
638
 
 
639
  menu_verbose (" New entry set %p\n", set);
 
640
 
 
641
  return set;
 
642
}
 
643
 
 
644
DesktopEntrySet *
 
645
desktop_entry_set_ref (DesktopEntrySet *set)
 
646
{
 
647
  g_return_val_if_fail (set != NULL, NULL);
 
648
  g_return_val_if_fail (set->refcount > 0, NULL);
 
649
 
 
650
  set->refcount += 1;
 
651
 
 
652
  return set;
 
653
}
 
654
 
 
655
void
 
656
desktop_entry_set_unref (DesktopEntrySet *set)
 
657
{
 
658
  g_return_if_fail (set != NULL);
 
659
  g_return_if_fail (set->refcount > 0);
 
660
 
 
661
  set->refcount -= 1;
 
662
  if (set->refcount == 0)
 
663
    {
 
664
      menu_verbose (" Deleting entry set %p\n", set);
 
665
 
 
666
      if (set->hash)
 
667
        g_hash_table_destroy (set->hash);
 
668
      set->hash = NULL;
 
669
 
 
670
      g_free (set);
 
671
    }
 
672
}
 
673
 
 
674
void
 
675
desktop_entry_set_add_entry (DesktopEntrySet *set,
 
676
                             DesktopEntry    *entry,
 
677
                             const char      *file_id)
 
678
{
 
679
  menu_verbose (" Adding to set %p entry %s\n", set, file_id);
 
680
 
 
681
  if (set->hash == NULL)
 
682
    {
 
683
      set->hash = g_hash_table_new_full (g_str_hash,
 
684
                                         g_str_equal,
 
685
                                         g_free,
 
686
                                         (GDestroyNotify) desktop_entry_unref);
 
687
    }
 
688
 
 
689
  g_hash_table_replace (set->hash,
 
690
                        g_strdup (file_id),
 
691
                        desktop_entry_ref (entry));
 
692
}
 
693
 
 
694
DesktopEntry *
 
695
desktop_entry_set_lookup (DesktopEntrySet *set,
 
696
                          const char      *file_id)
 
697
{
 
698
  if (set->hash == NULL)
 
699
    return NULL;
 
700
 
 
701
  return g_hash_table_lookup (set->hash, file_id);
 
702
}
 
703
 
 
704
typedef struct
 
705
{
 
706
  DesktopEntrySetForeachFunc func;
 
707
  gpointer                   user_data;
 
708
} EntryHashForeachData;
 
709
 
 
710
static void
 
711
entry_hash_foreach (const char           *file_id,
 
712
                    DesktopEntry         *entry,
 
713
                    EntryHashForeachData *fd)
 
714
{
 
715
  fd->func (file_id, entry, fd->user_data);
 
716
}
 
717
 
 
718
void
 
719
desktop_entry_set_foreach (DesktopEntrySet            *set,
 
720
                           DesktopEntrySetForeachFunc  func,
 
721
                           gpointer                    user_data)
 
722
{
 
723
  g_return_if_fail (set != NULL);
 
724
  g_return_if_fail (func != NULL);
 
725
 
 
726
  if (set->hash != NULL)
 
727
    {
 
728
      EntryHashForeachData fd;
 
729
 
 
730
      fd.func      = func;
 
731
      fd.user_data = user_data;
 
732
 
 
733
      g_hash_table_foreach (set->hash,
 
734
                            (GHFunc) entry_hash_foreach,
 
735
                            &fd);
 
736
    }
 
737
}
 
738
 
 
739
static void
 
740
desktop_entry_set_clear (DesktopEntrySet *set)
 
741
{
 
742
  menu_verbose (" Clearing set %p\n", set);
 
743
 
 
744
  if (set->hash != NULL)
 
745
    {
 
746
      g_hash_table_destroy (set->hash);
 
747
      set->hash = NULL;
 
748
    }
 
749
}
 
750
 
 
751
int
 
752
desktop_entry_set_get_count (DesktopEntrySet *set)
 
753
{
 
754
  if (set->hash == NULL)
 
755
    return 0;
 
756
 
 
757
  return g_hash_table_size (set->hash);
 
758
}
 
759
 
 
760
static void
 
761
union_foreach (const char      *file_id,
 
762
               DesktopEntry    *entry,
 
763
               DesktopEntrySet *set)
 
764
{
 
765
  /* we are iterating over "with" adding anything not
 
766
   * already in "set". We unconditionally overwrite
 
767
   * the stuff in "set" because we can assume
 
768
   * two entries with the same name are equivalent.
 
769
   */
 
770
  desktop_entry_set_add_entry (set, entry, file_id);
 
771
}
 
772
 
 
773
void
 
774
desktop_entry_set_union (DesktopEntrySet *set,
 
775
                         DesktopEntrySet *with)
 
776
{
 
777
  menu_verbose (" Union of %p and %p\n", set, with);
 
778
 
 
779
  if (desktop_entry_set_get_count (with) == 0)
 
780
    return; /* A fast simple case */
 
781
 
 
782
  g_hash_table_foreach (with->hash,
 
783
                        (GHFunc) union_foreach,
 
784
                        set);
 
785
}
 
786
 
 
787
typedef struct
 
788
{
 
789
  DesktopEntrySet *set;
 
790
  DesktopEntrySet *with;
 
791
} IntersectData;
 
792
 
 
793
static gboolean
 
794
intersect_foreach_remove (const char    *file_id,
 
795
                          DesktopEntry  *entry,
 
796
                          IntersectData *id)
 
797
{
 
798
  /* Remove everything in "set" which is not in "with" */
 
799
 
 
800
  if (g_hash_table_lookup (id->with->hash, file_id) != NULL)
 
801
    return FALSE;
 
802
 
 
803
  menu_verbose (" Removing from %p entry %s\n", id->set, file_id);
 
804
 
 
805
  return TRUE; /* return TRUE to remove */
 
806
}
 
807
 
 
808
void
 
809
desktop_entry_set_intersection (DesktopEntrySet *set,
 
810
                                DesktopEntrySet *with)
 
811
{
 
812
  IntersectData id;
 
813
 
 
814
  menu_verbose (" Intersection of %p and %p\n", set, with);
 
815
 
 
816
  if (desktop_entry_set_get_count (set) == 0 ||
 
817
      desktop_entry_set_get_count (with) == 0)
 
818
    {
 
819
      /* A fast simple case */
 
820
      desktop_entry_set_clear (set);
 
821
      return;
 
822
    }
 
823
 
 
824
  id.set  = set;
 
825
  id.with = with;
 
826
 
 
827
  g_hash_table_foreach_remove (set->hash,
 
828
                               (GHRFunc) intersect_foreach_remove,
 
829
                               &id);
 
830
}
 
831
 
 
832
typedef struct
 
833
{
 
834
  DesktopEntrySet *set;
 
835
  DesktopEntrySet *other;
 
836
} SubtractData;
 
837
 
 
838
static gboolean
 
839
subtract_foreach_remove (const char   *file_id,
 
840
                         DesktopEntry *entry,
 
841
                         SubtractData *sd)
 
842
{
 
843
  /* Remove everything in "set" which is not in "other" */
 
844
 
 
845
  if (g_hash_table_lookup (sd->other->hash, file_id) == NULL)
 
846
    return FALSE;
 
847
 
 
848
  menu_verbose (" Removing from %p entry %s\n", sd->set, file_id);
 
849
 
 
850
  return TRUE; /* return TRUE to remove */
 
851
}
 
852
 
 
853
void
 
854
desktop_entry_set_subtract (DesktopEntrySet *set,
 
855
                            DesktopEntrySet *other)
 
856
{
 
857
  SubtractData sd;
 
858
 
 
859
  menu_verbose (" Subtract from %p set %p\n", set, other);
 
860
 
 
861
  if (desktop_entry_set_get_count (set) == 0 ||
 
862
      desktop_entry_set_get_count (other) == 0)
 
863
    return; /* A fast simple case */
 
864
 
 
865
  sd.set   = set;
 
866
  sd.other = other;
 
867
 
 
868
  g_hash_table_foreach_remove (set->hash,
 
869
                               (GHRFunc) subtract_foreach_remove,
 
870
                               &sd);
 
871
}
 
872
 
 
873
void
 
874
desktop_entry_set_swap_contents (DesktopEntrySet *a,
 
875
                                 DesktopEntrySet *b)
 
876
{
 
877
  GHashTable *tmp;
 
878
 
 
879
  menu_verbose (" Swap contents of %p and %p\n", a, b);
 
880
 
 
881
  tmp = a->hash;
 
882
  a->hash = b->hash;
 
883
  b->hash = tmp;
 
884
}