Skip to content

Commit 1cf2ae3

Browse files
committed
add AppSystem.get_top_directories() and CinnamonApp.get_categories()
rev3
1 parent 90bbc7b commit 1cf2ae3

File tree

5 files changed

+136
-50
lines changed

5 files changed

+136
-50
lines changed

src/cinnamon-app-private.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ G_BEGIN_DECLS
1212

1313
CinnamonApp* _cinnamon_app_new_for_window (MetaWindow *window);
1414

15-
CinnamonApp* _cinnamon_app_new (GMenuTreeEntry *entry);
15+
CinnamonApp* _cinnamon_app_new (GMenuTreeEntry *entry, GPtrArray *categories);
1616

1717
void _cinnamon_app_set_entry (CinnamonApp *app, GMenuTreeEntry *entry);
1818

19+
void _cinnamon_app_set_categories (CinnamonApp *app, GPtrArray *categories);
20+
1921
void _cinnamon_app_handle_startup_sequence (CinnamonApp *app, SnStartupSequence *sequence);
2022

2123
void _cinnamon_app_add_window (CinnamonApp *app, MetaWindow *window);

src/cinnamon-app-system.c

Lines changed: 96 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,36 @@ struct _CinnamonAppSystemPrivate {
5252
GHashTable *running_apps;
5353
GHashTable *id_to_app;
5454
GHashTable *startup_wm_class_to_app;
55+
GPtrArray *top_level_directories;
5556

5657
GSList *known_vendor_prefixes;
5758
};
5859

60+
typedef struct {
61+
GMenuTreeEntry *entry;
62+
GPtrArray *categories;
63+
} FlattenedEntry;
64+
65+
static FlattenedEntry *
66+
flattened_entry_new (GMenuTreeEntry *entry)
67+
{
68+
g_return_val_if_fail (entry != NULL, NULL);
69+
FlattenedEntry *out = g_slice_new (FlattenedEntry);
70+
out->entry = gmenu_tree_item_ref (entry);
71+
out->categories = g_ptr_array_new_with_free_func ((GDestroyNotify) gmenu_tree_item_unref);
72+
return out;
73+
}
74+
75+
static void
76+
flattened_entry_free (FlattenedEntry *entry)
77+
{
78+
g_return_if_fail (entry != NULL);
79+
g_clear_pointer (&entry->entry, gmenu_tree_item_unref);
80+
g_clear_pointer (&entry->categories, g_ptr_array_unref);
81+
g_slice_free (FlattenedEntry, entry);
82+
}
83+
84+
5985
static void cinnamon_app_system_finalize (GObject *object);
6086
static void on_apps_tree_changed_cb (GMenuTree *tree, gpointer user_data);
6187
CinnamonApp * lookup_heuristic_basename (CinnamonAppSystem *system, const char *name);
@@ -127,6 +153,8 @@ cinnamon_app_system_init (CinnamonAppSystem *self)
127153
NULL,
128154
(GDestroyNotify)g_object_unref);
129155

156+
priv->top_level_directories = NULL;
157+
130158
priv->startup_wm_class_to_app = g_hash_table_new_full (g_str_hash, g_str_equal,
131159
NULL,
132160
(GDestroyNotify)g_object_unref);
@@ -476,12 +504,16 @@ deduplicate_apps (GPtrArray *app_array,
476504
DEBUG_RENAMING ("Done renaming for '%s'\n\n", (gchar *) key);
477505
}
478506

