From 58bda1f03a29e246083129911ac02db6bc24ac3a Mon Sep 17 00:00:00 2001 From: Jasper Huijsmans Date: Fri, 28 Dec 2007 11:06:30 +0100 Subject: [PATCH 3/4] Support 0install. Add support for DND of 0install URLs on the configuration dialog. New source file and header. Implementation is almost an exact copy of the 4.4 implementation by Thomas Leonard, without support for adding a new entry. --- plugins/launcher/Makefile.am | 4 +- plugins/launcher/launcher-dialog.c | 27 ++++- plugins/launcher/launcher-dialog.h | 12 ++- plugins/launcher/launcher-dnd-0install.c | 198 ++++++++++++++++++++++++++++++ plugins/launcher/launcher-dnd-0install.h | 39 ++++++ 5 files changed, 276 insertions(+), 4 deletions(-) diff --git a/plugins/launcher/Makefile.am b/plugins/launcher/Makefile.am index 27260ac..7fcb539 100644 --- a/plugins/launcher/Makefile.am +++ b/plugins/launcher/Makefile.am @@ -23,7 +23,9 @@ liblauncher_la_SOURCES = \ launcher-dialog.h \ launcher-dialog.c \ launcher-dnd.h \ - launcher-dnd.c + launcher-dnd.c \ + launcher-dnd-0instal.h \ + launcher-dnd-0install.c liblauncher_la_CFLAGS = \ $(GTK_CFLAGS) \ diff --git a/plugins/launcher/launcher-dialog.c b/plugins/launcher/launcher-dialog.c index 2bb03fd..81b4572 100644 --- a/plugins/launcher/launcher-dialog.c +++ b/plugins/launcher/launcher-dialog.c @@ -107,7 +107,6 @@ static void launcher_dialog_save_entry (GtkWidget LauncherDialog *ld); static void launcher_dialog_save_button (GtkWidget *button, LauncherDialog *ld); -static void launcher_dialog_update_entries (LauncherDialog *ld); static void launcher_dialog_update_icon (LauncherDialog *ld); static void launcher_dialog_folder_chooser (LauncherDialog *ld); static void launcher_dialog_command_chooser (LauncherDialog *ld); @@ -414,7 +413,7 @@ launcher_dialog_save_button (GtkWidget *button, -static void +void launcher_dialog_update_entries (LauncherDialog *ld) { /* quit if locked or no active entry set */ @@ -1400,6 +1399,30 @@ launcher_dialog_response (GtkWidget *dialog, +LauncherDialog * +launcher_dialog_get_from_plugin (XfcePanelPlugin *plugin) +{ + return (LauncherDialog*)g_object_get_data (G_OBJECT (plugin), I_("launcher-dialog")); +} + + + +LauncherEntry * +launcher_dialog_get_current_entry (LauncherDialog *ld) +{ + return ld->entry; +} + + + +XfcePanelPlugin * +launcher_dialog_get_plugin (LauncherDialog *ld) +{ + return ld->launcher->panel_plugin; +} + + + void launcher_dialog_show (LauncherPlugin *launcher) { diff --git a/plugins/launcher/launcher-dialog.h b/plugins/launcher/launcher-dialog.h index 95ad118..8d9211e 100644 --- a/plugins/launcher/launcher-dialog.h +++ b/plugins/launcher/launcher-dialog.h @@ -23,6 +23,16 @@ typedef struct _LauncherDialog LauncherDialog; -void launcher_dialog_show (LauncherPlugin *launcher) G_GNUC_INTERNAL; + +void launcher_dialog_show (LauncherPlugin *launcher) G_GNUC_INTERNAL; + + +LauncherDialog *launcher_dialog_get_from_plugin (XfcePanelPlugin *plugin); + +LauncherEntry *launcher_dialog_get_current_entry (LauncherDialog *ld); + +XfcePanelPlugin *launcher_dialog_get_plugin (LauncherDialog *ld); + +void launcher_dialog_update_entries (LauncherDialog *ld); #endif /* !__XFCE_PANEL_LAUNCHER_DIALOG_H__ */ diff --git a/plugins/launcher/launcher-dnd-0install.c b/plugins/launcher/launcher-dnd-0install.c new file mode 100644 index 0000000..08347a2 --- /dev/null +++ b/plugins/launcher/launcher-dnd-0install.c @@ -0,0 +1,198 @@ +/* $Id$ + * + * Copyright (c) 2007 Jasper Huijsmans + * Copyright (c) 2006 Thomas Leonard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include +#include + +#include "launcher.h" +#include "launcher-dialog.h" +#include "launcher-dnd-0install.h" + + +/* Adding a new Zero Install interface requires using the + * network, so we do it asynchronously. This structure records + * the details for the callback handler. + */ +typedef struct +{ + /* LauncherDialog objects are not ref-counted, so we ref-count + * the plugin object instead and use that to check that the + * LauncherDialog is still available. + */ + GObject *plugin; + + /* The package we are checking. */ + char *interface_uri; + + /* The entry to update. Need to check that this is still valid + * when the callback is invoked. + */ + LauncherEntry *entry; +} +ZeroInstallProcess; + +static LauncherEntry * +launcher_entry_update_from_interface (LauncherEntry *e, + const char *iface) +{ + GError *error = NULL; + char *child_stdout = NULL; + const gchar *argv[] = + {"python", "-c", + "import sys;" + "from zeroinstall.injector.iface_cache import iface_cache;" + "iface = iface_cache.get_interface(sys.argv[1]);" + "print iface.name;" + "print iface.summary.replace('\\n', ' ');" + "hasattr(iface_cache, 'get_icon_path') and " + " sys.stdout.write(iface_cache.get_icon_path(iface));", + NULL, NULL}; + + /* Set the command to "0launch iface" */ + g_free (e->exec); + e->exec = g_strconcat ("0launch ", iface, NULL); + + /* Get the name and summary from the interface file. Since 0launch + * worked, the user should have Python... + */ + argv[3] = iface; + g_spawn_sync (NULL, (gchar **) argv, NULL, + G_SPAWN_SEARCH_PATH, + NULL, NULL, + &child_stdout, NULL, + NULL, &error); + + if (error) + { + xfce_warn (_("Failed to run 0launch:\n%s\n\n" + "For help using Zero Install, " + "see http://0install.net"), error->message); + g_error_free (error); + } + else if (child_stdout) + { + gchar **lines; + + lines = g_strsplit(child_stdout, "\n", 3); + + if (lines[0]) + { + g_free(e->name); + e->name = lines[0]; + + if (lines[1]) + { + g_free(e->comment); + e->comment = lines[1]; + + if (lines[2]) { + g_free(e->icon); + e->icon = lines[2]; + } + } + } + + g_free (lines); /* Not strvfree(); we used all the lines */ + } + + g_free (child_stdout); + + return e; +} + +static void +zero_install_launch_done (GPid pid, + gint status, + ZeroInstallProcess *info) +{ + LauncherDialog *ld; + LauncherEntry *e; + g_spawn_close_pid (pid); + + if (status == 0) + { + /* Success! Let's add the application's details... */ + ld = launcher_dialog_get_from_plugin ((XfcePanelPlugin*)info->plugin); + if (ld && info->entry) /* && launcher_dialog_get_current_entry (ld) == info->entry */ + { + e = info->entry; + launcher_entry_update_from_interface (e, info->interface_uri); + launcher_dialog_update_entries (ld); + } + else + { + xfce_warn(_("The Zero Install GUI has finished, but the launcher dialog " + "has disappeared in the meantime. Not adding launcher " + "(but any files downloaded have not been lost).")); + } + } + + g_object_unref(G_OBJECT (info->plugin)); + g_free(info->interface_uri); + panel_slice_free(ZeroInstallProcess, info); +} + +/** The user wants to add a launcher for 'interface'. Confirm that it + * is a valid Zero Install interface, download archives needed to run + * the program, and then add it as a launcher. + * Note: This function will return immediately without adding or updating + * the entry. The update happens later in a callback. + */ +gboolean +launcher_dnd_handle_zeroinstall_interface (const char *file, + LauncherEntry *entry, + LauncherDialog *ld) +{ + ZeroInstallProcess *info; + GPid pid; + GError *error = NULL; + const gchar *argv[] = {"0launch", "-dg", "--", NULL, NULL}; + + argv[3] = file; + + g_spawn_async(NULL, (gchar **) argv, NULL, + G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, + NULL, NULL, + &pid, &error); + + if (G_UNLIKELY (error)) + { + xfce_warn (_("Failed to run 0launch:\n%s\n\n" + "For help using Zero Install, " + "see http://0install.net"), error->message); + g_error_free (error); + return FALSE; + } + + info = panel_slice_new0 (ZeroInstallProcess); + + info->interface_uri = g_strdup(file); + info->plugin = G_OBJECT(launcher_dialog_get_plugin (ld)); + info->entry = entry; + + g_object_ref (G_OBJECT (info->plugin)); + g_child_watch_add (pid, + (GChildWatchFunc) zero_install_launch_done, + info); + + return TRUE; +} diff --git a/plugins/launcher/launcher-dnd-0install.h b/plugins/launcher/launcher-dnd-0install.h new file mode 100644 index 0000000..45eb665 --- /dev/null +++ b/plugins/launcher/launcher-dnd-0install.h @@ -0,0 +1,39 @@ +/* $Id$ + * + * Copyright (c) 2007 Jasper Huijsmans + * Copyright (c) 2006 Thomas Leonard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __LAUNCHER_DND_0INSTAL_H__ +#define __LAUNCHER_DND_0INSTAL_H__ + +#include "launcher-dialog.h" + +/* inline file type test */ +static inline gboolean +launcher_dnd_test_zeroinstall_interface (const char *file) +{ + return (g_str_has_suffix (file, ".xml") || + g_str_has_prefix (file, "http://")); +} + +/* update LauncherEntry */ +gboolean launcher_dnd_handle_zeroinstall_interface (const char *file, + LauncherEntry *entry, + LauncherDialog *ld); + +#endif /*__LAUNCHER_DND_0INSTAL_H__ */ -- 1.5.3.7