diff options
Diffstat (limited to 'libslab/app-shell.c')
-rw-r--r-- | libslab/app-shell.c | 177 |
1 files changed, 176 insertions, 1 deletions
diff --git a/libslab/app-shell.c b/libslab/app-shell.c index 6e9be346..3c33230b 100644 --- a/libslab/app-shell.c +++ b/libslab/app-shell.c @@ -59,6 +59,7 @@ static GtkWidget *create_actions_section (AppShellData * app_data, const gchar * static void generate_category (const char * category, MateMenuTreeDirectory * root_dir, AppShellData * app_data, gboolean recursive); static void generate_launchers (MateMenuTreeDirectory * root_dir, AppShellData * app_data, CategoryData * cat_data, gboolean recursive); +static void generate_new_apps (AppShellData * app_data); static void insert_launcher_into_category (CategoryData * cat_data, MateDesktopItem * desktop_item, AppShellData * app_data); @@ -841,7 +842,7 @@ matemenu_tree_changed_callback (MateMenuTree * old_tree, gpointer user_data) } AppShellData * -appshelldata_new (const gchar * menu_name, GtkIconSize icon_size, gboolean show_tile_generic_name, gboolean exit_on_close) +appshelldata_new (const gchar * menu_name, GtkIconSize icon_size, gboolean show_tile_generic_name, gboolean exit_on_close, gint new_apps_max_items) { AppShellData *app_data = g_new0 (AppShellData, 1); app_data->settings = g_settings_new (CC_SCHEMA); @@ -850,6 +851,11 @@ appshelldata_new (const gchar * menu_name, GtkIconSize icon_size, gboolean show_ app_data->stop_incremental_relayout = TRUE; app_data->show_tile_generic_name = show_tile_generic_name; app_data->exit_on_close = exit_on_close; + if (new_apps_max_items > 0) { + app_data->new_apps = g_new0 (NewAppConfig, 1); + app_data->new_apps->max_items = new_apps_max_items; + app_data->new_apps->name = _("New Applications"); + } return app_data; } @@ -912,6 +918,9 @@ generate_categories (AppShellData * app_data) } matemenu_tree_item_unref (root_dir); + + if (app_data->new_apps && (app_data->new_apps->max_items > 0)) + generate_new_apps (app_data); } static void @@ -1055,6 +1064,172 @@ generate_launchers (MateMenuTreeDirectory * root_dir, AppShellData * app_data, C } static void +generate_new_apps (AppShellData * app_data) +{ + GHashTable *all_apps_cache = NULL; + gchar *all_apps; + GError *error = NULL; + gchar *separator = "\n"; + + gchar *all_apps_file_name; + gchar **all_apps_split; + gint x; + gboolean got_new_apps; + CategoryData *new_apps_category = NULL; + GList *categories, *launchers; + GHashTable *new_apps_dups; + + all_apps_file_name = g_build_filename (g_get_user_config_dir (), "mate", "ab-newapps.txt", NULL); + + if (!g_file_get_contents (all_apps_file_name, &all_apps, NULL, &error)) + { + /* If file does not exist, this is the first time this user has run this, create the baseline file */ + GList *categories, *launchers; + GString *gstr; + gchar *dirname; + + g_error_free (error); + error = NULL; + + /* best initial size determined by running on a couple different platforms */ + gstr = g_string_sized_new (10000); + + for (categories = app_data->categories_list; categories; categories = categories->next) + { + CategoryData *data = categories->data; + for (launchers = data->launcher_list; launchers; launchers = launchers->next) + { + Tile *tile = TILE (launchers->data); + MateDesktopItem *item = + application_tile_get_desktop_item (APPLICATION_TILE (tile)); + const gchar *uri = mate_desktop_item_get_location (item); + g_string_append (gstr, uri); + g_string_append (gstr, separator); + } + } + + dirname = g_path_get_dirname (all_apps_file_name); + g_mkdir_with_parents (dirname, 0700); /* creates if does not exist */ + g_free (dirname); + + if (!g_file_set_contents (all_apps_file_name, gstr->str, -1, &error)) + g_warning ("Error setting all apps file:%s\n", error->message); + + g_string_free (gstr, TRUE); + g_free (all_apps_file_name); + return; + } + + all_apps_cache = g_hash_table_new (g_str_hash, g_str_equal); + all_apps_split = g_strsplit (all_apps, separator, -1); + for (x = 0; all_apps_split[x]; x++) + { + g_hash_table_insert (all_apps_cache, all_apps_split[x], all_apps_split[x]); + } + + got_new_apps = FALSE; + new_apps_dups = g_hash_table_new (g_str_hash, g_str_equal); + for (categories = app_data->categories_list; categories; categories = categories->next) + { + CategoryData *cat_data = categories->data; + for (launchers = cat_data->launcher_list; launchers; launchers = launchers->next) + { + Tile *tile = TILE (launchers->data); + MateDesktopItem *item = + application_tile_get_desktop_item (APPLICATION_TILE (tile)); + const gchar *uri = mate_desktop_item_get_location (item); + if (!g_hash_table_lookup (all_apps_cache, uri)) + { + GFile *file; + GFileInfo *info; + long filetime; + + if (g_hash_table_lookup (new_apps_dups, uri)) + { + /* if a desktop file is in 2 or more top level categories, only show it once */ + /* printf("Discarding Newapp duplicate:%s\n", uri); */ + break; + } + g_hash_table_insert (new_apps_dups, (gpointer) uri, (gpointer) uri); + + if (!got_new_apps) + { + new_apps_category = g_new0 (CategoryData, 1); + new_apps_category->category = + g_strdup (app_data->new_apps->name); + app_data->new_apps->garray = + g_array_sized_new (FALSE, TRUE, + sizeof (NewAppData *), + app_data->new_apps->max_items); + + /* should not need this, but a bug in glib does not actually clear the elements until you call this method */ + g_array_set_size (app_data->new_apps->garray, app_data->new_apps->max_items); + got_new_apps = TRUE; + } + + file = g_file_new_for_uri (uri); + info = g_file_query_info (file, + G_FILE_ATTRIBUTE_TIME_MODIFIED, + 0, NULL, NULL); + + if (!info) + { + g_object_unref (file); + g_warning ("Cant get vfs info for %s\n", uri); + return; + } + filetime = (long) g_file_info_get_attribute_uint64 (info, + G_FILE_ATTRIBUTE_TIME_MODIFIED); + g_object_unref (info); + g_object_unref (file); + + for (x = 0; x < app_data->new_apps->max_items; x++) + { + NewAppData *temp_data = (NewAppData *) + g_array_index (app_data->new_apps->garray, NewAppData *, x); + if (!temp_data || filetime > temp_data->time) /* if this slot is empty or we are newer than this slot */ + { + NewAppData *temp = g_new0 (NewAppData, 1); + temp->time = filetime; + temp->item = item; + g_array_insert_val (app_data->new_apps->garray, x, + temp); + break; + } + } + } + } + } + g_hash_table_destroy (new_apps_dups); + g_hash_table_destroy (all_apps_cache); + + if (got_new_apps) + { + for (x = 0; x < app_data->new_apps->max_items; x++) + { + NewAppData *data = + (NewAppData *) g_array_index (app_data->new_apps->garray, + NewAppData *, x); + if (data) + { + insert_launcher_into_category (new_apps_category, data->item, + app_data); + g_free (data); + } + else + break; + } + app_data->categories_list = + g_list_prepend (app_data->categories_list, new_apps_category); + + g_array_free (app_data->new_apps->garray, TRUE); + } + g_free (all_apps); + g_free (all_apps_file_name); + g_strfreev (all_apps_split); +} + +static void insert_launcher_into_category (CategoryData * cat_data, MateDesktopItem * desktop_item, AppShellData * app_data) { |