diff options
author | Perberos <[email protected]> | 2011-12-01 22:56:10 -0300 |
---|---|---|
committer | Perberos <[email protected]> | 2011-12-01 22:56:10 -0300 |
commit | c51ef797a707f4e2c6f9688d4378f2b0e9898a66 (patch) | |
tree | 019ae92bb53c19b30077545cb14743cbd1b57aef /mate-panel/launcher.c | |
download | mate-panel-c51ef797a707f4e2c6f9688d4378f2b0e9898a66.tar.bz2 mate-panel-c51ef797a707f4e2c6f9688d4378f2b0e9898a66.tar.xz |
moving from https://github.com/perberos/mate-desktop-environment
Diffstat (limited to 'mate-panel/launcher.c')
-rw-r--r-- | mate-panel/launcher.c | 1114 |
1 files changed, 1114 insertions, 0 deletions
diff --git a/mate-panel/launcher.c b/mate-panel/launcher.c new file mode 100644 index 00000000..657bc0c8 --- /dev/null +++ b/mate-panel/launcher.c @@ -0,0 +1,1114 @@ +/* + * MATE panel launcher module. + * (C) 1997,1998,1999,2000 The Free Software Foundation + * (C) 2000 Eazel, Inc. + * + * Authors: Miguel de Icaza + * Federico Mena + * CORBAized by George Lebl + * de-CORBAized by George Lebl + * + */ + +#include <config.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <dirent.h> +#include <string.h> + +#include <glib/gi18n.h> +#include <gio/gio.h> +#include <gdk/gdkx.h> + +#include <libpanel-util/panel-error.h> +#include <libpanel-util/panel-glib.h> +#include <libpanel-util/panel-keyfile.h> +#include <libpanel-util/panel-launch.h> +#include <libpanel-util/panel-show.h> + +#include "launcher.h" + +#include "button-widget.h" +#include "panel-util.h" +#include "panel-config-global.h" +#include "panel-mateconf.h" +#include "panel-profile.h" +#include "xstuff.h" +#include "panel-toplevel.h" +#include "panel-a11y.h" +#include "panel-globals.h" +#include "panel-multiscreen.h" +#include "panel-lockdown.h" +#include "panel-compatibility.h" +#include "panel-ditem-editor.h" +#include "panel-icon-names.h" + +static GdkScreen * +launcher_get_screen (Launcher *launcher) +{ + PanelWidget *panel_widget; + + g_return_val_if_fail (launcher != NULL, NULL); + g_return_val_if_fail (launcher->info != NULL, NULL); + g_return_val_if_fail (launcher->info->widget != NULL, NULL); + + panel_widget = PANEL_WIDGET (gtk_widget_get_parent (launcher->info->widget)); + + return gtk_window_get_screen (GTK_WINDOW (panel_widget->toplevel)); +} + +static void +launcher_widget_open_dialog_destroyed (GtkWidget *dialog, + Launcher *launcher) +{ + g_return_if_fail (launcher->error_dialogs != NULL); + + launcher->error_dialogs = g_slist_remove (launcher->error_dialogs, dialog); +} + +static void +launcher_widget_destroy_open_dialogs (Launcher *launcher) +{ + GSList *l, *list; + + list = launcher->error_dialogs; + launcher->error_dialogs = NULL; + + for (l = list; l; l = l->next) { + g_signal_handlers_disconnect_by_func (G_OBJECT (l->data), + G_CALLBACK (launcher_widget_open_dialog_destroyed), + launcher); + gtk_widget_destroy (l->data); + } + g_slist_free (list); +} + +static void +launcher_register_error_dialog (Launcher *launcher, + GtkWidget *dialog) +{ + launcher->error_dialogs = g_slist_append (launcher->error_dialogs, + dialog); + g_signal_connect (dialog, "destroy", + G_CALLBACK (launcher_widget_open_dialog_destroyed), + launcher); +} + +static void +launch_url (Launcher *launcher) +{ + char *url; + GdkScreen *screen; + + g_return_if_fail (launcher != NULL); + g_return_if_fail (launcher->key_file != NULL); + + /* FIXME panel_ditem_launch() should be enough for this! */ + url = panel_key_file_get_string (launcher->key_file, "URL"); + + screen = launcher_get_screen (launcher); + + if (!url || *url == 0) { + GtkWidget *error_dialog; + + error_dialog = panel_error_dialog (NULL, screen, + "no_url_dialog", TRUE, + _("Could not show this URL"), + _("No URL was specified.")); + launcher_register_error_dialog (launcher, error_dialog); + g_free (url); + return; + } + + panel_show_uri (screen, url, gtk_get_current_event_time (), NULL); + + g_free (url); +} + +void +launcher_launch (Launcher *launcher, + GtkWidget *widget) +{ + char *type; + + g_return_if_fail (launcher != NULL); + g_return_if_fail (launcher->key_file != NULL); + + if (panel_global_config_get_enable_animations ()) + xstuff_zoom_animate (widget, + button_widget_get_pixbuf (BUTTON_WIDGET (widget)), + button_widget_get_orientation (BUTTON_WIDGET (widget)), + NULL); + + type = panel_key_file_get_string (launcher->key_file, "Type"); + if (type && !strcmp (type, "Link")) + launch_url (launcher); + else { + GError *error = NULL; + + panel_launch_key_file (launcher->key_file, NULL, + launcher_get_screen (launcher), &error); + if (error) { + GtkWidget *error_dialog; + + error_dialog = panel_error_dialog ( + NULL, + launcher_get_screen (launcher), + "cannot_launch_application", + TRUE, + _("Could not launch application"), + error->message); + launcher_register_error_dialog (launcher, error_dialog); + g_clear_error (&error); + } + } + g_free (type); + + if (panel_global_config_get_drawer_auto_close ()) { + PanelToplevel *toplevel; + PanelToplevel *parent; + + toplevel = PANEL_WIDGET (gtk_widget_get_parent (launcher->button))->toplevel; + + if (panel_toplevel_get_is_attached (toplevel)) { + parent = panel_toplevel_get_attach_toplevel (toplevel); + + while (panel_toplevel_get_is_attached (parent)) { + toplevel = parent; + parent = panel_toplevel_get_attach_toplevel (toplevel); + } + + panel_toplevel_hide (toplevel, FALSE, -1); + } + } +} + +static void +drag_data_received_cb (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time, + Launcher *launcher) +{ + GError *error = NULL; + char **uris; + int i; + GList *file_list; + + if (panel_global_config_get_enable_animations ()) + xstuff_zoom_animate (widget, + button_widget_get_pixbuf (BUTTON_WIDGET (widget)), + button_widget_get_orientation (BUTTON_WIDGET (widget)), + NULL); + + file_list = NULL; + uris = g_uri_list_extract_uris ((const char *) gtk_selection_data_get_data (selection_data)); + for (i = 0; uris[i]; i++) + file_list = g_list_prepend (file_list, uris[i]); + file_list = g_list_reverse (file_list); + + panel_launch_key_file (launcher->key_file, file_list, + launcher_get_screen (launcher), &error); + + g_list_free (file_list); + g_strfreev (uris); + + if (error) { + GtkWidget *error_dialog; + error_dialog = panel_error_dialog (NULL, + launcher_get_screen (launcher), + "cannot_use_dropped_item", + TRUE, + _("Could not use dropped item"), + error->message); + launcher_register_error_dialog (launcher, error_dialog); + g_clear_error (&error); + } + + gtk_drag_finish (context, TRUE, FALSE, time); +} + +static void +destroy_launcher (GtkWidget *widget, + Launcher *launcher) +{ + launcher_properties_destroy (launcher); + launcher_widget_destroy_open_dialogs (launcher); +} + +void +launcher_properties_destroy (Launcher *launcher) +{ + GtkWidget *dialog; + + dialog = launcher->prop_dialog; + launcher->prop_dialog = NULL; + + if (dialog) + gtk_widget_destroy (dialog); +} + +static void +free_launcher (gpointer data) +{ + Launcher *launcher = data; + + if (launcher->key_file) + g_key_file_free (launcher->key_file); + launcher->key_file = NULL; + + if (launcher->location != NULL) + g_free (launcher->location); + launcher->location = NULL; + + g_free (launcher); +} + +void +panel_launcher_delete (Launcher *launcher) +{ + if (!launcher->location) + return; + + /* do not remove the file if it's not in the user's launchers path */ + if (panel_launcher_is_in_personal_path (launcher->location)) { + GError *error; + GFile *file; + + file = panel_launcher_get_gfile (launcher->location); + + error = NULL; + if (!g_file_delete (file, NULL, &error)) { + char *path; + + path = g_file_get_path (file); + g_warning ("Error deleting '%s': %s\n", + path, error->message); + g_free (path); + g_error_free (error); + } + + g_object_unref (file); + } +} + +static gboolean +is_this_drop_ok (GtkWidget *widget, + GdkDragContext *context) +{ + static GdkAtom text_uri_list = GDK_NONE; + GList *l; + GtkWidget *source; + + source = gtk_drag_get_source_widget (context); + + if (source == widget) + return FALSE; + + if (!(gdk_drag_context_get_actions (context) & GDK_ACTION_COPY)) + return FALSE; + + if (!text_uri_list) + text_uri_list = gdk_atom_intern_static_string ("text/uri-list"); + + for (l = gdk_drag_context_list_targets (context); l; l = l->next) { + if (GDK_POINTER_TO_ATOM (l->data) == text_uri_list) + break; + } + + return l ? TRUE : FALSE; +} + +static void +drag_leave_cb(GtkWidget *widget, + GdkDragContext *context, + guint time, + Launcher *launcher) +{ + button_widget_set_dnd_highlight(BUTTON_WIDGET(widget), FALSE); +} + + +static gboolean +drag_motion_cb(GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time, + Launcher *launcher) +{ + if ( ! is_this_drop_ok (widget, context)) + return FALSE; + + gdk_drag_status (context, GDK_ACTION_COPY, time); + + button_widget_set_dnd_highlight(BUTTON_WIDGET(widget), TRUE); + + return TRUE; +} + +static gboolean +drag_drop_cb (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time, + Launcher *launcher) +{ + static GdkAtom text_uri_list = NULL; + + if ( ! is_this_drop_ok (widget, context)) + return FALSE; + + if (text_uri_list == NULL) + text_uri_list = gdk_atom_intern_static_string ("text/uri-list"); + + gtk_drag_get_data (widget, context, text_uri_list, time); + + return TRUE; +} + +enum { + TARGET_ICON_INTERNAL, + TARGET_URI_LIST +}; + + +static void +drag_data_get_cb (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time, + Launcher *launcher) +{ + char *location; + + g_return_if_fail (launcher != NULL); + + location = launcher->location; + + if (info == TARGET_URI_LIST) { + char *uri[2]; + + uri[0] = panel_launcher_get_uri (location); + uri[1] = NULL; + + gtk_selection_data_set_uris (selection_data, uri); + + g_free (uri[0]); + } else if (info == TARGET_ICON_INTERNAL) + gtk_selection_data_set (selection_data, + gtk_selection_data_get_target (selection_data), 8, + (unsigned char *) location, + strlen (location)); + +} + +static Launcher * +create_launcher (const char *location) +{ + GKeyFile *key_file; + gboolean loaded; + Launcher *launcher; + GError *error = NULL; + char *new_location; + + if (!location) { + g_printerr (_("No URI provided for panel launcher desktop file\n")); + return NULL; + } + + new_location = NULL; + key_file = g_key_file_new (); + + if (!strchr (location, G_DIR_SEPARATOR)) { + /* try to first load a file in our config directory, and if it + * doesn't exist there, try to find it in the xdg data dirs */ + char *path; + + path = panel_make_full_path (NULL, location); + + if (!g_file_test (path, G_FILE_TEST_EXISTS)) { + g_free (path); + path = panel_g_lookup_in_applications_dirs (location); + /* it's important to keep the full path if the desktop + * file comes from a data dir: when the user will edit + * it, we'll want to save it in PANEL_LAUNCHERS_PATH + * with a random name (and not evolution.desktop, eg) + * and having only a basename as location will make + * this impossible */ + if (path) + new_location = g_strdup (path); + } + + if (path) { + loaded = g_key_file_load_from_file (key_file, path, + G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS, + &error); + g_free (path); + } + } else + loaded = panel_key_file_load_from_uri (key_file, location, + G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS, + &error); + + if (!loaded) { + g_printerr (_("Unable to open desktop file %s for panel launcher%s%s\n"), + location, + error ? ": " : "", + error ? error->message : ""); + if (error) + g_error_free (error); + + g_key_file_free (key_file); + + return NULL; /*button is null*/ + } + + if (!new_location) + new_location = g_strdup (location); + + launcher = g_new0 (Launcher, 1); + + launcher->info = NULL; + launcher->button = NULL; + launcher->location = new_location; + launcher->key_file = key_file; + launcher->prop_dialog = NULL; + launcher->destroy_handler = 0; + + /* Icon will be setup later */ + launcher->button = button_widget_new (NULL /* icon */, + FALSE, + PANEL_ORIENTATION_TOP); + + gtk_widget_show (launcher->button); + + /*gtk_drag_dest_set (GTK_WIDGET (launcher->button), + GTK_DEST_DEFAULT_ALL, + dnd_targets, 2, + GDK_ACTION_COPY);*/ + gtk_drag_dest_set (GTK_WIDGET (launcher->button), + 0, NULL, 0, 0); + + g_signal_connect (launcher->button, "drag_data_get", + G_CALLBACK (drag_data_get_cb), launcher); + g_signal_connect (launcher->button, "drag_data_received", + G_CALLBACK (drag_data_received_cb), launcher); + g_signal_connect (launcher->button, "drag_motion", + G_CALLBACK (drag_motion_cb), launcher); + g_signal_connect (launcher->button, "drag_drop", + G_CALLBACK (drag_drop_cb), launcher); + g_signal_connect (launcher->button, "drag_leave", + G_CALLBACK (drag_leave_cb), launcher); + g_signal_connect_swapped (launcher->button, "clicked", + G_CALLBACK (launcher_launch), launcher); + + launcher->destroy_handler = + g_signal_connect (launcher->button, "destroy", + G_CALLBACK (destroy_launcher), + launcher); + + return launcher; +} + +static void +setup_button (Launcher *launcher) +{ + char *comment; + char *name; + char *str; + char *icon; + char *unescaped_str; + + g_return_if_fail (launcher != NULL); + + name = panel_key_file_get_locale_string (launcher->key_file, "Name"); + comment = panel_key_file_get_locale_string (launcher->key_file, + "Comment"); + + /* Setup tooltip */ + if (!PANEL_GLIB_STR_EMPTY (name) && !PANEL_GLIB_STR_EMPTY (comment)) + str = g_strdup_printf ("%s\n%s", name, comment); + else if (!PANEL_GLIB_STR_EMPTY (name)) + str = g_strdup (name); + else + str = g_strdup (comment); + + g_free (name); + g_free (comment); + + /* If we can unescape the string, then we probably have an escaped + * string (a location e.g.). If we can't, then it most probably means + * we have a % that is not here to encode a character, and we don't + * want to unescape in this case. See bug #170516 for details. */ + unescaped_str = g_uri_unescape_string (str, NULL); + if (unescaped_str) { + g_free (str); + str = unescaped_str; + } + + panel_util_set_tooltip_text (launcher->button, str); + + /* Setup accessible name */ + panel_a11y_set_atk_name_desc (launcher->button, str, NULL); + + g_free (str); + + /* Setup icon */ + icon = panel_key_file_get_locale_string (launcher->key_file, "Icon"); + if (icon && icon[0] == '\0') { + g_free (icon); + icon = NULL; + } + + if (!icon) + icon = guess_icon_from_exec (button_widget_get_icon_theme (BUTTON_WIDGET (launcher->button)), + launcher->key_file); + if (!icon) + icon = g_strdup (PANEL_ICON_LAUNCHER); + + button_widget_set_icon_name (BUTTON_WIDGET (launcher->button), icon); + g_free (icon); +} + +static char * +panel_launcher_find_writable_uri (const char *launcher_location, + const char *source) +{ + char *path; + char *uri; + + if (!launcher_location) + return panel_make_unique_desktop_uri (NULL, source); + + if (!strchr (launcher_location, G_DIR_SEPARATOR)) { + path = panel_make_full_path (NULL, launcher_location); + uri = g_filename_to_uri (path, NULL, NULL); + g_free (path); + return uri; + } + + if (panel_launcher_get_filename (launcher_location) != NULL) { + /* we have a file in the user directory. We either have a path + * or an URI */ + if (g_path_is_absolute (launcher_location)) + return g_filename_to_uri (launcher_location, + NULL, NULL); + else + return g_strdup (launcher_location); + } + + return panel_make_unique_desktop_uri (NULL, source); +} + +static void +launcher_changed (PanelDItemEditor *dialog, + Launcher *launcher) +{ + /* Setup the button look */ + setup_button (launcher); +} + +static void +launcher_command_changed (PanelDItemEditor *dialog, + const char *command, + Launcher *launcher) +{ + char *exec; + char *old_exec; + GKeyFile *revert_key_file; + + revert_key_file = panel_ditem_editor_get_revert_key_file (dialog); + + if (revert_key_file) { + exec = panel_key_file_get_string (launcher->key_file, "Exec"); + old_exec = panel_key_file_get_string (revert_key_file, "Exec"); + + if (!old_exec || !exec || strcmp (old_exec, exec)) + panel_key_file_remove_key (launcher->key_file, + "StartupNotify"); + + g_free (exec); + g_free (old_exec); + } +} + +static char * +launcher_save_uri (PanelDItemEditor *dialog, + gpointer data) +{ + GKeyFile *key_file; + char *type; + char *exec_or_uri; + Launcher *launcher; + char *new_uri; + const char *uri; + + key_file = panel_ditem_editor_get_key_file (dialog); + type = panel_key_file_get_string (key_file, "Type"); + if (type && !strcmp (type, "Application")) + exec_or_uri = panel_key_file_get_string (key_file, "Exec"); + else if (type && !strcmp (type, "Link")) + exec_or_uri = panel_key_file_get_string (key_file, "URL"); + else + exec_or_uri = panel_key_file_get_string (key_file, "Name"); + g_free (type); + + launcher = (Launcher *) data; + + if (launcher) + new_uri = panel_launcher_find_writable_uri (launcher->location, + exec_or_uri); + else + new_uri = panel_launcher_find_writable_uri (NULL, exec_or_uri); + + g_free (exec_or_uri); + + uri = panel_ditem_editor_get_uri (dialog); + + if (!uri || (new_uri && strcmp (new_uri, uri))) + return new_uri; + + g_free (new_uri); + + return NULL; +} + +static void +launcher_saved (GtkWidget *dialog, + Launcher *launcher) +{ + const char *uri; + MateConfClient *client; + const char *key; + + uri = panel_ditem_editor_get_uri (PANEL_DITEM_EDITOR (dialog)); + if (panel_launcher_get_filename (uri) != NULL) + uri = panel_launcher_get_filename (uri); + + if (uri && launcher->location && strcmp (uri, launcher->location)) { + client = panel_mateconf_get_client (); + + key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, + launcher->info->id, + "launcher_location"); + + mateconf_client_set_string (client, key, uri, NULL); + + if (launcher->location) + g_free (launcher->location); + launcher->location = g_strdup (uri); + } +} + +static void +launcher_error_reported (GtkWidget *dialog, + const char *primary, + const char *secondary, + gpointer data) +{ + panel_error_dialog (GTK_WINDOW (dialog), NULL, + "error_editing_launcher", TRUE, + primary, secondary); +} + +void +launcher_properties (Launcher *launcher) +{ + if (launcher->prop_dialog != NULL) { + gtk_window_set_screen (GTK_WINDOW (launcher->prop_dialog), + gtk_widget_get_screen (launcher->button)); + gtk_window_present (GTK_WINDOW (launcher->prop_dialog)); + return; + } + + launcher->prop_dialog = panel_ditem_editor_new (NULL, + launcher->key_file, + launcher->location, + _("Launcher Properties")); + + panel_widget_register_open_dialog (PANEL_WIDGET + (gtk_widget_get_parent (launcher->info->widget)), + launcher->prop_dialog); + + panel_ditem_register_save_uri_func (PANEL_DITEM_EDITOR (launcher->prop_dialog), + launcher_save_uri, + launcher); + + g_signal_connect (launcher->prop_dialog, "changed", + G_CALLBACK (launcher_changed), launcher); + + g_signal_connect (launcher->prop_dialog, "command_changed", + G_CALLBACK (launcher_command_changed), launcher); + + g_signal_connect (launcher->prop_dialog, "saved", + G_CALLBACK (launcher_saved), launcher); + + g_signal_connect (launcher->prop_dialog, "error_reported", + G_CALLBACK (launcher_error_reported), NULL); + + g_signal_connect (launcher->prop_dialog, "destroy", + G_CALLBACK (gtk_widget_destroyed), + &launcher->prop_dialog); + + gtk_widget_show (launcher->prop_dialog); +} + +static gboolean +lancher_properties_enabled (void) +{ + if (panel_lockdown_get_locked_down () || + panel_lockdown_get_disable_command_line ()) + return FALSE; + + return TRUE; +} + +static Launcher * +load_launcher_applet (const char *location, + PanelWidget *panel, + gboolean locked, + int pos, + gboolean exactpos, + const char *id) +{ + Launcher *launcher; + + launcher = create_launcher (location); + + if (!launcher) + return NULL; + + launcher->info = mate_panel_applet_register (launcher->button, launcher, + free_launcher, + panel, locked, pos, exactpos, + PANEL_OBJECT_LAUNCHER, id); + if (!launcher->info) { + free_launcher (launcher); + return NULL; + } + + mate_panel_applet_add_callback (launcher->info, + "launch", + GTK_STOCK_EXECUTE, + _("_Launch"), + NULL); + + mate_panel_applet_add_callback (launcher->info, + "properties", + GTK_STOCK_PROPERTIES, + _("_Properties"), + lancher_properties_enabled); + + panel_widget_set_applet_expandable (panel, GTK_WIDGET (launcher->button), FALSE, TRUE); + panel_widget_set_applet_size_constrained (panel, GTK_WIDGET (launcher->button), TRUE); + + /* setup button according to ditem */ + setup_button (launcher); + + return launcher; +} + +void +launcher_load_from_mateconf (PanelWidget *panel_widget, + gboolean locked, + int position, + const char *id) +{ + MateConfClient *client; + Launcher *launcher; + const char *key; + char *launcher_location; + + g_return_if_fail (panel_widget != NULL); + g_return_if_fail (id != NULL); + + client = panel_mateconf_get_client (); + + key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "launcher_location"); + panel_compatibility_migrate_applications_scheme (client, key); + launcher_location = mateconf_client_get_string (client, key, NULL); + + if (!launcher_location) { + g_printerr (_("Key %s is not set, cannot load launcher\n"), + key); + return; + } + + launcher = load_launcher_applet (launcher_location, + panel_widget, + locked, + position, + TRUE, + id); + + if (launcher) { + key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, id, "launcher_location"); + if (!mateconf_client_key_is_writable (client, key, NULL)) { + AppletUserMenu *menu; + + menu = mate_panel_applet_get_callback (launcher->info->user_menu, + "properties"); + if (menu != NULL) + menu->sensitive = FALSE; + } + } + + g_free (launcher_location); +} + +static void +launcher_new_saved (GtkWidget *dialog, + gpointer data) +{ + PanelWidget *panel; + int pos; + const char *uri; + + pos = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), "pos")); + panel = g_object_get_data (G_OBJECT (dialog), "panel"); + + uri = panel_ditem_editor_get_uri (PANEL_DITEM_EDITOR (dialog)); + if (panel_launcher_get_filename (uri) != NULL) + uri = panel_launcher_get_filename (uri); + panel_launcher_create (panel->toplevel, pos, uri); +} + +void +ask_about_launcher (const char *file, + PanelWidget *panel, + int pos, + gboolean exactpos) +{ + GtkWidget *dialog; + GKeyFile *key_file; + + if (panel_lockdown_get_disable_command_line ()) + return; + + dialog = panel_ditem_editor_new (NULL, NULL, NULL, + _("Create Launcher")); + panel_widget_register_open_dialog (panel, dialog); + + key_file = panel_ditem_editor_get_key_file (PANEL_DITEM_EDITOR (dialog)); + if (file != NULL) + panel_key_file_set_string (key_file, "Exec", file); + panel_key_file_set_string (key_file, "Type", "Application"); + panel_ditem_editor_sync_display (PANEL_DITEM_EDITOR (dialog)); + + panel_ditem_register_save_uri_func (PANEL_DITEM_EDITOR (dialog), + launcher_save_uri, + NULL); + + g_signal_connect (G_OBJECT (dialog), "saved", + G_CALLBACK (launcher_new_saved), NULL); + + g_signal_connect (G_OBJECT (dialog), "error_reported", + G_CALLBACK (launcher_error_reported), NULL); + + gtk_window_set_screen (GTK_WINDOW (dialog), + gtk_widget_get_screen (GTK_WIDGET (panel))); + + g_object_set_data (G_OBJECT (dialog), "pos", GINT_TO_POINTER (pos)); + g_object_set_data (G_OBJECT (dialog), "panel", panel); + + gtk_widget_show (dialog); +} + +void +panel_launcher_create_from_info (PanelToplevel *toplevel, + int position, + gboolean exec_info, + const char *exec_or_uri, + const char *name, + const char *comment, + const char *icon) +{ + GKeyFile *key_file; + char *location; + GError *error; + + key_file = panel_key_file_new_desktop (); + + /* set current language and the "C" locale to this name, + * this is kind of evil... */ + panel_key_file_set_string (key_file, "Name", name); + panel_key_file_set_string (key_file, "Comment", comment); + panel_key_file_set_string (key_file, "Icon", icon); + panel_key_file_set_locale_string (key_file, "Name", name); + panel_key_file_set_locale_string (key_file, "Comment", comment); + panel_key_file_set_locale_string (key_file, "Icon", icon); + + if (exec_info) { + panel_key_file_set_string (key_file, "Exec", exec_or_uri); + panel_key_file_set_string (key_file, "Type", "Application"); + } else { + panel_key_file_set_string (key_file, "URL", exec_or_uri); + panel_key_file_set_string (key_file, "Type", "Link"); + } + + location = panel_make_unique_desktop_uri (NULL, exec_or_uri); + + error = NULL; + if (panel_key_file_to_file (key_file, location, &error)) { + panel_launcher_create (toplevel, position, location); + } else { + panel_error_dialog (GTK_WINDOW (toplevel), + gtk_window_get_screen (GTK_WINDOW (toplevel)), + "cannot_save_launcher", TRUE, + _("Could not save launcher"), + error->message); + g_error_free (error); + } + + g_key_file_free (key_file); +} + +void +panel_launcher_create_with_id (const char *toplevel_id, + int position, + const char *location) +{ + MateConfClient *client; + const char *key; + char *id; + char *no_uri; + const char *new_location; + + g_return_if_fail (location != NULL); + + client = panel_mateconf_get_client (); + + id = panel_profile_prepare_object_with_id (PANEL_OBJECT_LAUNCHER, + toplevel_id, + position, + FALSE); + + no_uri = NULL; + /* if we have an URI, it might contain escaped characters (? : etc) + * that might get unescaped on disk */ + if (!g_ascii_strncasecmp (location, "file:", strlen ("file:"))) + no_uri = g_filename_from_uri (location, NULL, NULL); + if (!no_uri) + no_uri = g_strdup (location); + + new_location = panel_launcher_get_filename (no_uri); + if (new_location == NULL) + new_location = no_uri; + + key = panel_mateconf_full_key (PANEL_MATECONF_OBJECTS, + id, + "launcher_location"); + mateconf_client_set_string (client, key, new_location, NULL); + + panel_profile_add_to_list (PANEL_MATECONF_OBJECTS, id); + + g_free (no_uri); + g_free (id); +} + +void +panel_launcher_create (PanelToplevel *toplevel, + int position, + const char *location) +{ + panel_launcher_create_with_id (panel_profile_get_toplevel_id (toplevel), + position, + location); +} + +gboolean +panel_launcher_create_copy (PanelToplevel *toplevel, + int position, + const char *location) +{ + char *new_location; + GFile *source; + GFile *dest; + gboolean copied; + const char *filename; + + new_location = panel_make_unique_desktop_uri (NULL, location); + + source = panel_launcher_get_gfile (location); + dest = g_file_new_for_uri (new_location); + + copied = g_file_copy (source, dest, G_FILE_COPY_OVERWRITE, + NULL, NULL, NULL, NULL); + + if (!copied) { + g_free (new_location); + return FALSE; + } + + filename = panel_launcher_get_filename (new_location); + panel_launcher_create (toplevel, position, filename); + g_free (new_location); + + return TRUE; +} + +Launcher * +find_launcher (const char *path) +{ + GSList *l; + + g_return_val_if_fail (path != NULL, NULL); + + for (l = mate_panel_applet_list_applets (); l; l = l->next) { + AppletInfo *info = l->data; + Launcher *launcher; + + if (info->type != PANEL_OBJECT_LAUNCHER) + continue; + + launcher = info->data; + + if (launcher->key_file == NULL) + continue; + + if (launcher->location != NULL && + strcmp (launcher->location, path) == 0) + return launcher; + } + + return NULL; +} + +void +panel_launcher_set_dnd_enabled (Launcher *launcher, + gboolean dnd_enabled) +{ + GdkPixbuf *pixbuf; + + if (dnd_enabled) { + static GtkTargetEntry dnd_targets[] = { + { "application/x-panel-icon-internal", 0, TARGET_ICON_INTERNAL }, + { "text/uri-list", 0, TARGET_URI_LIST } + }; + + gtk_widget_set_has_window (launcher->button, TRUE); + gtk_drag_source_set (launcher->button, + GDK_BUTTON1_MASK, + dnd_targets, 2, + GDK_ACTION_COPY | GDK_ACTION_MOVE); + //FIXME: this doesn't work since the pixbuf isn't loaded yet + pixbuf = button_widget_get_pixbuf (BUTTON_WIDGET (launcher->button)); + if (pixbuf) { + gtk_drag_source_set_icon_pixbuf (launcher->button, + pixbuf); + g_object_unref (pixbuf); + } + gtk_widget_set_has_window (launcher->button, FALSE); + + + } else + gtk_drag_source_unset (launcher->button); +} |