diff options
Diffstat (limited to 'libslab/app-shell.c')
-rw-r--r-- | libslab/app-shell.c | 1448 |
1 files changed, 0 insertions, 1448 deletions
diff --git a/libslab/app-shell.c b/libslab/app-shell.c deleted file mode 100644 index 0e681c2e..00000000 --- a/libslab/app-shell.c +++ /dev/null @@ -1,1448 +0,0 @@ -/* - * This file is part of libslab. - * - * Copyright (c) 2006 Novell, Inc. - * - * Libslab is free software; you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * Libslab is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for - * more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with libslab; if not, write to the Free Software Foundation, Inc., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <libmate-desktop/mate-desktop-item.h> -#include <gio/gio.h> -#include <gtk/gtk.h> -#include <gdk/gdkkeysyms.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <string.h> -#include <stdlib.h> - -#include <glib/gi18n-lib.h> - -#include "app-shell.h" -#include "shell-window.h" -#include "app-resizer.h" -#include "slab-section.h" -#include "slab-mate-util.h" -#include "search-bar.h" - -#include "application-tile.h" -#include "themed-icon.h" - -#define TILE_EXEC_NAME "Tile_desktop_exec_name" -#define CC_SCHEMA "org.mate.control-center" -#define EXIT_SHELL_ON_ACTION_START "cc-exit-shell-on-action-start" -#define EXIT_SHELL_ON_ACTION_HELP "cc-exit-shell-on-action-help" -#define EXIT_SHELL_ON_ACTION_ADD_REMOVE "cc-exit-shell-on-action-add-remove" -#define EXIT_SHELL_ON_ACTION_UPGRADE_UNINSTALL "cc-exit-shell-on-action-upgrade-uninstall" - -static void create_application_category_sections (AppShellData * app_data); -static GtkWidget *create_filter_section (AppShellData * app_data, const gchar * title); -static GtkWidget *create_groups_section (AppShellData * app_data, const gchar * title); -static GtkWidget *create_actions_section (AppShellData * app_data, const gchar * title, - void (*actions_handler) (Tile *, TileEvent *, gpointer)); - -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); - -static gboolean main_keypress_callback (GtkWidget * widget, GdkEventKey * event, - AppShellData * app_data); -static gboolean main_delete_callback (GtkWidget * widget, GdkEvent * event, - AppShellData * app_data); -static void application_launcher_clear_search_bar (AppShellData * app_data); -static void launch_selected_app (AppShellData * app_data); -static void generate_potential_apps (gpointer catdata, gpointer user_data); - -static void relayout_shell (AppShellData * app_data); -static gboolean handle_filter_changed (NldSearchBar * search_bar, const char *text, - gpointer user_data); -static void handle_group_clicked (Tile * tile, TileEvent * event, gpointer user_data); -static void set_state (AppShellData * app_data, GtkWidget * widget); -static void populate_groups_section (AppShellData * app_data); -static void generate_filtered_lists (gpointer catdata, gpointer user_data); -static void show_no_results_message (AppShellData * app_data, GtkWidget * containing_vbox); -static void populate_application_category_sections (AppShellData * app_data, - GtkWidget * containing_vbox); -static void populate_application_category_section (AppShellData * app_data, SlabSection * section, - GList * launcher_list); -static void tile_activated_cb (Tile * tile, TileEvent * event, gpointer user_data); -static void handle_launcher_single_clicked (Tile * launcher, gpointer data); -static void handle_menu_action_performed (Tile * launcher, TileEvent * event, TileAction * action, - gpointer data); -static gint application_launcher_compare (gconstpointer a, gconstpointer b); -static void matemenu_tree_changed_callback (MateMenuTree * tree, gpointer user_data); -gboolean regenerate_categories (AppShellData * app_data); - -void -hide_shell (AppShellData * app_data) -{ - gtk_window_get_position (GTK_WINDOW (app_data->main_app), - &app_data->main_app_window_x, &app_data->main_app_window_y); - /* clear the search bar now so reshowing is fast and flicker free - BNC#283186 */ - application_launcher_clear_search_bar (app_data); - gtk_widget_hide (app_data->main_app); -} - -void -show_shell (AppShellData * app_data) -{ - gtk_widget_show_all (app_data->main_app); - if (!app_data->static_actions) - gtk_widget_hide (app_data->actions_section); /* don't show unless a launcher is selected */ - - if (app_data->main_app_window_shown_once) - gtk_window_move (GTK_WINDOW (app_data->main_app), - app_data->main_app_window_x, app_data->main_app_window_y); - - /* if this is the first time shown, need to clear this handler */ - else - shell_window_clear_resize_handler (SHELL_WINDOW (app_data->shell)); - app_data->main_app_window_shown_once = TRUE; -} - -gboolean -create_main_window (AppShellData * app_data, const gchar * app_name, const gchar * title, - const gchar * window_icon, gint width, gint height, gboolean hidden) -{ - GtkWidget *main_app = gtk_window_new (GTK_WINDOW_TOPLEVEL); - app_data->main_app = main_app; - gtk_widget_set_name (main_app, app_name); - gtk_window_set_title (GTK_WINDOW (main_app), title); - gtk_window_set_default_size(GTK_WINDOW(main_app), width, height); - gtk_window_set_icon_name (GTK_WINDOW (main_app), window_icon); - gtk_container_add (GTK_CONTAINER (main_app), app_data->shell); - - g_signal_connect (main_app, "delete-event", G_CALLBACK (main_delete_callback), app_data); - g_signal_connect (main_app, "key-press-event", G_CALLBACK (main_keypress_callback), - app_data); - - gtk_window_set_position (GTK_WINDOW (app_data->main_app), GTK_WIN_POS_CENTER); - if (!hidden) - show_shell (app_data); - - return TRUE; -} - -static void -generate_potential_apps (gpointer catdata, gpointer user_data) -{ - GHashTable *app_hash = (GHashTable *) user_data; - CategoryData *data = (CategoryData *) catdata; - gchar *uri; - - GList *launcher_list = data->filtered_launcher_list; - - while (launcher_list) - { - g_object_get (launcher_list->data, "tile-uri", &uri, NULL); - /* eliminate dups of same app in multiple categories */ - if (!g_hash_table_lookup (app_hash, uri)) - g_hash_table_insert (app_hash, uri, launcher_list->data); - else - g_free (uri); - launcher_list = g_list_next (launcher_list); - } -} - -static gboolean -return_first_entry (gpointer key, gpointer value, gpointer unused) -{ - return TRUE; /*better way to pull an entry out ? */ -} - -static void -launch_selected_app (AppShellData * app_data) -{ - GHashTable *app_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - guint num_apps; - - g_list_foreach (app_data->categories_list, generate_potential_apps, app_hash); - num_apps = g_hash_table_size (app_hash); - if (num_apps == 1) - { - ApplicationTile *launcher = - APPLICATION_TILE (g_hash_table_find (app_hash, return_first_entry, NULL)); - g_hash_table_destroy (app_hash); - handle_launcher_single_clicked (TILE (launcher), app_data); - return; - } - - g_hash_table_destroy (app_hash); -} - -static gboolean -main_keypress_callback (GtkWidget * widget, GdkEventKey * event, AppShellData * app_data) -{ - GApplication *app; - - if (event->keyval == GDK_KEY_Return) - { - SlabSection *section = SLAB_SECTION (app_data->filter_section); - NldSearchBar *search_bar; - - /* Make sure our implementation has not changed */ - g_assert (NLD_IS_SEARCH_BAR (section->contents)); - search_bar = NLD_SEARCH_BAR (section->contents); - if (nld_search_bar_has_focus (search_bar)) - { - launch_selected_app (app_data); - return TRUE; - } - } - - /* quit on ESC or Ctl-W or Ctl-Q */ - if (event->keyval == GDK_KEY_Escape || - ((event->keyval == GDK_KEY_w || event->keyval == GDK_KEY_W) && (event->state & GDK_CONTROL_MASK)) || - ((event->keyval == GDK_KEY_q || event->keyval == GDK_KEY_Q) && (event->state & GDK_CONTROL_MASK))) - { - if (app_data->exit_on_close) - { - app=g_application_get_default(); - g_application_quit(app); - } - else - hide_shell (app_data); - - return TRUE; - } - return FALSE; -} - -static gboolean -main_delete_callback (GtkWidget * widget, GdkEvent * event, AppShellData * app_data) -{ - GApplication *app; - - if (app_data->exit_on_close) - { - app=g_application_get_default(); - g_application_quit(app); - return FALSE; - } - - hide_shell (app_data); - return TRUE; /* stop the processing of this event */ -} - -void -layout_shell (AppShellData * app_data, const gchar * filter_title, const gchar * groups_title, - const gchar * actions_title, GSList * actions, - void (*actions_handler) (Tile *, TileEvent *, gpointer)) -{ - GtkWidget *filter_section; - GtkWidget *groups_section; - GtkWidget *actions_section; - - GtkWidget *left_vbox; - GtkWidget *right_vbox; - gint num_cols; - - GtkWidget *sw; - GtkAdjustment *adjustment; - - app_data->shell = shell_window_new (app_data); - app_data->static_actions = actions; - - right_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - - num_cols = SIZING_SCREEN_WIDTH_LARGE_NUMCOLS; - - GdkRectangle geometry = {0}; - - GdkDisplay *display; - GdkMonitor *monitor; - - display= gdk_screen_get_display (gdk_screen_get_default ()); - monitor = gdk_display_get_monitor (display, 0); - gdk_monitor_get_geometry (monitor, &geometry); - - if (geometry.width <= SIZING_SCREEN_WIDTH_LARGE) - { - if (geometry.width <= SIZING_SCREEN_WIDTH_MEDIUM) - num_cols = SIZING_SCREEN_WIDTH_SMALL_NUMCOLS; - else - num_cols = SIZING_SCREEN_WIDTH_MEDIUM_NUMCOLS; - } - app_data->category_layout = - app_resizer_new (GTK_BOX (right_vbox), num_cols, TRUE, app_data); - - sw = gtk_scrolled_window_new (NULL, NULL); - gtk_widget_set_vexpand (GTK_WIDGET (sw), TRUE); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (sw), app_data->category_layout); - adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (sw)); - g_object_set (adjustment, "step-increment", (double) 20, NULL); - - create_application_category_sections (app_data); - populate_application_category_sections (app_data, right_vbox); - app_resizer_set_table_cache (APP_RESIZER (app_data->category_layout), - app_data->cached_tables_list); - - gtk_container_set_focus_vadjustment (GTK_CONTAINER (right_vbox), - gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (sw))); - - left_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 15); - - filter_section = create_filter_section (app_data, filter_title); - app_data->filter_section = filter_section; - gtk_box_pack_start (GTK_BOX (left_vbox), filter_section, FALSE, FALSE, 0); - - groups_section = create_groups_section (app_data, groups_title); - app_data->groups_section = groups_section; - populate_groups_section (app_data); - gtk_box_pack_start (GTK_BOX (left_vbox), groups_section, FALSE, FALSE, 0); - - actions_section = create_actions_section (app_data, actions_title, actions_handler); - app_data->actions_section = actions_section; - gtk_box_pack_start (GTK_BOX (left_vbox), actions_section, FALSE, FALSE, 0); - - shell_window_set_contents (SHELL_WINDOW (app_data->shell), left_vbox, sw); -} - -static gboolean -relayout_shell_partial (gpointer user_data) -{ - AppShellData *app_data = (AppShellData *) user_data; - GtkBox *vbox = APP_RESIZER (app_data->category_layout)->child; - CategoryData *data; - - if (app_data->stop_incremental_relayout) - return FALSE; - - if (app_data->incremental_relayout_cat_list != NULL) - { - /* There are still categories to layout */ - data = (CategoryData *) app_data->incremental_relayout_cat_list->data; - if (data->filtered_launcher_list != NULL) - { - populate_application_category_section (app_data, data->section, - data->filtered_launcher_list); - gtk_box_pack_start (vbox, GTK_WIDGET (data->section), TRUE, TRUE, - 0); - app_data->filtered_out_everything = FALSE; - } - - app_data->incremental_relayout_cat_list = - g_list_next (app_data->incremental_relayout_cat_list); - return TRUE; - } - - /* We're done laying out the categories; finish up */ - if (app_data->filtered_out_everything) - show_no_results_message (app_data, GTK_WIDGET (vbox)); - - app_resizer_set_table_cache (APP_RESIZER (app_data->category_layout), - app_data->cached_tables_list); - populate_groups_section (app_data); - - gtk_widget_show_all (app_data->category_layout); - gdk_window_set_cursor (gtk_widget_get_window (app_data->shell), NULL); - - app_data->stop_incremental_relayout = TRUE; - return FALSE; -} - -static void -relayout_shell_incremental (AppShellData * app_data) -{ - GtkBox *vbox = APP_RESIZER (app_data->category_layout)->child; - - app_data->stop_incremental_relayout = FALSE; - app_data->filtered_out_everything = TRUE; - app_data->incremental_relayout_cat_list = app_data->categories_list; - - if (app_data->cached_tables_list) - g_list_free (app_data->cached_tables_list); - app_data->cached_tables_list = NULL; - - remove_container_entries (GTK_CONTAINER (vbox)); - - g_idle_add ((GSourceFunc) relayout_shell_partial, app_data); -} - -static void -relayout_shell (AppShellData * app_data) -{ - GtkWidget *shell = app_data->shell; - GtkBox *vbox = APP_RESIZER (app_data->category_layout)->child; - - populate_application_category_sections (app_data, GTK_WIDGET (vbox)); - app_resizer_set_table_cache (APP_RESIZER (app_data->category_layout), - app_data->cached_tables_list); - populate_groups_section (app_data); - - gtk_widget_show_all (shell); - if (!app_data->static_actions && !app_data->last_clicked_launcher) - gtk_widget_hide (app_data->actions_section); /* don't show unless a launcher is selected */ -} - -static GtkWidget * -create_actions_section (AppShellData * app_data, const gchar * title, - void (*actions_handler) (Tile *, TileEvent *, gpointer)) -{ - GtkWidget *section, *launcher; - GtkWidget *vbox; - GSList *actions; - AppAction *action; - AtkObject *a11y_cat; - - g_assert (app_data != NULL); - - section = slab_section_new (title, Style1); - g_object_ref (section); - - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - slab_section_set_contents (SLAB_SECTION (section), vbox); - - if (app_data->static_actions) - { - for (actions = app_data->static_actions; actions; actions = actions->next) - { - GtkWidget *header; - - action = (AppAction *) actions->data; - header = gtk_label_new (action->name); - gtk_label_set_line_wrap (GTK_LABEL (header), TRUE); - gtk_label_set_max_width_chars (GTK_LABEL (header), 0); - gtk_label_set_xalign (GTK_LABEL (header), 0.0); - launcher = nameplate_tile_new (NULL, NULL, header, NULL); - - g_object_set_data (G_OBJECT (launcher), APP_ACTION_KEY, action->item); - g_signal_connect (launcher, "tile-activated", G_CALLBACK (actions_handler), - app_data); - gtk_box_pack_start (GTK_BOX (vbox), launcher, FALSE, FALSE, 0); - - a11y_cat = gtk_widget_get_accessible (GTK_WIDGET (launcher)); - atk_object_set_name (a11y_cat, action->name); - } - } - - return section; -} - -static GtkWidget * -create_groups_section (AppShellData * app_data, const gchar * title) -{ - GtkWidget *section; - GtkWidget *vbox; - - g_assert (app_data != NULL); - - section = slab_section_new (title, Style1); - g_object_ref (section); - - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - slab_section_set_contents (SLAB_SECTION (section), vbox); - - return section; -} - -static void -populate_groups_section (AppShellData * app_data) -{ - SlabSection *section = SLAB_SECTION (app_data->groups_section); - GtkBox *vbox; - GList *cat_list; - - vbox = GTK_BOX (section->contents); - remove_container_entries (GTK_CONTAINER (vbox)); - - cat_list = app_data->categories_list; - do - { - CategoryData *data = (CategoryData *) cat_list->data; - if (NULL != data->filtered_launcher_list) - { - gtk_widget_set_state_flags (GTK_WIDGET (data->group_launcher), GTK_STATE_FLAG_NORMAL, FALSE); - gtk_box_pack_start (vbox, GTK_WIDGET (data->group_launcher), - FALSE, FALSE, 0); - } - } - while (NULL != (cat_list = g_list_next (cat_list))); -} - -static void -handle_group_clicked (Tile * tile, TileEvent * event, gpointer user_data) -{ - AppShellData *app_data = (AppShellData *) user_data; - GtkWidget *section = NULL; - GtkAllocation allocation; - - gint clicked_pos = - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tile), GROUP_POSITION_NUMBER_KEY)); - - GList *cat_list = app_data->categories_list; - - gint total = 0; - do - { - CategoryData *cat_data = (CategoryData *) cat_list->data; - gint pos = - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cat_data->group_launcher), - GROUP_POSITION_NUMBER_KEY)); - if (pos == clicked_pos) - { - section = GTK_WIDGET (cat_data->section); - break; - } - - if (NULL != cat_data->filtered_launcher_list) - { - gtk_widget_get_allocation (GTK_WIDGET (cat_data->section), &allocation); - total += allocation.height; - } - } - while (NULL != (cat_list = g_list_next (cat_list))); - - g_assert (section != NULL); - set_state (app_data, section); - - app_resizer_set_vadjustment_value (app_data->category_layout, total); -} - -static void -set_state (AppShellData * app_data, GtkWidget * widget) -{ - if (app_data->selected_group) - { - slab_section_set_selected (app_data->selected_group, FALSE); - app_data->selected_group = NULL; - } - - if (widget) - { - app_data->selected_group = SLAB_SECTION (widget); - slab_section_set_selected (SLAB_SECTION (widget), TRUE); - } - gtk_widget_queue_draw (app_data->shell); -} - -static GtkWidget * -create_filter_section (AppShellData * app_data, const gchar * title) -{ - GtkWidget *section; - - GtkWidget *search_bar; - - section = slab_section_new (title, Style1); - g_object_ref (section); - - search_bar = nld_search_bar_new (); - nld_search_bar_set_search_timeout (NLD_SEARCH_BAR (search_bar), 0); - slab_section_set_contents (SLAB_SECTION (section), search_bar); - - g_signal_connect (search_bar, "search", - G_CALLBACK (handle_filter_changed), - app_data); - - return section; -} - -static gboolean -handle_filter_changed_delayed (gpointer user_data) -{ - AppShellData *app_data = (AppShellData *) user_data; - - g_list_foreach (app_data->categories_list, generate_filtered_lists, - (gpointer) app_data->filter_string); - app_data->last_clicked_launcher = NULL; - - /* showing the updates incremtally is very visually distracting. Much worse than just blanking until - the incremental work is done and then doing one show. It would be nice to optimize this though - somehow and not even show any change but the cursor change until all the work is done. But since - we do the work incrementally in an idle loop I don't know how else besides hiding to not show - incremental updates - */ - /* gdk_window_freeze_updates(app_data->category_layout->window); */ - gtk_widget_hide (app_data->category_layout); - app_data->busy_cursor = - gdk_cursor_new_for_display (gtk_widget_get_display (app_data->shell), GDK_WATCH); - gdk_window_set_cursor (gtk_widget_get_window (app_data->shell), app_data->busy_cursor); - g_object_unref (app_data->busy_cursor); - - set_state (app_data, NULL); - app_resizer_set_vadjustment_value (app_data->category_layout, 0); - - relayout_shell_incremental (app_data); - - app_data->filter_changed_timeout = 0; - return FALSE; -} - -static gboolean -handle_filter_changed (NldSearchBar * search_bar, const char *text, gpointer data) -{ - AppShellData *app_data; - - app_data = (AppShellData *) data; - - if (app_data->filter_string) - g_free (app_data->filter_string); - app_data->filter_string = g_strdup (text); - - if (app_data->filter_changed_timeout) - g_source_remove (app_data->filter_changed_timeout); - - app_data->filter_changed_timeout = - g_timeout_add (75, handle_filter_changed_delayed, app_data); - app_data->stop_incremental_relayout = TRUE; - - return FALSE; -} - -static void -generate_filtered_lists (gpointer catdata, gpointer user_data) -{ - CategoryData *data = (CategoryData *) catdata; - - /* Fixme - everywhere you use ascii you need to fix up for multibyte */ - gchar *filter_string = g_ascii_strdown (user_data, -1); - gchar *temp1, *temp2; - GList *launcher_list = data->launcher_list; - - g_list_free (data->filtered_launcher_list); - data->filtered_launcher_list = NULL; - - do - { - ApplicationTile *launcher = APPLICATION_TILE (launcher_list->data); - const gchar *filename; - - temp1 = NULL; - temp2 = NULL; - - /* Since the filter may remove this entry from the - container it will not get a mouse out event */ - gtk_widget_set_state_flags (GTK_WIDGET (launcher), GTK_STATE_FLAG_NORMAL, FALSE); - filename = g_object_get_data (G_OBJECT (launcher), TILE_EXEC_NAME); /* do I need to free this */ - - temp1 = g_ascii_strdown (launcher->name, -1); - if (launcher->description) - temp2 = g_ascii_strdown (launcher->description, -1); - if (g_strrstr (temp1, filter_string) || (launcher->description - && g_strrstr (temp2, filter_string)) - || g_strrstr (filename, filter_string)) - { - data->filtered_launcher_list = - g_list_append (data->filtered_launcher_list, launcher); - } - if (temp1) - g_free (temp1); - if (temp2) - g_free (temp2); - } - while (NULL != (launcher_list = g_list_next (launcher_list))); - g_free (filter_string); -} - -static void -delete_old_data (AppShellData * app_data) -{ - GList *temp; - GList *cat_list; - - g_assert (app_data != NULL); - g_assert (app_data->categories_list != NULL); - - cat_list = app_data->categories_list; - - do - { - CategoryData *data = (CategoryData *) cat_list->data; - gtk_widget_destroy (GTK_WIDGET (data->section)); - gtk_widget_destroy (GTK_WIDGET (data->group_launcher)); - g_object_unref (data->section); - g_object_unref (data->group_launcher); - g_free (data->category); - - for (temp = data->launcher_list; temp; temp = g_list_next (temp)) - { - g_free (g_object_get_data (G_OBJECT (temp->data), TILE_EXEC_NAME)); - g_object_unref (temp->data); - } - - g_list_free (data->launcher_list); - g_list_free (data->filtered_launcher_list); - g_free (data); - } - while (NULL != (cat_list = g_list_next (cat_list))); - - g_list_free (app_data->categories_list); - app_data->categories_list = NULL; - app_data->selected_group = NULL; -} - -static void -create_application_category_sections (AppShellData * app_data) -{ - GList *cat_list; - AtkObject *a11y_cat; - gint pos = 0; - - g_assert (app_data != NULL); - g_assert (app_data->categories_list != NULL); /* Fixme - pop up a dialog box and then close */ - - cat_list = app_data->categories_list; - - do - { - CategoryData *data = (CategoryData *) cat_list->data; - GtkWidget *header = gtk_label_new (data->category); - gchar *markup; - GtkWidget *hbox; - GtkWidget *table; - - gtk_label_set_xalign (GTK_LABEL (header), 0.0); - data->group_launcher = TILE (nameplate_tile_new (NULL, NULL, header, NULL)); - g_object_ref (data->group_launcher); - - g_object_set_data (G_OBJECT (data->group_launcher), GROUP_POSITION_NUMBER_KEY, - GINT_TO_POINTER (pos)); - pos++; - g_signal_connect (data->group_launcher, "tile-activated", - G_CALLBACK (handle_group_clicked), app_data); - a11y_cat = gtk_widget_get_accessible (GTK_WIDGET (data->group_launcher)); - atk_object_set_name (a11y_cat, data->category); - - markup = g_markup_printf_escaped ("<span size=\"x-large\" weight=\"bold\">%s</span>", - data->category); - data->section = SLAB_SECTION (slab_section_new_with_markup (markup, Style2)); - - /* as we filter these will be added/removed from parent container and we dont want them destroyed */ - g_object_ref (data->section); - g_free (markup); - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); - table = gtk_grid_new (); - gtk_grid_set_column_spacing (GTK_GRID (table), 5); - gtk_grid_set_row_spacing (GTK_GRID (table), 5); - gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, FALSE, 15); - slab_section_set_contents (SLAB_SECTION (data->section), hbox); - } - while (NULL != (cat_list = g_list_next (cat_list))); -} - -static void -show_no_results_message (AppShellData * app_data, GtkWidget * containing_vbox) -{ - gchar *markup; - gchar *str1; - gchar *str2; - - if (!app_data->filtered_out_everything_widget) - { - GtkWidget *image; - GtkWidget *label; - - app_data->filtered_out_everything_widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); - gtk_widget_set_halign (app_data->filtered_out_everything_widget, GTK_ALIGN_CENTER); - gtk_widget_set_valign (app_data->filtered_out_everything_widget, GTK_ALIGN_CENTER); - g_object_ref (app_data->filtered_out_everything_widget); - - image = themed_icon_new ("face-surprise", GTK_ICON_SIZE_DIALOG); - gtk_box_pack_start (GTK_BOX (app_data->filtered_out_everything_widget), image, FALSE, FALSE, 0); - - label = gtk_label_new (NULL); - gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); - gtk_box_pack_start (GTK_BOX (app_data->filtered_out_everything_widget), label, TRUE, TRUE, 15); - app_data->filtered_out_everything_widget_label = GTK_LABEL (label); - } - - str1 = g_markup_printf_escaped ("<b>%s</b>", app_data->filter_string); - str2 = g_strdup_printf (_("Your filter \"%s\" does not match any items."), str1); - markup = g_strdup_printf ("<span size=\"large\"><b>%s</b></span>\n\n%s", - _("No matches found."), str2); - gtk_label_set_text (app_data->filtered_out_everything_widget_label, markup); - gtk_label_set_use_markup (app_data->filtered_out_everything_widget_label, TRUE); - gtk_box_pack_start (GTK_BOX (containing_vbox), app_data->filtered_out_everything_widget, - TRUE, TRUE, 0); - g_free (str1); - g_free (str2); - g_free (markup); -} - -static void -populate_application_category_sections (AppShellData * app_data, GtkWidget * containing_vbox) -{ - GList *cat_list = app_data->categories_list; - gboolean filtered_out_everything = TRUE; - if (app_data->cached_tables_list) - g_list_free (app_data->cached_tables_list); - app_data->cached_tables_list = NULL; - - remove_container_entries (GTK_CONTAINER (containing_vbox)); - do - { - CategoryData *data = (CategoryData *) cat_list->data; - if (NULL != data->filtered_launcher_list) - { - populate_application_category_section (app_data, data->section, - data->filtered_launcher_list); - gtk_box_pack_start (GTK_BOX (containing_vbox), GTK_WIDGET (data->section), - TRUE, TRUE, 0); - filtered_out_everything = FALSE; - } - } - while (NULL != (cat_list = g_list_next (cat_list))); - - if (TRUE == filtered_out_everything) - show_no_results_message (app_data, containing_vbox); -} - -static void -populate_application_category_section (AppShellData * app_data, SlabSection * section, - GList * launcher_list) -{ - GtkWidget *hbox; - GtkGrid *table; - GList *children; - - hbox = GTK_WIDGET (section->contents); - - children = gtk_container_get_children (GTK_CONTAINER (hbox)); - table = children->data; - g_list_free (children); - - /* Make sure our implementation has not changed and it's still a GtkGrid */ - g_assert (GTK_IS_GRID (table)); - - app_data->cached_tables_list = g_list_append (app_data->cached_tables_list, table); - - app_resizer_layout_table_default (APP_RESIZER (app_data->category_layout), table, - launcher_list); - -} - -gboolean -regenerate_categories (AppShellData * app_data) -{ - delete_old_data (app_data); - generate_categories (app_data); - create_application_category_sections (app_data); - relayout_shell (app_data); - - return FALSE; /* remove this function from the list */ -} - -static void -matemenu_tree_changed_callback (MateMenuTree * old_tree, gpointer user_data) -{ - /* - This method only gets called on the first change (matemenu appears to ignore subsequent) until - we reget the root dir which we can't do in this method because if we do for some reason this - method then gets called multiple times for one actual change. This actually is okay because - it's probably a good idea to wait a couple seconds to regenerate the categories in case there - are multiple quick changes being made, no sense regenerating multiple times. - */ - GError *error = NULL; - AppShellData * app_data = user_data; - if (!matemenu_tree_load_sync (app_data->tree, &error)) { - g_warning ("Menu tree loading got error:%s\n", error->message); - g_object_unref (app_data->tree); - app_data->tree = NULL; - g_error_free (error); - } else { - g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 3000, (GSourceFunc) regenerate_categories, - user_data, NULL); - } -} - -AppShellData * -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); - app_data->menu_name = menu_name; - app_data->icon_size = icon_size; - 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; -} - -void -generate_categories (AppShellData * app_data) -{ - MateMenuTreeDirectory *root_dir; - gboolean need_misc = FALSE; - MateMenuTreeIter *iter; - MateMenuTreeItemType type; - - if (!app_data->tree) - { - GError *error = NULL; - - app_data->tree = matemenu_tree_new (app_data->menu_name, MATEMENU_TREE_FLAGS_NONE); - g_signal_connect (app_data->tree, "changed", G_CALLBACK (matemenu_tree_changed_callback), app_data); - if (! matemenu_tree_load_sync (app_data->tree, &error)) { - g_warning("Menu tree loading got error:%s\n", error->message); - g_error_free(error); - g_object_unref(app_data->tree); - app_data->tree = NULL; - } - } - - if (app_data->tree != NULL) - root_dir = matemenu_tree_get_root_directory (app_data->tree); - else - root_dir = NULL; - - if ( app_data->tree == NULL || root_dir == NULL) { - GtkWidget *dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Failure loading - %s", - app_data->menu_name); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - exit (1); /* Fixme - is there a MATE/GTK way to do this. */ - } - - iter = matemenu_tree_directory_iter (root_dir); - while ((type = matemenu_tree_iter_next (iter)) != MATEMENU_TREE_ITEM_INVALID) { - gpointer item; - const char *category; - switch (type) { - case MATEMENU_TREE_ITEM_DIRECTORY: - item = matemenu_tree_iter_get_directory (iter); - category = matemenu_tree_directory_get_name (item); - generate_category(category, item, app_data, TRUE); - matemenu_tree_item_unref (item); - break; - case MATEMENU_TREE_ITEM_ENTRY: - need_misc = TRUE; - break; - default: - break; - } - } - matemenu_tree_iter_unref(iter); - - if (need_misc) - generate_category (_("Other"), root_dir, app_data, FALSE); - - if (app_data->hash) - { - g_hash_table_destroy (app_data->hash); - app_data->hash = NULL; - } - - 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 -generate_category (const char * category, MateMenuTreeDirectory * root_dir, AppShellData * app_data, gboolean recursive) -{ - CategoryData *data; - /* This is not needed. MateMenu already returns an ordered, non duplicate list - GList *list_entry; - list_entry = - g_list_find_custom (app_data->categories_list, category, - category_name_compare); - if (!list_entry) - { - */ - data = g_new0 (CategoryData, 1); - data->category = g_strdup (category); - app_data->categories_list = - /* use the matemenu order instead of alphabetical */ - g_list_append (app_data->categories_list, data); - /* g_list_insert_sorted (app_data->categories_list, data, category_data_compare); */ - /* - } - else - { - data = list_entry->data; - } - */ - - if (app_data->hash) /* used to eliminate dups on a per category basis. */ - g_hash_table_destroy (app_data->hash); - app_data->hash = g_hash_table_new (g_str_hash, g_str_equal); - generate_launchers (root_dir, app_data, data, recursive); -} - -static gboolean -check_specific_apps_hack (MateDesktopItem * item) -{ - static const gchar *COMMAND_LINE_LOCKDOWN_SCHEMA = "org.mate.lockdown"; - static const gchar *COMMAND_LINE_LOCKDOWN_KEY = "disable-command-line"; - static const gchar *COMMAND_LINE_LOCKDOWN_DESKTOP_CATEGORY = "TerminalEmulator"; - static gboolean got_lockdown_value = FALSE; - static gboolean command_line_lockdown; - - gchar *path; - const char *exec; - - if (!got_lockdown_value) - { - got_lockdown_value = TRUE; - GSettings *lockdown_settings; - lockdown_settings = g_settings_new (COMMAND_LINE_LOCKDOWN_SCHEMA); - command_line_lockdown = g_settings_get_boolean (lockdown_settings, COMMAND_LINE_LOCKDOWN_KEY); - g_object_unref (lockdown_settings); - } - - /* This seems like an ugly hack but it's the way it's currently done in the old control center */ - exec = mate_desktop_item_get_string (item, MATE_DESKTOP_ITEM_EXEC); - - /* discard xscreensaver if mate-screensaver is installed */ - if ((exec && !strcmp (exec, "xscreensaver-demo")) - && (path = g_find_program_in_path ("mate-screensaver-preferences"))) - { - g_free (path); - return TRUE; - } - - /* discard gnome-keyring-manager if CASA is installed */ - if ((exec && !strcmp (exec, "gnome-keyring-manager")) - && (path = g_find_program_in_path ("CASAManager.sh"))) - { - g_free (path); - return TRUE; - } - - /* discard terminals if lockdown key is set */ - if (command_line_lockdown) - { - const gchar *categories = - mate_desktop_item_get_string (item, MATE_DESKTOP_ITEM_CATEGORIES); - if (g_strrstr (categories, COMMAND_LINE_LOCKDOWN_DESKTOP_CATEGORY)) - { - return TRUE; - } - } - - return FALSE; -} - -static void -generate_launchers (MateMenuTreeDirectory * root_dir, AppShellData * app_data, CategoryData * cat_data, gboolean recursive) -{ - MateDesktopItem *desktop_item; - const gchar *desktop_file; - MateMenuTreeIter *iter; - MateMenuTreeItemType type; - - iter = matemenu_tree_directory_iter (root_dir); - while ((type = matemenu_tree_iter_next (iter)) != MATEMENU_TREE_ITEM_INVALID) { - gpointer item; - switch (type) { - case MATEMENU_TREE_ITEM_DIRECTORY: - item = matemenu_tree_iter_get_directory(iter); - /* g_message ("Found sub-category %s", matemenu_tree_directory_get_name (item)); */ - if (recursive) - generate_launchers (item, app_data, cat_data, TRUE); - matemenu_tree_item_unref (item); - break; - case MATEMENU_TREE_ITEM_ENTRY: - item = matemenu_tree_iter_get_entry(iter); - /* g_message ("Found item name is:%s", matemenu_tree_entry_get_desktop_file_id(item)); */ - desktop_file = matemenu_tree_entry_get_desktop_file_path (item); - if (desktop_file) - { - if (g_hash_table_lookup (app_data->hash, desktop_file)) - { - break; /* duplicate */ - } - /* Fixme - make sure it's safe to store this without duping it. As far as I can tell it is - safe as long as I don't hang on to this anylonger than I hang on to the MateMenuTreeEntry* - which brings up another point - am I supposed to free these or does freeing the top level recurse - */ - g_hash_table_insert (app_data->hash, (gpointer) desktop_file, - (gpointer) desktop_file); - } - desktop_item = mate_desktop_item_new_from_file (desktop_file, 0, NULL); - if (!desktop_item) - { - g_critical ("Failure - mate_desktop_item_new_from_file(%s)", - desktop_file); - break; - } - if (!check_specific_apps_hack (desktop_item)) - insert_launcher_into_category (cat_data, desktop_item, app_data); - mate_desktop_item_unref (desktop_item); - matemenu_tree_item_unref (item); - break; - default: - break; - } - } - matemenu_tree_iter_unref(iter); -} - -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 */ - 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); - if (new_apps_category) { - g_free (new_apps_category->category); - g_free (new_apps_category); - } - g_free (all_apps_file_name); - g_strfreev (all_apps_split); - 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) -{ - GtkWidget *launcher; - static GtkSizeGroup *icon_group = NULL; - - gchar *filepath; - gchar *filename; - GtkWidget *tile_icon; - - if (!icon_group) - icon_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); - - launcher = - application_tile_new_full (mate_desktop_item_get_location (desktop_item), - app_data->icon_size, app_data->show_tile_generic_name); - gtk_widget_set_size_request (launcher, SIZING_TILE_WIDTH, -1); - - filepath = - g_strdup (mate_desktop_item_get_string (desktop_item, MATE_DESKTOP_ITEM_EXEC)); - g_strdelimit (filepath, " ", '\0'); /* just want the file name - no args or replacements */ - filename = g_strrstr (filepath, "/"); - if (filename) - g_stpcpy (filepath, filename + 1); - filename = g_ascii_strdown (filepath, -1); - g_free (filepath); - g_object_set_data (G_OBJECT (launcher), TILE_EXEC_NAME, filename); - - tile_icon = NAMEPLATE_TILE (launcher)->image; - gtk_size_group_add_widget (icon_group, tile_icon); - - g_signal_connect (launcher, "tile-activated", G_CALLBACK (tile_activated_cb), app_data); - - /* Note that this will handle the case of the action being launched via the side panel as - well as directly from the context menu of an individual launcher, because they both - funnel through tile_button_action_activate. - */ - g_signal_connect (launcher, "tile-action-triggered", - G_CALLBACK (handle_menu_action_performed), app_data); - - /* These will be inserted/removed from tables as the filter changes and we dont want them */ - /* destroyed when they are removed */ - g_object_ref (launcher); - - /* use alphabetical order instead of the matemenu order. We group all sub items in each top level - category together, ignoring sub menus, so we also ignore sub menu layout hints */ - cat_data->launcher_list = - /* g_list_insert (cat_data->launcher_list, launcher, -1); */ - g_list_insert_sorted (cat_data->launcher_list, launcher, application_launcher_compare); - cat_data->filtered_launcher_list = - /* g_list_insert (cat_data->filtered_launcher_list, launcher, -1); */ - g_list_insert_sorted (cat_data->filtered_launcher_list, launcher, application_launcher_compare); -} - -static gint -application_launcher_compare (gconstpointer a, gconstpointer b) -{ - ApplicationTile *launcher1 = APPLICATION_TILE (a); - ApplicationTile *launcher2 = APPLICATION_TILE (b); - - gchar *val1 = launcher1->name; - gchar *val2 = launcher2->name; - - if (val1 == NULL || val2 == NULL) - { - g_assert_not_reached (); - } - return g_ascii_strcasecmp (val1, val2); -} - -static void -application_launcher_clear_search_bar (AppShellData * app_data) -{ - SlabSection *section = SLAB_SECTION (app_data->filter_section); - NldSearchBar *search_bar; - g_assert (NLD_IS_SEARCH_BAR (section->contents)); - search_bar = NLD_SEARCH_BAR (section->contents); - nld_search_bar_set_text (search_bar, "", TRUE); -} - -/* -static gint -category_name_compare (gconstpointer a, gconstpointer b) -{ - CategoryData *data = (CategoryData *) a; - const gchar *category = b; - - if (category == NULL || data->category == NULL) - { - g_assert_not_reached (); - } - return g_ascii_strcasecmp (category, data->category); -} -*/ - -static void -tile_activated_cb (Tile * tile, TileEvent * event, gpointer user_data) -{ - switch (event->type) - { - case TILE_EVENT_ACTIVATED_SINGLE_CLICK: - case TILE_EVENT_ACTIVATED_KEYBOARD: - handle_launcher_single_clicked (tile, user_data); - break; - default: - break; - } - -} - -static void -handle_launcher_single_clicked (Tile * launcher, gpointer data) -{ - GApplication *app; - AppShellData *app_data = (AppShellData *) data; - - tile_trigger_action (launcher, launcher->actions[APPLICATION_TILE_ACTION_START]); - - if (g_settings_get_boolean (app_data->settings, EXIT_SHELL_ON_ACTION_START)) - { - if (app_data->exit_on_close) - { - app=g_application_get_default(); - g_application_quit(app); - } - else - hide_shell (app_data); - } -} - -static void -handle_menu_action_performed (Tile * launcher, TileEvent * event, TileAction * action, - gpointer data) -{ - GApplication *app; - AppShellData *app_data = (AppShellData *) data; - gchar *temp; - - temp = NULL; - if (action == launcher->actions[APPLICATION_TILE_ACTION_START]) - { - temp = EXIT_SHELL_ON_ACTION_START; - } - - else if (action == launcher->actions[APPLICATION_TILE_ACTION_HELP]) - { - temp = EXIT_SHELL_ON_ACTION_HELP; - } - - else if (action == launcher->actions[APPLICATION_TILE_ACTION_UPDATE_MAIN_MENU] - || action == launcher->actions[APPLICATION_TILE_ACTION_UPDATE_STARTUP]) - { - temp = EXIT_SHELL_ON_ACTION_ADD_REMOVE; - } - - else if (action == launcher->actions[APPLICATION_TILE_ACTION_UPGRADE_PACKAGE] - || action == launcher->actions[APPLICATION_TILE_ACTION_UNINSTALL_PACKAGE]) - { - temp = EXIT_SHELL_ON_ACTION_UPGRADE_UNINSTALL; - } - - if (temp) - { - if (g_settings_get_boolean (app_data->settings, temp)) - { - if (app_data->exit_on_close) - { - app=g_application_get_default(); - g_application_quit(app); - } - else - hide_shell (app_data); - } - } - else - g_warning ("Unknown Action"); -} |