479-
static void
507+
static gboolean
480508
get_flattened_entries_recurse (GMenuTreeDirectory *dir,
481-
GHashTable *entry_set)
509+
GMenuTreeDirectory *top_dir,
510+
GHashTable *flattened_entry_set,
511+
GPtrArray *top_level_dirs)
482512
{
483513
GMenuTreeIter *iter = gmenu_tree_directory_iter (dir);
484514
GMenuTreeItemType next_type;
515+
gboolean has_entries = FALSE;
516+
gboolean is_root = top_dir == NULL;
485517

486518
while ((next_type = gmenu_tree_iter_next (iter)) != GMENU_TREE_ITEM_INVALID)
487519
{
@@ -492,17 +524,36 @@ get_flattened_entries_recurse (GMenuTreeDirectory *dir,
492524
case GMENU_TREE_ITEM_ENTRY:
493525
{
494526
GMenuTreeEntry *entry;
527+
FlattenedEntry *f_entry;
495528
item = entry = gmenu_tree_iter_get_entry (iter);
496-
/* Key is owned by entry */
497-
g_hash_table_replace (entry_set,
498-
(char*)gmenu_tree_entry_get_desktop_file_id (entry),
499-
gmenu_tree_item_ref (entry));
529+
char *desktop_id = (char*)gmenu_tree_entry_get_desktop_file_id (entry);
530+
531+
f_entry = g_hash_table_lookup (flattened_entry_set, desktop_id);
532+
if (!f_entry)
533+
{
534+
f_entry = flattened_entry_new (entry);
535+
536+
if (!is_root)
537+
g_ptr_array_add (f_entry->categories, g_strdup(gmenu_tree_directory_get_menu_id (top_dir)));
538+
539+
/* Key is owned by entry */
540+
g_hash_table_insert (flattened_entry_set, desktop_id, f_entry);
541+
}
542+
g_ptr_array_add (f_entry->categories, g_strdup(gmenu_tree_directory_get_menu_id (dir)));
543+
has_entries = TRUE;
500544
}
501545
break;
502546
case GMENU_TREE_ITEM_DIRECTORY:
503547
{
504-
item = gmenu_tree_iter_get_directory (iter);
505-
get_flattened_entries_recurse ((GMenuTreeDirectory*)item, entry_set);
548+
GMenuTreeDirectory *next_dir;
549+
item = next_dir = gmenu_tree_iter_get_directory (iter);
550+
gboolean res = get_flattened_entries_recurse (next_dir,
551+
is_root ? dir : top_dir,
552+
flattened_entry_set,
553+
top_level_dirs);
554+
has_entries |= res;
555+
if (is_root && res && !g_ptr_array_find (top_level_dirs, item, NULL))
556+
g_ptr_array_add (top_level_dirs, gmenu_tree_item_ref (item));
506557
}
507558
break;
508559
case GMENU_TREE_ITEM_INVALID:
@@ -518,26 +569,7 @@ get_flattened_entries_recurse (GMenuTreeDirectory *dir,
518569
}
519570

520571
gmenu_tree_iter_unref (iter);
521-
}
522-
523-
static GHashTable *
524-
get_flattened_entries_from_tree (GMenuTree *tree)
525-
{
526-
GHashTable *table;
527-
GMenuTreeDirectory *root;
528-
529-
table = g_hash_table_new_full (g_str_hash, g_str_equal,
530-
(GDestroyNotify) NULL,
531-
(GDestroyNotify) gmenu_tree_item_unref);
532-
533-
root = gmenu_tree_get_root_directory (tree);
534-
535-
if (root != NULL)
536-
get_flattened_entries_recurse (root, table);
537-
538-
gmenu_tree_item_unref (root);
539-
540-
return table;
572+
return has_entries;
541573
}
542574

543575
static void
@@ -547,11 +579,20 @@ on_apps_tree_changed_cb (GMenuTree *tree,
547579
CinnamonAppSystem *self = CINNAMON_APP_SYSTEM (user_data);
548580
GError *error = NULL;
549581
GHashTable *new_apps, *display_names;
582+
GPtrArray *dirs;
583+
GMenuTreeDirectory *root;
550584
GHashTableIter iter;
551585
gpointer key, value;
552586

553587
g_assert (tree == self->priv->apps_tree);
554588

589+
new_apps = g_hash_table_new_full (g_str_hash, g_str_equal,
590+
(GDestroyNotify) NULL,
591+
(GDestroyNotify) flattened_entry_free);
592+
593+
dirs = g_ptr_array_new_with_free_func ((GDestroyNotify) gmenu_tree_item_unref);
594+
g_clear_pointer (&self->priv->top_level_directories, g_ptr_array_unref);
595+
555596
g_slist_free_full (self->priv->known_vendor_prefixes, g_free);
556597
self->priv->known_vendor_prefixes = NULL;
557598

@@ -569,7 +610,14 @@ on_apps_tree_changed_cb (GMenuTree *tree,
569610
return;
570611
}
571612

572-
new_apps = get_flattened_entries_from_tree (self->priv->apps_tree);
613+
root = gmenu_tree_get_root_directory (self->priv->apps_tree);
614+
615+
if (root != NULL)
616+
get_flattened_entries_recurse (root, NULL, new_apps, dirs);
617+
618+
gmenu_tree_item_unref (root);
619+
620+
self->priv->top_level_directories = dirs;
573621

574622
display_names = g_hash_table_new_full (g_str_hash, g_str_equal,
575623
(GDestroyNotify) g_free,
@@ -579,7 +627,8 @@ on_apps_tree_changed_cb (GMenuTree *tree,
579627
while (g_hash_table_iter_next (&iter, &key, &value))
580628
{
581629
const char *id = key;
582-
GMenuTreeEntry *entry = value;
630+
FlattenedEntry *f_entry = value;
631+
GMenuTreeEntry *entry = f_entry->entry;
583632
GMenuTreeEntry *old_entry;
584633
char *prefix;
585634
CinnamonApp *app;
@@ -627,13 +676,14 @@ on_apps_tree_changed_cb (GMenuTree *tree,
627676
#endif
628677

629678
_cinnamon_app_set_entry (app, entry);
679+
_cinnamon_app_set_categories (app, f_entry->categories);
630680

631681
g_object_ref (app); /* Extra ref, removed in _replace below */
632682
}
633683
else
634684
{
635685
old_entry = NULL;
636-
app = _cinnamon_app_new (entry);
686+
app = _cinnamon_app_new (entry, f_entry->categories);
637687

638688
DEBUG_RENAMING ("New app entry: '%s' with source '%s'\n",
639689
_cinnamon_app_get_common_name (app),
@@ -748,7 +798,7 @@ cinnamon_app_system_get_tree (CinnamonAppSystem *self)
748798
/**
749799
* cinnamon_app_system_get_default:
750800
*
751-
* Return Value: (transfer none): The global #CinnamonAppSystem singleton
801+
* Returns: (transfer none): The global #CinnamonAppSystem singleton
752802
*/
753803
CinnamonAppSystem *
754804
cinnamon_app_system_get_default (void)
@@ -761,6 +811,19 @@ cinnamon_app_system_get_default (void)
761811
return instance;
762812
}
763813

814+
/**
815+
* cinnamon_app_system_get_top_directories:
816+
*
817+
* Returns: (nullable) (transfer none) (element-type GMenuTreeDirectory): A list of top level menu directories.
818+
*/
819+
GPtrArray *
820+
cinnamon_app_system_get_top_directories (CinnamonAppSystem *self)
821+
{
822+
return self->priv->top_level_directories;
823+
}
824+
825+
826+
764827
gboolean
765828
case_insensitive_search (const char *key,
766829
const char *value,
@@ -780,7 +843,7 @@ case_insensitive_search (const char *key,
780843
*
781844
* Find a #CinnamonApp corresponding to an id.
782845
*
783-
* Return value: (transfer none): The #CinnamonApp for id, or %NULL if none
846+
* Returns: (transfer none): The #CinnamonApp for id, or %NULL if none
784847
*/
785848
CinnamonApp *
786849
cinnamon_app_system_lookup_app (CinnamonAppSystem *self,

src/cinnamon-app-system.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,6 @@ GSList *cinnamon_app_system_get_all (CinnamonAppSystem
5353

5454
GSList *cinnamon_app_system_get_running (CinnamonAppSystem *self);
5555

56+
GPtrArray *cinnamon_app_system_get_top_directories (CinnamonAppSystem *self);
57+
5658
#endif /* __CINNAMON_APP_SYSTEM_H__ */

src/cinnamon-app.c

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ struct _CinnamonApp
5757
* want (e.g. it will be of TYPE_NORMAL from
5858
* the way cinnamon-window-tracker.c works).
5959
*/
60+
61+
GPtrArray *categories;
62+
6063
GDesktopAppInfo *info;
6164

6265
CinnamonAppRunningState *running_state;
@@ -739,6 +742,16 @@ cinnamon_app_get_windows (CinnamonApp *app)
739742
return app->running_state->windows;
740743
}
741744

745+
/**
746+
* cinnamon_app_get_categories:
747+
*
748+
* Returns: (nullable) (transfer none) (element-type utf8): List of categories or NULL if app is window-backed
749+
*/
750+
GPtrArray *
751+
cinnamon_app_get_categories (CinnamonApp *app) {
752+
return app->categories;
753+
}
754+
742755
guint
743756
cinnamon_app_get_n_windows (CinnamonApp *app)
744757
{
@@ -789,20 +802,20 @@ _cinnamon_app_new_for_window (MetaWindow *window)
789802
}
790803

791804
CinnamonApp *
792-
_cinnamon_app_new (GMenuTreeEntry *info)
805+
_cinnamon_app_new (GMenuTreeEntry *info, GPtrArray *categories)
793806
{
794807
CinnamonApp *app;
795808

796809
app = g_object_new (CINNAMON_TYPE_APP, NULL);
797810

798811
_cinnamon_app_set_entry (app, info);
799-
812+
_cinnamon_app_set_categories (app, categories);
800813
return app;
801814
}
802815

803816
void
804817
_cinnamon_app_set_entry (CinnamonApp *app,
805-
GMenuTreeEntry *entry)
818+
GMenuTreeEntry *entry)
806819
{
807820
g_clear_pointer (&app->entry, gmenu_tree_item_unref);
808821
g_clear_object (&app->info);
@@ -820,6 +833,14 @@ _cinnamon_app_set_entry (CinnamonApp *app,
820833
}
821834
}
822835

836+
void
837+
_cinnamon_app_set_categories (CinnamonApp *app,
838+
GPtrArray *categories)
839+
{
840+
g_clear_pointer (&app->categories, g_ptr_array_unref);
841+
app->categories = g_ptr_array_ref (categories);
842+
}
843+
823844
static void
824845
cinnamon_app_state_transition (CinnamonApp *app,
825846
CinnamonAppState state)
@@ -1193,27 +1214,23 @@ unref_running_state (CinnamonAppRunningState *state)
11931214
static void
11941215
cinnamon_app_init (CinnamonApp *self)
11951216
{
1196-
self->state = CINNAMON_APP_STATE_STOPPED;
1197-
self->keywords = NULL;
1217+
self->categories = NULL;
1218+
self->entry = NULL;
11981219
self->global = cinnamon_global_get ();
1220+
self->keywords = NULL;
1221+
self->state = CINNAMON_APP_STATE_STOPPED;
1222+
self->unique_name = NULL;
1223+
self->window_id_string = NULL;
11991224
}
12001225

12011226
static void
12021227
cinnamon_app_dispose (GObject *object)
12031228
{
12041229
CinnamonApp *app = CINNAMON_APP (object);
12051230

1206-
if (app->entry)
1207-
{
1208-
gmenu_tree_item_unref (app->entry);
1209-
app->entry = NULL;
1210-
}
1211-
1212-
if (app->info)
1213-
{
1214-
g_object_unref (app->info);
1215-
app->info = NULL;
1216-
}
1231+
g_clear_pointer(&app->entry, gmenu_tree_item_unref);
1232+
g_clear_pointer(&app->info, g_object_unref);
1233+
g_clear_pointer(&app->categories, g_ptr_array_unref);
12171234

12181235
while (app->running_state)
12191236
_cinnamon_app_remove_window (app, app->running_state->windows->data);

src/cinnamon-app.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ GSList *cinnamon_app_get_windows (CinnamonApp *app);
7373

7474
GSList *cinnamon_app_get_pids (CinnamonApp *app);
7575

76+
GPtrArray *cinnamon_app_get_categories (CinnamonApp *app);
77+
7678
gboolean cinnamon_app_is_on_workspace (CinnamonApp *app, MetaWorkspace *workspace);
7779

7880
gboolean cinnamon_app_launch (CinnamonApp *app,

0 commit comments

Comments
 (0)