From eae33615af610f84fc2be016c5b222f44e741cc1 Mon Sep 17 00:00:00 2001 From: Stefano Karapetsas Date: Thu, 17 Oct 2013 17:40:03 +0200 Subject: Add sendto extension --- sendto/Makefile.am | 82 ++ sendto/caja-nste.c | 162 ++++ sendto/caja-nste.h | 51 ++ sendto/caja-sendto-command.c | 843 +++++++++++++++++++++ sendto/caja-sendto-convert | 3 + sendto/caja-sendto-module.c | 60 ++ sendto/caja-sendto-plugin.h | 116 +++ sendto/caja-sendto.1 | 27 + sendto/caja-sendto.pc.in | 10 + sendto/caja-sendto.ui | 498 ++++++++++++ sendto/docs/Makefile.am | 100 +++ sendto/docs/caja-sendto-docs.sgml | 29 + sendto/docs/caja-sendto-overrides.txt | 0 sendto/docs/caja-sendto-sections.txt | 14 + sendto/docs/caja-sendto.types | 1 + sendto/docs/html/annotation-glossary.html | 36 + sendto/docs/html/api-index-full.html | 66 ++ .../docs/html/caja-sendto-caja-sendto-plugin.html | 219 ++++++ sendto/docs/html/caja-sendto.devhelp | 17 + sendto/docs/html/caja-sendto.devhelp2 | 20 + sendto/docs/html/ch01.html | 33 + sendto/docs/html/home.png | Bin 0 -> 654 bytes sendto/docs/html/index.html | 39 + sendto/docs/html/index.sgml | 14 + sendto/docs/html/left.png | Bin 0 -> 459 bytes sendto/docs/html/right.png | Bin 0 -> 472 bytes sendto/docs/html/style.css | 265 +++++++ sendto/docs/html/up.png | Bin 0 -> 406 bytes sendto/docs/tmpl/caja-sendto-mimetype.sgml | 33 + sendto/docs/tmpl/caja-sendto-packer.sgml | 112 +++ sendto/docs/tmpl/caja-sendto-plugin.sgml | 63 ++ sendto/docs/tmpl/caja-sendto-unused.sgml | 368 +++++++++ sendto/docs/tmpl/nst-common.sgml | 31 + sendto/docs/tmpl/nst-enum-types.sgml | 38 + sendto/docs/tmpl/nst-plugin-marshal.sgml | 50 ++ sendto/docs/version.xml.in | 1 + sendto/org.mate.Caja.Sendto.gschema.xml.in | 21 + sendto/plugins/Makefile.am | 16 + sendto/plugins/caja-burn/Makefile.am | 19 + sendto/plugins/caja-burn/caja-burn.c | 189 +++++ sendto/plugins/emailclient/Makefile.am | 17 + sendto/plugins/emailclient/emailclient.c | 274 +++++++ sendto/plugins/gajim/Makefile.am | 18 + sendto/plugins/gajim/gajim.c | 516 +++++++++++++ sendto/plugins/nst-common.c | 98 +++ sendto/plugins/nst-common.h | 23 + sendto/plugins/pidgin/Makefile.am | 18 + sendto/plugins/pidgin/pidgin.c | 475 ++++++++++++ sendto/plugins/removable-devices/Makefile.am | 19 + .../plugins/removable-devices/removable-devices.c | 259 +++++++ sendto/plugins/upnp/Makefile.am | 18 + sendto/plugins/upnp/upnp.c | 320 ++++++++ 52 files changed, 5701 insertions(+) create mode 100644 sendto/Makefile.am create mode 100644 sendto/caja-nste.c create mode 100644 sendto/caja-nste.h create mode 100644 sendto/caja-sendto-command.c create mode 100644 sendto/caja-sendto-convert create mode 100644 sendto/caja-sendto-module.c create mode 100644 sendto/caja-sendto-plugin.h create mode 100644 sendto/caja-sendto.1 create mode 100644 sendto/caja-sendto.pc.in create mode 100644 sendto/caja-sendto.ui create mode 100644 sendto/docs/Makefile.am create mode 100644 sendto/docs/caja-sendto-docs.sgml create mode 100644 sendto/docs/caja-sendto-overrides.txt create mode 100644 sendto/docs/caja-sendto-sections.txt create mode 100644 sendto/docs/caja-sendto.types create mode 100644 sendto/docs/html/annotation-glossary.html create mode 100644 sendto/docs/html/api-index-full.html create mode 100644 sendto/docs/html/caja-sendto-caja-sendto-plugin.html create mode 100644 sendto/docs/html/caja-sendto.devhelp create mode 100644 sendto/docs/html/caja-sendto.devhelp2 create mode 100644 sendto/docs/html/ch01.html create mode 100644 sendto/docs/html/home.png create mode 100644 sendto/docs/html/index.html create mode 100644 sendto/docs/html/index.sgml create mode 100644 sendto/docs/html/left.png create mode 100644 sendto/docs/html/right.png create mode 100644 sendto/docs/html/style.css create mode 100644 sendto/docs/html/up.png create mode 100644 sendto/docs/tmpl/caja-sendto-mimetype.sgml create mode 100644 sendto/docs/tmpl/caja-sendto-packer.sgml create mode 100644 sendto/docs/tmpl/caja-sendto-plugin.sgml create mode 100644 sendto/docs/tmpl/caja-sendto-unused.sgml create mode 100644 sendto/docs/tmpl/nst-common.sgml create mode 100644 sendto/docs/tmpl/nst-enum-types.sgml create mode 100644 sendto/docs/tmpl/nst-plugin-marshal.sgml create mode 100644 sendto/docs/version.xml.in create mode 100644 sendto/org.mate.Caja.Sendto.gschema.xml.in create mode 100644 sendto/plugins/Makefile.am create mode 100644 sendto/plugins/caja-burn/Makefile.am create mode 100644 sendto/plugins/caja-burn/caja-burn.c create mode 100644 sendto/plugins/emailclient/Makefile.am create mode 100644 sendto/plugins/emailclient/emailclient.c create mode 100644 sendto/plugins/gajim/Makefile.am create mode 100644 sendto/plugins/gajim/gajim.c create mode 100644 sendto/plugins/nst-common.c create mode 100644 sendto/plugins/nst-common.h create mode 100644 sendto/plugins/pidgin/Makefile.am create mode 100644 sendto/plugins/pidgin/pidgin.c create mode 100644 sendto/plugins/removable-devices/Makefile.am create mode 100644 sendto/plugins/removable-devices/removable-devices.c create mode 100644 sendto/plugins/upnp/Makefile.am create mode 100644 sendto/plugins/upnp/upnp.c (limited to 'sendto') diff --git a/sendto/Makefile.am b/sendto/Makefile.am new file mode 100644 index 0000000..030b731 --- /dev/null +++ b/sendto/Makefile.am @@ -0,0 +1,82 @@ +SUBDIRS = docs plugins + +AM_CPPFLAGS = \ + -DDATADIR=\"$(datadir)\" \ + -DPLUGINDIR=\"$(libdir)/caja-sendto/plugins\" \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -DUIDIR=\""$(uidir)"\" \ + -DLOCALEDIR="\"$(datadir)/locale\"" \ + $(SENDTO_CFLAGS) \ + $(CAJA_CFLAGS) \ + $(DISABLE_DEPRECATED) \ + $(WARN_CFLAGS) + +caja_sendto_includedir = $(includedir)/caja-sendto/ +caja_sendto_include_HEADERS = caja-sendto-plugin.h + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = caja-sendto.pc + +ui_DATA = caja-sendto.ui +uidir = $(datadir)/caja-sendto/ui + +noinst_LTLIBRARIES = libnstplugin.la +libnstplugin_la_SOURCES = \ + caja-sendto-plugin.h \ + nst-enum-types.c \ + nst-enum-types.h +libnstplugin_la_LIBADD = $(SENDTO_LIBS) + +bin_PROGRAMS = caja-sendto + +caja_sendto_SOURCES = caja-sendto-command.c +caja_sendto_LDADD = $(SENDTO_LIBS) libnstplugin.la + +caja_extensiondir = $(CAJA_EXTENSION_DIR) +caja_extension_LTLIBRARIES = libcaja-sendto.la +libcaja_sendto_la_SOURCES = \ + caja-nste.c \ + caja-nste.h \ + caja-sendto-module.c + +libcaja_sendto_la_LDFLAGS = -module -avoid-version -no-undefined +libcaja_sendto_la_LIBADD = $(CAJA_LIBS) + +nst_headers_to_scan_for_enums = caja-sendto-plugin.h +# Generate the enums source code, with glib-mkenums: +# This is based on the same Makefile.am stuff in pango: +nst_built_headers = nst-enum-types.h +nst_built_cfiles = nst-enum-types.c + +nst-enum-types.h: $(nst_headers_to_scan_for_enums) Makefile + $(AM_V_GEN) (cd $(srcdir) && glib-mkenums \ + --fhead "#ifndef __NST_ENUM_TYPES_H__\n#define __NST_ENUM_TYPES_H__\n\n#include \n\nG_BEGIN_DECLS\n" \ + --fprod "/* enumerations from \"@filename@\" */\n" \ + --vhead "GType @enum_name@_get_type (void);\n#define NST_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ + --ftail "G_END_DECLS\n\n#endif /* __NST_ENUM_TYPES_H__ */" \ + $(nst_headers_to_scan_for_enums)) > $@ + +nst-enum-types.c: $(nst_headers_to_scan_for_enums) Makefile nst-enum-types.h + $(AM_V_GEN) (cd $(srcdir) && glib-mkenums \ + --fhead "#include \n" \ + --fhead "#include \"nst-enum-types.h\"\n" \ + --fhead "#include " \ + --fprod "\n/* enumerations from \"@filename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ + $(nst_headers_to_scan_for_enums)) > $@ + +convertdir=$(datadir)/MateConf/gsettings +convert_DATA = caja-sendto-convert + +gsettingsschema_in_files = org.mate.Caja.Sendto.gschema.xml.in +gsettings_SCHEMAS = $(gsettingsschema_in_files:.xml.in=.xml) +@INTLTOOL_XML_NOMERGE_RULE@ +@GSETTINGS_RULES@ + +man_MANS = caja-sendto.1 + +EXTRA_DIST = $(ui_DATA) $(man_MANS) caja-sendto.pc.in $(convert_DATA) $(gsettingsschema_in_files) +CLEANFILES = $(nst_built_headers) $(nst_built_cfiles) diff --git a/sendto/caja-nste.c b/sendto/caja-nste.c new file mode 100644 index 0000000..62b62b4 --- /dev/null +++ b/sendto/caja-nste.c @@ -0,0 +1,162 @@ +/* + * Caja-sendto + * + * Copyright (C) 2004 Free Software Foundation, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Author: Roberto Majadas + * + */ + +#include +#include +#include +#include +#include +#include +#include "caja-nste.h" + + +static GObjectClass *parent_class; + +static void +sendto_callback (CajaMenuItem *item, + gpointer user_data) +{ + GList *files, *scan; + CajaFileInfo *file; + gchar *uri; + GString *cmd; + + files = g_object_get_data (G_OBJECT (item), "files"); + file = files->data; + + cmd = g_string_new ("caja-sendto"); + + for (scan = files; scan; scan = scan->next) { + CajaFileInfo *file = scan->data; + + uri = caja_file_info_get_uri (file); + g_string_append_printf (cmd, " \"%s\"", uri); + g_free (uri); + } + + g_spawn_command_line_async (cmd->str, NULL); + + g_string_free (cmd, TRUE); +} + +static GList * +caja_nste_get_file_items (CajaMenuProvider *provider, + GtkWidget *window, + GList *files) +{ + GList *items = NULL; + gboolean one_item; + CajaMenuItem *item; + + if (files == NULL) + return NULL; + + one_item = (files != NULL) && (files->next == NULL); + if (one_item && + !caja_file_info_is_directory ((CajaFileInfo *)files->data)) { + item = caja_menu_item_new ("CajaNste::sendto", + _("Send To..."), + _("Send file by mail, instant message..."), + "document-send"); + } else { + item = caja_menu_item_new ("CajaNste::sendto", + _("Send To..."), + _("Send files by mail, instant message..."), + "document-send"); + } + g_signal_connect (item, + "activate", + G_CALLBACK (sendto_callback), + provider); + g_object_set_data_full (G_OBJECT (item), + "files", + caja_file_info_list_copy (files), + (GDestroyNotify) caja_file_info_list_free); + + items = g_list_append (items, item); + + return items; +} + + +static void +caja_nste_menu_provider_iface_init (CajaMenuProviderIface *iface) +{ + iface->get_file_items = caja_nste_get_file_items; +} + + +static void +caja_nste_instance_init (CajaNste *nste) +{ +} + + +static void +caja_nste_class_init (CajaNsteClass *class) +{ + parent_class = g_type_class_peek_parent (class); +} + + +static GType nste_type = 0; + + +GType +caja_nste_get_type (void) +{ + return nste_type; +} + + +void +caja_nste_register_type (GTypeModule *module) +{ + static const GTypeInfo info = { + sizeof (CajaNsteClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) caja_nste_class_init, + NULL, + NULL, + sizeof (CajaNste), + 0, + (GInstanceInitFunc) caja_nste_instance_init, + }; + + static const GInterfaceInfo menu_provider_iface_info = { + (GInterfaceInitFunc) caja_nste_menu_provider_iface_init, + NULL, + NULL + }; + + nste_type = g_type_module_register_type (module, + G_TYPE_OBJECT, + "CajaNste", + &info, 0); + + g_type_module_add_interface (module, + nste_type, + CAJA_TYPE_MENU_PROVIDER, + &menu_provider_iface_info); +} diff --git a/sendto/caja-nste.h b/sendto/caja-nste.h new file mode 100644 index 0000000..87b5222 --- /dev/null +++ b/sendto/caja-nste.h @@ -0,0 +1,51 @@ +/* + * Caja SendTo extension + * + * Copyright (C) 2005 Roberto Majadas + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Author: Roberto Majadas + * + */ + +#ifndef CAJA_NSTE_H +#define CAJA_NSTE_H + +#include + +G_BEGIN_DECLS + +#define CAJA_TYPE_NSTE (caja_nste_get_type ()) +#define CAJA_NSTE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CAJA_TYPE_NSTE, CajaNste)) +#define CAJA_IS_NSTE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CAJA_TYPE_NSTE)) + +typedef struct _CajaNste CajaNste; +typedef struct _CajaNsteClass CajaNsteClass; + +struct _CajaNste { + GObject __parent; +}; + +struct _CajaNsteClass { + GObjectClass __parent; +}; + +GType caja_nste_get_type (void); +void caja_nste_register_type (GTypeModule *module); + +G_END_DECLS + +#endif /* CAJA_NSTE_H */ diff --git a/sendto/caja-sendto-command.c b/sendto/caja-sendto-command.c new file mode 100644 index 0000000..27753e0 --- /dev/null +++ b/sendto/caja-sendto-command.c @@ -0,0 +1,843 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2004 Roberto Majadas + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 + * General Public License for more av. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Author: Roberto Majadas + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include "caja-sendto-plugin.h" + +#define CAJA_SENDTO_LAST_MEDIUM "last-medium" +#define CAJA_SENDTO_LAST_COMPRESS "last-compress" +#define CAJA_SENDTO_STATUS_LABEL_TIMEOUT_SECONDS 10 + +#define UNINSTALLED_PLUGINDIR "plugins/removable-devices" +#define UNINSTALLED_SOURCE "caja-sendto-command.c" + +#define SOEXT ("." G_MODULE_SUFFIX) +#define SOEXT_LEN (strlen (SOEXT)) + +enum { + COLUMN_ICON, + COLUMN_DESCRIPTION, + NUM_COLUMNS, +}; + +/* Options */ +static char **filenames = NULL; + +GList *file_list = NULL; +gboolean has_dirs = FALSE; +GList *plugin_list = NULL; +GHashTable *hash ; +guint option = 0; + +static GSettings *settings = NULL; + +typedef struct _NS_ui NS_ui; + +struct _NS_ui { + GtkWidget *dialog; + GtkWidget *options_combobox; + GtkWidget *send_to_label; + GtkWidget *hbox_contacts_ws; + GtkWidget *cancel_button; + GtkWidget *send_button; + GtkWidget *pack_combobox; + GtkWidget *pack_checkbutton; + GtkWidget *pack_entry; + GList *contact_widgets; + + GtkWidget *status_box; + GtkWidget *status_image; + GtkWidget *status_label; + guint status_timeoutid; +}; + +static const GOptionEntry entries[] = { + { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, "Files to send", "[FILES...]" }, + { NULL } +}; + +static void +destroy_dialog (GtkWidget *widget, gpointer data ) +{ + gtk_main_quit (); +} + +static char * +get_filename_from_list (void) +{ + GList *l; + GString *common_part = NULL; + gboolean matches = TRUE; + guint offset = 0; + const char *encoding; + gboolean use_utf8 = TRUE; + + encoding = g_getenv ("G_FILENAME_ENCODING"); + + if (encoding != NULL && strcasecmp(encoding, "UTF-8") != 0) + use_utf8 = FALSE; + + if (file_list == NULL) + return NULL; + + common_part = g_string_new(""); + + while (TRUE) { + gunichar cur_char = '\0'; + for (l = file_list; l ; l = l->next) { + char *path = NULL, *name = NULL; + char *offset_name = NULL; + + path = g_filename_from_uri ((char *) l->data, + NULL, NULL); + if (!path) + break; + + name = g_path_get_basename (path); + + if (!use_utf8) { + char *tmp; + + tmp = g_filename_to_utf8 (name, -1, + NULL, NULL, NULL); + g_free (name); + name = tmp; + } + + if (!name) { + g_free (path); + break; + } + + if (offset >= g_utf8_strlen (name, -1)) { + g_free(name); + g_free(path); + matches = FALSE; + break; + } + + offset_name = g_utf8_offset_to_pointer (name, offset); + + if (offset_name == g_utf8_strrchr (name, -1, '.')) { + g_free (name); + g_free (path); + matches = FALSE; + break; + } + if (cur_char == '\0') { + cur_char = g_utf8_get_char (offset_name); + } else if (cur_char != g_utf8_get_char (offset_name)) { + g_free (name); + g_free (path); + matches = FALSE; + break; + } + g_free (name); + g_free (path); + } + if (matches == TRUE && cur_char != '\0') { + offset++; + common_part = g_string_append_unichar (common_part, + cur_char); + } else { + break; + } + } + + if (g_utf8_strlen (common_part->str, -1) < 4) { + g_string_free (common_part, TRUE); + return NULL; + } + + return g_string_free (common_part, FALSE); +} + +static char * +pack_files (NS_ui *ui) +{ + char *engrampa_cmd; + const char *filename; + GList *l; + GString *cmd, *tmp; + char *pack_type, *tmp_dir, *tmp_work_dir, *packed_file; + + engrampa_cmd = g_find_program_in_path ("engrampa"); + filename = gtk_entry_get_text(GTK_ENTRY(ui->pack_entry)); + + g_assert (filename != NULL && *filename != '\0'); + + tmp_dir = g_strdup_printf ("%s/caja-sendto-%s", + g_get_tmp_dir(), g_get_user_name()); + g_mkdir (tmp_dir, 0700); + tmp_work_dir = g_strdup_printf ("%s/caja-sendto-%s/%li", + g_get_tmp_dir(), g_get_user_name(), + time(NULL)); + g_mkdir (tmp_work_dir, 0700); + g_free (tmp_dir); + + switch (gtk_combo_box_get_active (GTK_COMBO_BOX(ui->pack_combobox))) + { + case 0: + pack_type = g_strdup (".zip"); + break; + case 1: + pack_type = g_strdup (".tar.gz"); + break; + case 2: + pack_type = g_strdup (".tar.bz2"); + break; + default: + pack_type = NULL; + g_assert_not_reached (); + } + + g_settings_set_int (settings, + CAJA_SENDTO_LAST_COMPRESS, + gtk_combo_box_get_active(GTK_COMBO_BOX(ui->pack_combobox))); + + cmd = g_string_new (""); + g_string_printf (cmd, "%s --add-to=\"%s/%s%s\"", + engrampa_cmd, tmp_work_dir, + filename, + pack_type); + + /* engrampa doesn't understand URIs */ + for (l = file_list ; l; l=l->next){ + char *file; + + file = g_filename_from_uri (l->data, NULL, NULL); + g_string_append_printf (cmd," \"%s\"", file); + g_free (file); + } + + g_spawn_command_line_sync (cmd->str, NULL, NULL, NULL, NULL); + g_string_free (cmd, TRUE); + tmp = g_string_new(""); + g_string_printf (tmp,"%s/%s%s", tmp_work_dir, + filename, + pack_type); + g_free (tmp_work_dir); + packed_file = g_filename_to_uri (tmp->str, NULL, NULL); + g_string_free(tmp, TRUE); + return packed_file; +} + +static gboolean +status_label_clear (gpointer data) +{ + NS_ui *ui = (NS_ui *) data; + gtk_label_set_label (GTK_LABEL (ui->status_label), ""); + gtk_widget_hide (ui->status_image); + + ui->status_timeoutid = 0; + + return FALSE; +} + +static void +send_button_cb (GtkWidget *widget, NS_ui *ui) +{ + char *error; + NstPlugin *p; + GtkWidget *w; + + gtk_widget_set_sensitive (ui->dialog, FALSE); + + p = (NstPlugin *) g_list_nth_data (plugin_list, option); + w = (GtkWidget *) g_list_nth_data (ui->contact_widgets, option); + + if (ui->status_timeoutid != 0) { + g_source_remove (ui->status_timeoutid); + status_label_clear (ui); + } + + if (p == NULL) + return; + + if (p->info->validate_destination != NULL) { + error = NULL; + if (p->info->validate_destination (p, w, &error) == FALSE) { + char *message; + + message = g_strdup_printf ("%s", error); + g_free (error); + gtk_label_set_markup (GTK_LABEL (ui->status_label), message); + g_free (message); + ui->status_timeoutid = g_timeout_add_seconds (CAJA_SENDTO_STATUS_LABEL_TIMEOUT_SECONDS, + status_label_clear, + ui); + gtk_widget_show (ui->status_image); + gtk_widget_show (ui->status_box); + gtk_widget_set_sensitive (ui->dialog, TRUE); + return; + } + } + + g_settings_set_string (settings, + CAJA_SENDTO_LAST_MEDIUM, + p->info->id); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ui->pack_checkbutton))){ + char *f; + + f = pack_files (ui); + if (f != NULL) { + GList *packed_file = NULL; + packed_file = g_list_append (packed_file, f); + if (!p->info->send_files (p, w, packed_file)) { + g_free (f); + g_list_free (packed_file); + return; + } + g_list_free (packed_file); + } else { + gtk_widget_set_sensitive (ui->dialog, TRUE); + return; + } + g_free (f); + } else { + if (!p->info->send_files (p, w, file_list)) { + g_list_foreach (file_list, (GFunc) g_free, NULL); + g_list_free (file_list); + file_list = NULL; + return; + } + g_list_free (file_list); + file_list = NULL; + } + destroy_dialog (NULL,NULL); +} + +static void +send_if_no_pack_cb (GtkWidget *widget, NS_ui *ui) +{ + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton))) { + if (gtk_widget_is_sensitive (ui->pack_entry)) { + gtk_widget_grab_focus (ui->pack_entry); + } else { + gtk_widget_grab_focus (ui->pack_checkbutton); + } + } else { + send_button_cb (widget, ui); + } +} + +static void +toggle_pack_check (GtkWidget *widget, NS_ui *ui) +{ + GtkToggleButton *t = GTK_TOGGLE_BUTTON (widget); + gboolean enabled, send_enabled; + + enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (t)); + gtk_widget_set_sensitive (ui->pack_combobox, enabled); + gtk_widget_set_sensitive (ui->pack_entry, enabled); + + send_enabled = TRUE; + + if (enabled) { + const char *filename; + + filename = gtk_entry_get_text(GTK_ENTRY(ui->pack_entry)); + if (filename == NULL || *filename == '\0') + send_enabled = FALSE; + } + + gtk_widget_set_sensitive (ui->send_button, send_enabled); +} + +static void +option_changed (GtkComboBox *cb, NS_ui *ui) +{ + GList *aux; + NstPlugin *p; + gboolean supports_dirs = FALSE; + + aux = g_list_nth (ui->contact_widgets, option); + option = gtk_combo_box_get_active (GTK_COMBO_BOX(cb)); + gtk_widget_hide ((GtkWidget *) aux->data); + aux = g_list_nth (ui->contact_widgets, option); + gtk_widget_show ((GtkWidget *) aux->data); + + gtk_label_set_mnemonic_widget (GTK_LABEL (ui->send_to_label), aux->data); + + p = (NstPlugin *) g_list_nth_data (plugin_list, option); + supports_dirs = (p->info->capabilities & CAJA_CAPS_SEND_DIRECTORIES); + + if (has_dirs == FALSE || supports_dirs != FALSE) { + gboolean toggle; + + toggle = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton)); + gtk_widget_set_sensitive (ui->pack_combobox, toggle); + gtk_widget_set_sensitive (ui->pack_entry, toggle); + gtk_widget_set_sensitive (ui->pack_checkbutton, TRUE); + } else { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton), TRUE); + gtk_widget_set_sensitive (ui->pack_checkbutton, FALSE); + } +} + +static void +set_contact_widgets (NS_ui *ui) +{ + GList *aux ; + GtkWidget *w; + NstPlugin *p; + + ui->contact_widgets = NULL; + + for (aux = plugin_list; aux; aux = aux->next){ + p = (NstPlugin *) aux->data; + w = p->info->get_contacts_widget(p); + gtk_box_pack_end (GTK_BOX(ui->hbox_contacts_ws),w, TRUE, TRUE, 0); + gtk_widget_hide (GTK_WIDGET(w)); + ui->contact_widgets = g_list_append (ui->contact_widgets, w); + if (GTK_IS_ENTRY (w)) { + g_signal_connect_after (G_OBJECT (w), "activate", + G_CALLBACK (send_if_no_pack_cb), ui); + } + } +} + +static gboolean +set_model_for_options_combobox (NS_ui *ui) +{ + GdkPixbuf *pixbuf; + GtkTreeIter iter; + GtkListStore *model; + GtkIconTheme *it; + GtkCellRenderer *renderer; + GtkWidget *widget; + GList *aux; + NstPlugin *p; + char *last_used = NULL; + int i = 0; + gboolean last_used_support_dirs = FALSE; + + it = gtk_icon_theme_get_default (); + + model = gtk_list_store_new (NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING); + + last_used = g_settings_get_string (settings, + CAJA_SENDTO_LAST_MEDIUM); + + for (aux = plugin_list; aux; aux = aux->next) { + p = (NstPlugin *) aux->data; + pixbuf = gtk_icon_theme_load_icon (it, p->info->icon, 16, + GTK_ICON_LOOKUP_USE_BUILTIN, NULL); + gtk_list_store_append (model, &iter); + gtk_list_store_set (model, &iter, + COLUMN_ICON, pixbuf, + COLUMN_DESCRIPTION, dgettext(p->info->gettext_package, p->info->description), + -1); + if (last_used != NULL && !strcmp(last_used, p->info->id)) { + option = i; + last_used_support_dirs = (p->info->capabilities & CAJA_CAPS_SEND_DIRECTORIES); + } + i++; + } + g_free(last_used); + + gtk_combo_box_set_model (GTK_COMBO_BOX(ui->options_combobox), + GTK_TREE_MODEL (model)); + renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->options_combobox), + renderer, + FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (ui->options_combobox), + renderer, + "pixbuf", COLUMN_ICON, + NULL); + renderer = gtk_cell_renderer_text_new (); + g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->options_combobox), + renderer, + TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (ui->options_combobox), + renderer, + "text", COLUMN_DESCRIPTION, + NULL); + + g_signal_connect (G_OBJECT (ui->options_combobox), "changed", + G_CALLBACK (option_changed), ui); + + gtk_combo_box_set_active (GTK_COMBO_BOX (ui->options_combobox), option); + + /* Grab the focus for the most recently used widget */ + widget = g_list_nth_data (ui->contact_widgets, option); + gtk_widget_grab_focus (widget); + + return last_used_support_dirs; +} + +static void +pack_entry_changed_cb (GObject *object, GParamSpec *spec, NS_ui *ui) +{ + gboolean send_enabled; + + send_enabled = TRUE; + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton))) { + const char *filename; + + filename = gtk_entry_get_text(GTK_ENTRY(ui->pack_entry)); + if (filename == NULL || *filename == '\0') + send_enabled = FALSE; + } + + gtk_widget_set_sensitive (ui->send_button, send_enabled); +} + +static void +update_button_image (GtkSettings *settings, + GParamSpec *spec, + GtkWidget *widget) +{ + gboolean show_images; + + g_object_get (settings, "gtk-button-images", &show_images, NULL); + if (show_images == FALSE) + gtk_widget_hide (widget); + else + gtk_widget_show (widget); +} + +static void +caja_sendto_create_ui (void) +{ + GtkBuilder *app; + GError* error = NULL; + NS_ui *ui; + gboolean one_file = FALSE; + gboolean supports_dirs; + GtkSettings *gtk_settings; + GtkWidget *button_image; + + app = gtk_builder_new (); + if (!gtk_builder_add_from_file (app, UIDIR "/" "caja-sendto.ui", &error)) { + g_warning ("Couldn't load builder file: %s", error->message); + g_error_free (error); + } + + ui = g_new0 (NS_ui, 1); + + ui->hbox_contacts_ws = GTK_WIDGET (gtk_builder_get_object (app, "hbox_contacts_widgets")); + ui->send_to_label = GTK_WIDGET (gtk_builder_get_object (app, "send_to_label")); + ui->options_combobox = GTK_WIDGET (gtk_builder_get_object (app, "options_combobox")); + ui->dialog = GTK_WIDGET (gtk_builder_get_object (app, "caja_sendto_dialog")); + ui->cancel_button = GTK_WIDGET (gtk_builder_get_object (app, "cancel_button")); + ui->send_button = GTK_WIDGET (gtk_builder_get_object (app, "send_button")); + ui->pack_combobox = GTK_WIDGET (gtk_builder_get_object (app, "pack_combobox")); + ui->pack_entry = GTK_WIDGET (gtk_builder_get_object (app, "pack_entry")); + ui->pack_checkbutton = GTK_WIDGET (gtk_builder_get_object (app, "pack_checkbutton")); + ui->status_box = GTK_WIDGET (gtk_builder_get_object (app, "status_box")); + ui->status_label = GTK_WIDGET (gtk_builder_get_object (app, "status_label")); + ui->status_image = GTK_WIDGET (gtk_builder_get_object (app, "status_image")); + + gtk_settings = gtk_settings_get_default (); + button_image = GTK_WIDGET (gtk_builder_get_object (app, "image1")); + g_signal_connect (G_OBJECT (gtk_settings), "notify::gtk-button-images", + G_CALLBACK (update_button_image), button_image); + update_button_image (gtk_settings, NULL, button_image); + + gtk_combo_box_set_active (GTK_COMBO_BOX(ui->pack_combobox), + g_settings_get_int (settings, + CAJA_SENDTO_LAST_COMPRESS)); + + if (file_list != NULL && file_list->next != NULL) + one_file = FALSE; + else if (file_list != NULL) + one_file = TRUE; + + gtk_entry_set_text (GTK_ENTRY (ui->pack_entry), _("Files")); + + if (one_file) { + char *filepath = NULL, *filename = NULL; + + filepath = g_filename_from_uri ((char *)file_list->data, + NULL, NULL); + + if (filepath != NULL) + filename = g_path_get_basename (filepath); + if (filename != NULL && filename[0] != '\0') + gtk_entry_set_text (GTK_ENTRY (ui->pack_entry), filename); + + g_free (filename); + g_free (filepath); + } else { + char *filename = get_filename_from_list (); + if (filename != NULL && filename[0] != '\0') { + gtk_entry_set_text (GTK_ENTRY (ui->pack_entry), + filename); + } + g_free (filename); + } + + set_contact_widgets (ui); + supports_dirs = set_model_for_options_combobox (ui); + g_signal_connect (G_OBJECT (ui->dialog), "destroy", + G_CALLBACK (destroy_dialog), NULL); + g_signal_connect (G_OBJECT (ui->cancel_button), "clicked", + G_CALLBACK (destroy_dialog), NULL); + g_signal_connect (G_OBJECT (ui->send_button), "clicked", + G_CALLBACK (send_button_cb), ui); + g_signal_connect (G_OBJECT (ui->pack_entry), "activate", + G_CALLBACK (send_button_cb), ui); + g_signal_connect (G_OBJECT (ui->pack_entry), "notify::text", + G_CALLBACK (pack_entry_changed_cb), ui); + g_signal_connect (G_OBJECT (ui->pack_checkbutton), "toggled", + G_CALLBACK (toggle_pack_check), ui); + + if (has_dirs == FALSE || supports_dirs != FALSE) { + gboolean toggle; + + toggle = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton)); + gtk_widget_set_sensitive (ui->pack_combobox, toggle); + gtk_widget_set_sensitive (ui->pack_entry, toggle); + } else { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton), TRUE); + gtk_widget_set_sensitive (ui->pack_checkbutton, FALSE); + } + + gtk_widget_show (ui->dialog); + +} + +static void +caja_sendto_plugin_dir_process (const char *plugindir) +{ + GDir *dir; + const char *item; + NstPlugin *p = NULL; + gboolean (*nst_init_plugin)(NstPlugin *p); + GError *err = NULL; + + dir = g_dir_open (plugindir, 0, &err); + + if (dir == NULL) { + g_warning ("Can't open the plugins dir: %s", err ? err->message : "No reason"); + if (err) + g_error_free (err); + } else { + while ((item = g_dir_read_name(dir))) { + if (g_str_has_suffix (item, SOEXT)) { + char *module_path; + + p = g_new0(NstPlugin, 1); + module_path = g_module_build_path (plugindir, item); + p->module = g_module_open (module_path, 0); + if (!p->module) { + g_warning ("error opening %s: %s", module_path, g_module_error ()); + g_free (module_path); + continue; + } + g_free (module_path); + + if (!g_module_symbol (p->module, "nst_init_plugin", (gpointer *) &nst_init_plugin)) { + g_warning ("error: %s", g_module_error ()); + g_module_close (p->module); + continue; + } + + nst_init_plugin (p); + if (p->info->init(p)) { + plugin_list = g_list_append (plugin_list, p); + } else { + g_free (p); + } + } + } + g_dir_close (dir); + } +} + +static gboolean +caja_sendto_plugin_init (void) +{ + if (g_file_test (UNINSTALLED_PLUGINDIR, G_FILE_TEST_IS_DIR) != FALSE) { + /* Try to load the local plugins */ + GError *err = NULL; + GDir *dir; + const char *item; + + dir = g_dir_open ("plugins/", 0, &err); + if (dir == NULL) { + g_warning ("Can't open the plugins dir: %s", err ? err->message : "No reason"); + if (err) + g_error_free (err); + return FALSE; + } + while ((item = g_dir_read_name(dir))) { + char *plugindir; + + plugindir = g_strdup_printf ("plugins/%s/.libs/", item); + if (g_file_test (plugindir, G_FILE_TEST_IS_DIR) != FALSE) + caja_sendto_plugin_dir_process (plugindir); + g_free (plugindir); + } + g_dir_close (dir); + } + + if (g_list_length (plugin_list) == 0) + caja_sendto_plugin_dir_process (PLUGINDIR); + + return g_list_length (plugin_list) != 0; +} + +static char * +escape_ampersands_and_commas (const char *url) +{ + int i; + char *str, *ptr; + + /* Count the number of ampersands & commas */ + i = 0; + ptr = (char *) url; + while ((ptr = strchr (ptr, '&')) != NULL) { + i++; + ptr++; + } + ptr = (char *) url; + while ((ptr = strchr (ptr, ',')) != NULL) { + i++; + ptr++; + } + + /* No ampersands or commas ? */ + if (i == 0) + return NULL; + + /* Replace the '&' */ + str = g_malloc0 (strlen (url) - i + 3 * i + 1); + ptr = str; + for (i = 0; url[i] != '\0'; i++) { + if (url[i] == '&') { + *ptr++ = '%'; + *ptr++ = '2'; + *ptr++ = '6'; + } else if (url[i] == ',') { + *ptr++ = '%'; + *ptr++ = '2'; + *ptr++ = 'C'; + } else { + *ptr++ = url[i]; + } + } + + return str; +} + +static void +caja_sendto_init (void) +{ + int i; + + if (g_module_supported() == FALSE) + g_error ("Could not initialize gmodule support"); + + for (i = 0; filenames != NULL && filenames[i] != NULL; i++) { + GFile *file; + char *filename, *escaped, *uri; + + file = g_file_new_for_commandline_arg (filenames[i]); + filename = g_file_get_path (file); + g_object_unref (file); + if (filename == NULL) + continue; + + if (g_file_test (filename, G_FILE_TEST_IS_DIR) != FALSE) + has_dirs = TRUE; + + uri = g_filename_to_uri (filename, NULL, NULL); + g_free (filename); + escaped = escape_ampersands_and_commas (uri); + + if (escaped == NULL) { + file_list = g_list_prepend (file_list, uri); + } else { + file_list = g_list_prepend (file_list, escaped); + g_free (uri); + } + } + + if (file_list == NULL) { + g_print (_("Expects URIs or filenames to be passed as options\n")); + exit (1); + } + + file_list = g_list_reverse (file_list); +} + +int main (int argc, char **argv) +{ + GOptionContext *context; + GError *error = NULL; + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + g_thread_init (NULL); + context = g_option_context_new (""); + g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); + g_option_context_add_group (context, gtk_get_option_group (TRUE)); + if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) { + g_print (_("Could not parse command-line options: %s\n"), error->message); + g_error_free (error); + return 1; + } + + settings = g_settings_new ("org.mate.Caja.Sendto"); + caja_sendto_init (); + if (caja_sendto_plugin_init () == FALSE) { + GtkWidget *error_dialog; + + error_dialog = + gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("Could not load any plugins.")); + gtk_message_dialog_format_secondary_text + (GTK_MESSAGE_DIALOG (error_dialog), + _("Please verify your installation")); + + gtk_window_set_title (GTK_WINDOW (error_dialog), ""); /* as per HIG */ + gtk_container_set_border_width (GTK_CONTAINER (error_dialog), 5); + gtk_dialog_set_default_response (GTK_DIALOG (error_dialog), + GTK_RESPONSE_OK); + gtk_dialog_run (GTK_DIALOG (error_dialog)); + return 1; + } + caja_sendto_create_ui (); + + gtk_main (); + g_object_unref(settings); + + return 0; +} + diff --git a/sendto/caja-sendto-convert b/sendto/caja-sendto-convert new file mode 100644 index 0000000..4555b9a --- /dev/null +++ b/sendto/caja-sendto-convert @@ -0,0 +1,3 @@ +[org.mate.Caja.Sendto] +last-medium = /org/mate/caja-sendto/last_medium +last-compress = /org/mate/caja-sendto/last_compress diff --git a/sendto/caja-sendto-module.c b/sendto/caja-sendto-module.c new file mode 100644 index 0000000..f3746ff --- /dev/null +++ b/sendto/caja-sendto-module.c @@ -0,0 +1,60 @@ +/* + * Caja SendTo + * + * Copyright (C) 2005 Roberto Majadas + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Author: Roberto Majadas + * + */ + +#include +#include +#include +#include +#include "caja-nste.h" + + +void +caja_module_initialize (GTypeModule*module) +{ + caja_nste_register_type (module); + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +} + + +void +caja_module_shutdown (void) +{ +} + + +void +caja_module_list_types (const GType **types, + int *num_types) +{ + static GType type_list[1]; + + type_list[0] = CAJA_TYPE_NSTE; + *types = type_list; + + *num_types = 1; +} + + + diff --git a/sendto/caja-sendto-plugin.h b/sendto/caja-sendto-plugin.h new file mode 100644 index 0000000..f208718 --- /dev/null +++ b/sendto/caja-sendto-plugin.h @@ -0,0 +1,116 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2004 Roberto Majadas + * Copyright (C) 2009 Bastien Nocera + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 + * General Public License for more av. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Authors: Roberto Majadas + * Bastien Nocera + */ + +#ifndef _CAJA_SENDTO_PLUGIN_H_ +#define _CAJA_SENDTO_PLUGIN_H_ + +#include +#include + +/** + * SECTION:caja-sendto-plugin + * @short_description: caja-sento plug-in + * @stability: Stable + * @include: bluetooth-plugin.h + * + * Plug-ins can be used to extend caja-sendto. + **/ + +typedef struct _NstPluginInfo NstPluginInfo; +typedef struct _NstPlugin NstPlugin; + +/** + * NstPluginCapabilities: + * @CAJA_CAPS_NONE: No capabilities + * @CAJA_CAPS_SEND_DIRECTORIES: The plugin can send whole directories without compression + * @CAJA_CAPS_SEND_IMAGES: The plugin only sends images which could be resized + * + * Capabilities of the plugin. + **/ +typedef enum { + CAJA_CAPS_NONE = 0, + CAJA_CAPS_SEND_DIRECTORIES = 1 << 0, + CAJA_CAPS_SEND_IMAGES = 1 << 1, +} NstPluginCapabilities; + +/** + * NstPluginInfo: + * @icon: The icon name for the plugin selection drop-down + * @id: A unique ID representing the plugin + * @description: The label used in the plugin selection drop-down + * @gettext_package: The domain to use to translate the description, %NULL if the plugin is part of caja-sendto + * @capabilities: a bitmask of #NstPluginCapabilities + * @init: Check for dependencies, and return %FALSE if dependencies such as programs are missing. + * @get_contacts_widget: Return the contact widget, the widget to select the destination of the files + * @validate_destination: Validate whether the destination can receive the file. This callback is optional. + * @send_files: Actually send the files to the selected destination. The file list is a #GList of URI strings. + * @destroy: Free all the resources used by the plugin. + * + * A structure representing a caja-sendto plugin. You should also call NST_INIT_PLUGIN() on the plugin structure to export it. + **/ +struct _NstPluginInfo +{ + gchar *icon; + gchar *id; + gchar *description; + gchar *gettext_package; + NstPluginCapabilities capabilities; + gboolean (*init) (NstPlugin *plugin); + GtkWidget* (*get_contacts_widget) (NstPlugin *plugin); + gboolean (*validate_destination) (NstPlugin *plugin, GtkWidget *contact_widget, char **error); + gboolean (*send_files) (NstPlugin *plugin, + GtkWidget *contact_widget, + GList *file_list); + gboolean (*destroy) (NstPlugin *plugin) ; +}; + +/** + * NstPlugin: + * @module: the #GModule for the opened shared library + * @info: a #NstPluginInfo structure + * + * A structure as used in caja-sendto. + **/ +struct _NstPlugin +{ + GModule *module; + NstPluginInfo *info; +}; + +/** + * NST_INIT_PLUGIN: + * @plugininfo: a #NstPluginInfo structure representing the plugin + * + * Call this on an #NstPluginInfo structure to make it available to caja-sendto. + **/ +# define NST_INIT_PLUGIN(plugininfo) \ + gboolean nst_init_plugin(NstPlugin *plugin); \ + G_MODULE_EXPORT gboolean nst_init_plugin(NstPlugin *plugin) { \ + plugin->info = &(plugininfo); \ + return TRUE; \ + } + +#endif /* _CAJA_SENDTO_PLUGIN_H_ */ + diff --git a/sendto/caja-sendto.1 b/sendto/caja-sendto.1 new file mode 100644 index 0000000..bcb8430 --- /dev/null +++ b/sendto/caja-sendto.1 @@ -0,0 +1,27 @@ +.TH CAJA-SENDTO 1 2006\-07\-18 "MATE" "MATE" +.SH NAME +caja\-sendto \- convenience application to send a file via email or instant messenger +.SH SYNOPSIS +.B caja-sendto +.RI [ OPTIONS " " | " " FILES... ] +.SH DESCRIPTION +Send FILE(s) via email or instant messenger. + +A dialog window presents a choice of carrier application and recipient of the file(s). +Recipent names can be selected from a list or autocompleted. The selected application +is then opened with the file(s) and recipient ready for transfer. + +The application is intented to integrate with caja and is +written for the MATE graphical desktop. +.SH OPTIONS +.TP +.B \-?, \-\-help +Show a help message listing all the options and their meanings. +.SH AUTHOR +Written by Roberto Majadas +.PP +This manual page was originally written by Oystein Gisnas for the +Debian system. +.\" Copyright 2006 Oystein Gisnas +.\" You may copy this manual page under the terms of the version 2 of +.\" the GNU General Public License. diff --git a/sendto/caja-sendto.pc.in b/sendto/caja-sendto.pc.in new file mode 100644 index 0000000..50f629f --- /dev/null +++ b/sendto/caja-sendto.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +includedir=@includedir@ +pluginsdir=@libdir@/caja-sendto/plugins + +Name: caja-sendto +Description: Extend caja-sendto through plugins +Version: @VERSION@ +Requires: glib-2.0 gmodule-2.0 gtk+-2.0 +Cflags: -I${includedir}/caja-sendto diff --git a/sendto/caja-sendto.ui b/sendto/caja-sendto.ui new file mode 100644 index 0000000..44db667 --- /dev/null +++ b/sendto/caja-sendto.ui @@ -0,0 +1,498 @@ + + + + + + + + + + .zip + + + .tar.gz + + + .tar.bz2 + + + + + 5 + 370 + True + Send To... + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + False + False + document-send + + + True + False + 2 + + + True + GTK_BUTTONBOX_END + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + + + + + True + True + True + GTK_RELIEF_NORMAL + True + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + True + False + 2 + + + True + document-send + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + True + _Send + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + + 0 + False + True + GTK_PACK_END + + + + + 5 + True + False + 18 + + + True + False + 6 + + + True + <b>Destination</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + True + 2 + 2 + False + 6 + 12 + + + True + Send _as: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + options_combobox + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + True + False + True + + + 1 + 2 + 0 + 1 + fill + + + + + True + Send t_o: + True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + True + False + 12 + + + + + + 1 + 2 + 1 + 2 + fill + fill + + + + + + + 0 + True + True + + + + + 6 + False + True + + + + + True + False + 6 + + + True + <b>Compression</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + True + False + 6 + + + True + True + Send _packed in: + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + True + False + 6 + + + True + True + True + True + 0 + + True + * + False + + + 0 + True + True + + + + + True + False + True + model1 + + + + 0 + + + + + 0 + True + True + + + + + + + 0 + True + True + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + 12 + + + gtk-dialog-error + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + True + + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_MIDDLE + -1 + False + 0 + + + 0 + True + True + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + cancel_button + send_button + + + diff --git a/sendto/docs/Makefile.am b/sendto/docs/Makefile.am new file mode 100644 index 0000000..830ec37 --- /dev/null +++ b/sendto/docs/Makefile.am @@ -0,0 +1,100 @@ +## Process this file with automake to produce Makefile.in + +# We require automake 1.6 at least. +AUTOMAKE_OPTIONS = 1.6 + +# This is a blank Makefile.am for using gtk-doc. +# Copy this to your project's API docs directory and modify the variables to +# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples +# of using the various options. + +# The name of the module, e.g. 'glib'. +DOC_MODULE=caja-sendto + +# Uncomment for versioned docs and specify the version of the module, e.g. '2'. +#DOC_MODULE_VERSION=2 + + +# The top-level SGML file. You can change this if you want to. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml + +# The directory containing the source code. Relative to $(srcdir). +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting the functions and macros. +# e.g. DOC_SOURCE_DIR=../../../gtk +DOC_SOURCE_DIR=../../src + +# Extra options to pass to gtkdoc-scangobj. Not normally needed. +SCANGOBJ_OPTIONS= + +# Extra options to supply to gtkdoc-scan. +# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" +SCAN_OPTIONS= + +# Extra options to supply to gtkdoc-mkdb. +# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml +MKDB_OPTIONS=--sgml-mode --output-format=xml + +# Extra options to supply to gtkdoc-mktmpl +# e.g. MKTMPL_OPTIONS=--only-section-tmpl +MKTMPL_OPTIONS= + +# Extra options to supply to gtkdoc-mkhtml +MKHTML_OPTIONS= + +# Extra options to supply to gtkdoc-fixref. Not normally needed. +# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html +FIXXREF_OPTIONS= + +# Used for dependencies. The docs will be rebuilt if any of these change. +# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h +# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c +HFILE_GLOB=$(top_srcdir)/src/*.h +CFILE_GLOB=$(top_srcdir)/src/*.c + +# Header files to ignore when scanning. +# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h +IGNORE_HFILES=caja-nste.h bluetooth-marshal.h e-contact-entry.h econtactentry-marshal.h nst-common.h + +# Images to copy into HTML directory. +# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png +HTML_IMAGES= + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +# e.g. content_files=running.sgml building.sgml changes-2.0.sgml +content_files=version.xml + +# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded +# These files must be listed here *and* in content_files +# e.g. expand_content_files=running.sgml +expand_content_files= + +# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. +# Only needed if you are using gtkdoc-scangobj to dynamically query widget +# signals and properties. +# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) +# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) +GTKDOC_CFLAGS=$(CAJA_SENDTO_CFLAGS) +GTKDOC_LIBS=$(top_builddir)/src/libnstplugin.la + +# This includes the standard gtk-doc make rules, copied by gtkdocize. +include $(top_srcdir)/gtk-doc.make + +# Other files to distribute +# e.g. EXTRA_DIST += version.xml.in +EXTRA_DIST += version.xml.in + +# Files not to distribute +# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types +# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt +#DISTCLEANFILES += + +# Comment this out if you want your docs-status tested during 'make check' +#TESTS = $(GTKDOC_CHECK) + +if ENABLE_GTK_DOC +TESTS_ENVIRONMENT = cd $(srcdir) && +TESTS = $(GTKDOC_CHECK) +endif + + diff --git a/sendto/docs/caja-sendto-docs.sgml b/sendto/docs/caja-sendto-docs.sgml new file mode 100644 index 0000000..5e849f2 --- /dev/null +++ b/sendto/docs/caja-sendto-docs.sgml @@ -0,0 +1,29 @@ + + + +]> + + + caja-sendto Reference Manual + + for caja-sendto &version; + The latest version of this documentation can be found on-line at + http://library.mate.org/devel/caja-sendto/index.html. + + + + + caja-sendto documentation + + + + + API Index + + + + + diff --git a/sendto/docs/caja-sendto-overrides.txt b/sendto/docs/caja-sendto-overrides.txt new file mode 100644 index 0000000..e69de29 diff --git a/sendto/docs/caja-sendto-sections.txt b/sendto/docs/caja-sendto-sections.txt new file mode 100644 index 0000000..9a94c9d --- /dev/null +++ b/sendto/docs/caja-sendto-sections.txt @@ -0,0 +1,14 @@ +
+caja-sendto-plugin +NstPluginInfo +NstPlugin +NstPluginCapabilities +NST_INIT_PLUGIN +
+ +
+nst-enum-types +nst_plugin_capabilities_get_type +NST_TYPE_PLUGIN_CAPABILITIES +
+ diff --git a/sendto/docs/caja-sendto.types b/sendto/docs/caja-sendto.types new file mode 100644 index 0000000..a177dee --- /dev/null +++ b/sendto/docs/caja-sendto.types @@ -0,0 +1 @@ +nst_plugin_capabilities_get_type diff --git a/sendto/docs/html/annotation-glossary.html b/sendto/docs/html/annotation-glossary.html new file mode 100644 index 0000000..b088d39 --- /dev/null +++ b/sendto/docs/html/annotation-glossary.html @@ -0,0 +1,36 @@ + + + + +Annotation Glossary + + + + + + + + + + + + + + + + + + +
+

+Annotation Glossary

+

E

+
+element-type
+

Generics and defining elements of containers and arrays.

+
+ + + \ No newline at end of file diff --git a/sendto/docs/html/api-index-full.html b/sendto/docs/html/api-index-full.html new file mode 100644 index 0000000..f373472 --- /dev/null +++ b/sendto/docs/html/api-index-full.html @@ -0,0 +1,66 @@ + + + + +API Index + + + + + + + + + + + + + + + + + + + +
+

+API Index

+

I

+
+NST_INIT_PLUGIN, macro in caja-sendto-plugin +
+
+

P

+
+NstPlugin, struct in caja-sendto-plugin +
+
+
+NstPluginCapabilities, enum in caja-sendto-plugin +
+
+
+NstPluginInfo, struct in caja-sendto-plugin +
+
+
+nst_plugin_capabilities_get_type, function in nst-enum-types +
+
+

T

+
+NST_TYPE_PLUGIN_CAPABILITIES, macro in nst-enum-types +
+
+
+ + + \ No newline at end of file diff --git a/sendto/docs/html/caja-sendto-caja-sendto-plugin.html b/sendto/docs/html/caja-sendto-caja-sendto-plugin.html new file mode 100644 index 0000000..e8961cb --- /dev/null +++ b/sendto/docs/html/caja-sendto-caja-sendto-plugin.html @@ -0,0 +1,219 @@ + + + + +caja-sendto-plugin + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+

caja-sendto-plugin

+

caja-sendto-plugin — caja-sento plug-in

+
+
+

Stability Level

+Stable, unless otherwise indicated +
+
+

Synopsis

+
+#include <bluetooth-plugin.h>
+
+                    NstPluginInfo;
+                    NstPlugin;
+enum                NstPluginCapabilities;
+#define             NST_INIT_PLUGIN                     (plugininfo)
+
+
+
+

Description

+

+Plug-ins can be used to extend caja-sendto. +

+
+
+

Details

+
+

NstPluginInfo

+
typedef struct {
+	gchar                             *icon;
+	gchar                             *id;
+	gchar                             *description;
+	gchar                             *gettext_package;
+	NstPluginCapabilities              capabilities;
+	gboolean (*init)                  (NstPlugin *plugin);
+	GtkWidget* (*get_contacts_widget) (NstPlugin *plugin);
+	gboolean (*validate_destination)  (NstPlugin *plugin, GtkWidget *contact_widget, char **error);
+	gboolean (*send_files)            (NstPlugin *plugin,
+					   GtkWidget *contact_widget,
+					   GList *file_list);
+	gboolean (*destroy)               (NstPlugin *plugin) ;
+} NstPluginInfo;
+
+

+A structure representing a caja-sendto plugin. You should also call NST_INIT_PLUGIN() on the plugin structure to export it. +

+
++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

gchar *icon;

The icon name for the plugin selection drop-down +

gchar *id;

A unique ID representing the plugin +

gchar *description;

The label used in the plugin selection drop-down +

gchar *gettext_package;

The domain to use to translate the description, NULL if the plugin is part of caja-sendto +

NstPluginCapabilities capabilities;

a bitmask of NstPluginCapabilities +

init ()

Check for dependencies, and return FALSE if dependencies such as programs are missing. +

get_contacts_widget ()

Return the contact widget, the widget to select the destination of the files +

validate_destination ()

Validate whether the destination can receive the file. This callback is optional. +

send_files ()

Actually send the files to the selected destination. The file list is a GList of URI strings. +

destroy ()

Free all the resources used by the plugin. +
+
+
+
+

NstPlugin

+
typedef struct {
+	GModule *module;
+	NstPluginInfo *info;
+} NstPlugin;
+
+

+A structure as used in caja-sendto. +

+
++ + + + + + + + + + +

GModule *module;

the GModule for the opened shared library +

NstPluginInfo *info;

a NstPluginInfo structure +
+
+
+
+

enum NstPluginCapabilities

+
typedef enum {
+	CAJA_CAPS_NONE = 0,
+	CAJA_CAPS_SEND_DIRECTORIES = 1 << 0,
+	CAJA_CAPS_SEND_IMAGES = 1 << 1,
+} NstPluginCapabilities;
+
+

+Capabilities of the plugin. +

+
++ + + + + + + + + + + + + + +

CAJA_CAPS_NONE

No capabilities +

CAJA_CAPS_SEND_DIRECTORIES

The plugin can send whole directories without compression +

CAJA_CAPS_SEND_IMAGES

The plugin only sends images which could be resized +
+
+
+
+

NST_INIT_PLUGIN()

+
#define             NST_INIT_PLUGIN(plugininfo)
+

+Call this on an NstPluginInfo structure to make it available to caja-sendto. +

+
++ + + + +

plugininfo :

a NstPluginInfo structure representing the plugin +
+
+
+
+ + + \ No newline at end of file diff --git a/sendto/docs/html/caja-sendto.devhelp b/sendto/docs/html/caja-sendto.devhelp new file mode 100644 index 0000000..a536a45 --- /dev/null +++ b/sendto/docs/html/caja-sendto.devhelp @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/sendto/docs/html/caja-sendto.devhelp2 b/sendto/docs/html/caja-sendto.devhelp2 new file mode 100644 index 0000000..de85c9d --- /dev/null +++ b/sendto/docs/html/caja-sendto.devhelp2 @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/sendto/docs/html/ch01.html b/sendto/docs/html/ch01.html new file mode 100644 index 0000000..ff74863 --- /dev/null +++ b/sendto/docs/html/ch01.html @@ -0,0 +1,33 @@ + + + + +caja-sendto documentation + + + + + + + + + + + + + + + + +
+

+caja-sendto documentation

+
+caja-sendto-plugin — caja-sento plug-in +
+
+ + + \ No newline at end of file diff --git a/sendto/docs/html/home.png b/sendto/docs/html/home.png new file mode 100644 index 0000000..1700361 Binary files /dev/null and b/sendto/docs/html/home.png differ diff --git a/sendto/docs/html/index.html b/sendto/docs/html/index.html new file mode 100644 index 0000000..6183dbf --- /dev/null +++ b/sendto/docs/html/index.html @@ -0,0 +1,39 @@ + + + + +caja-sendto Reference Manual + + + + + + + +
+
+
+
+

+ for caja-sendto 2.32.0 + + The latest version of this documentation can be found on-line at + http://library.mate.org/devel/caja-sendto/index.html. +

+
+
+
+ +
+ + + \ No newline at end of file diff --git a/sendto/docs/html/index.sgml b/sendto/docs/html/index.sgml new file mode 100644 index 0000000..de59262 --- /dev/null +++ b/sendto/docs/html/index.sgml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/sendto/docs/html/left.png b/sendto/docs/html/left.png new file mode 100644 index 0000000..2d05b3d Binary files /dev/null and b/sendto/docs/html/left.png differ diff --git a/sendto/docs/html/right.png b/sendto/docs/html/right.png new file mode 100644 index 0000000..92832e3 Binary files /dev/null and b/sendto/docs/html/right.png differ diff --git a/sendto/docs/html/style.css b/sendto/docs/html/style.css new file mode 100644 index 0000000..d544a2c --- /dev/null +++ b/sendto/docs/html/style.css @@ -0,0 +1,265 @@ +.synopsis, .classsynopsis +{ + /* tango:aluminium 1/2 */ + background: #eeeeec; + border: solid 1px #d3d7cf; + padding: 0.5em; +} +.programlisting +{ + /* tango:sky blue 0/1 */ + background: #e6f3ff; + border: solid 1px #729fcf; + padding: 0.5em; +} +.variablelist +{ + padding: 4px; + margin-left: 3em; +} +.variablelist td:first-child +{ + vertical-align: top; +} + +@media screen { + sup a.footnote + { + position: relative; + top: 0em ! important; + + } + /* this is needed so that the local anchors are displayed below the naviagtion */ + div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name] + { + position: relative; + padding-top:4.5em; + } + /* this seems to be a bug in the xsl style sheets when generating indexes */ + div.index div.index + { + top: 0em; + } + /* make space for the fixed navigation bar and add space at the bottom so that + * link targets appear somewhat close to top + */ + body + { + padding-top: 3.2em; + padding-bottom: 20em; + } + /* style and size the navigation bar */ + table.navigation#top + { + position: fixed; + /* tango:scarlet red 0/1 */ + background: #ffe6e6; + border: solid 1px #ef2929; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + height: 3em; + z-index: 10; + } + .navigation a, .navigation a:visited + { + /* tango:scarlet red 3 */ + color: #a40000; + } + .navigation a:hover + { + /* tango:scarlet red 1 */ + color: #ef2929; + } + td.shortcuts + { + /* tango:scarlet red 1 */ + color: #ef2929; + font-size: 80%; + white-space: nowrap; + } +} +@media print { + table.navigation { + visibility: collapse; + display: none; + } + div.titlepage table.navigation { + visibility: visible; + display: table; + /* tango:scarlet red 0/1 */ + background: #ffe6e6; + border: solid 1px #ef2929; + margin-top: 0; + margin-bottom: 0; + top: 0; + left: 0; + height: 3em; + } +} + +.navigation .title +{ + font-size: 200%; +} + +div.gallery-float +{ + float: left; + padding: 10px; +} +div.gallery-float img +{ + border-style: none; +} +div.gallery-spacer +{ + clear: both; +} + +a, a:visited +{ + text-decoration: none; + /* tango:sky blue 2 */ + color: #3465a4; +} +a:hover +{ + text-decoration: underline; + /* tango:sky blue 1 */ + color: #729fcf; +} + +div.table table +{ + border-collapse: collapse; + border-spacing: 0px; + /* tango:aluminium 3 */ + border: solid 1px #babdb6; +} + +div.table table td, div.table table th +{ + /* tango:aluminium 3 */ + border: solid 1px #babdb6; + padding: 3px; + vertical-align: top; +} + +div.table table th +{ + /* tango:aluminium 2 */ + background-color: #d3d7cf; +} + +hr +{ + /* tango:aluminium 3 */ + color: #babdb6; + background: #babdb6; + border: none 0px; + height: 1px; + clear: both; +} + +.footer +{ + padding-top: 3.5em; + /* tango:aluminium 3 */ + color: #babdb6; + text-align: center; + font-size: 80%; +} + +.warning +{ + /* tango:orange 0/1 */ + background: #ffeed9; + border-color: #ffb04f; +} +.note +{ + /* tango:chameleon 0/0.5 */ + background: #d8ffb2; + border-color: #abf562; +} +.note, .warning +{ + padding: 0.5em; + border-width: 1px; + border-style: solid; +} +.note h3, .warning h3 +{ + margin-top: 0.0em +} +.note p, .warning p +{ + margin-bottom: 0.0em +} + +/* blob links */ +h2 .extralinks, h3 .extralinks +{ + float: right; + /* tango:aluminium 3 */ + color: #babdb6; + font-size: 80%; + font-weight: normal; +} + +.annotation +{ + /* tango:aluminium 5 */ + color: #555753; + font-size: 80%; + font-weight: normal; +} + +/* code listings */ + +.listing_code .programlisting .cbracket { color: #a40000; } /* tango: scarlet red 3 */ +.listing_code .programlisting .comment { color: #a1a39d; } /* tango: aluminium 4 */ +.listing_code .programlisting .function { color: #000000; font-weight: bold; } +.listing_code .programlisting .function a { color: #11326b; font-weight: bold; } /* tango: sky blue 4 */ +.listing_code .programlisting .keyword { color: #4e9a06; } /* tango: chameleon 3 */ +.listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */ +.listing_code .programlisting .normal { color: #000000; } +.listing_code .programlisting .number { color: #75507b; } /* tango: plum 2 */ +.listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */ +.listing_code .programlisting .string { color: #c17d11; } /* tango: chocolate 2 */ +.listing_code .programlisting .type { color: #000000; } +.listing_code .programlisting .type a { color: #11326b; } /* tango: sky blue 4 */ +.listing_code .programlisting .symbol { color: #ce5c00; } /* tango: orange 3 */ + +.listing_frame { + /* tango:sky blue 1 */ + border: solid 1px #729fcf; + padding: 0px; +} + +.listing_lines, .listing_code { + margin-top: 0px; + margin-bottom: 0px; + padding: 0.5em; +} +.listing_lines { + /* tango:sky blue 0.5 */ + background: #a6c5e3; + /* tango:aluminium 6 */ + color: #2e3436; +} +.listing_code { + /* tango:sky blue 0 */ + background: #e6f3ff; +} +.listing_code .programlisting { + /* override from previous */ + border: none 0px; + padding: 0px; +} +.listing_lines pre, .listing_code pre { + margin: 0px; +} + diff --git a/sendto/docs/html/up.png b/sendto/docs/html/up.png new file mode 100644 index 0000000..85b3e2a Binary files /dev/null and b/sendto/docs/html/up.png differ diff --git a/sendto/docs/tmpl/caja-sendto-mimetype.sgml b/sendto/docs/tmpl/caja-sendto-mimetype.sgml new file mode 100644 index 0000000..e54fb59 --- /dev/null +++ b/sendto/docs/tmpl/caja-sendto-mimetype.sgml @@ -0,0 +1,33 @@ + +caja-sendto-mimetype + + + + + + + + + + + + + + + + + + + + + + + + + +@mimetypes: +@num_files: +@num_dirs: +@Returns: + + diff --git a/sendto/docs/tmpl/caja-sendto-packer.sgml b/sendto/docs/tmpl/caja-sendto-packer.sgml new file mode 100644 index 0000000..08dc602 --- /dev/null +++ b/sendto/docs/tmpl/caja-sendto-packer.sgml @@ -0,0 +1,112 @@ + +NstPackWidget + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@parent: + + + + + + +@void: +@Returns: + + + + + + + +@widget: +@file_list: +@Returns: + + + + + + + +@widget: +@file_list: + + + + + + + +@widget: +@enabled: + + + + + + + +@widget: +@Returns: + + + + + + + +@widget: +@force_enabled: + + + + + + + +@widget: +@Returns: + + diff --git a/sendto/docs/tmpl/caja-sendto-plugin.sgml b/sendto/docs/tmpl/caja-sendto-plugin.sgml new file mode 100644 index 0000000..89ae0d7 --- /dev/null +++ b/sendto/docs/tmpl/caja-sendto-plugin.sgml @@ -0,0 +1,63 @@ + +caja-sendto-plugin + + + + + + + + + + + + + + + + + + + + + + + + + +@icon: +@id: +@description: +@gettext_package: +@capabilities: +@init: +@get_contacts_widget: +@validate_destination: +@send_files: +@destroy: + + + + + + +@module: +@info: + + + + + + +@CAJA_CAPS_NONE: +@CAJA_CAPS_SEND_DIRECTORIES: +@CAJA_CAPS_SEND_IMAGES: + + + + + + +@plugininfo: + + diff --git a/sendto/docs/tmpl/caja-sendto-unused.sgml b/sendto/docs/tmpl/caja-sendto-unused.sgml new file mode 100644 index 0000000..c275685 --- /dev/null +++ b/sendto/docs/tmpl/caja-sendto-unused.sgml @@ -0,0 +1,368 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +caja-sendto-mimetype + + + + + + + + + + + + + + + + + + + + + + + + + + + +NstPackWidget + + + + + + + + + + + + + + + + + + + + + + + +nst-common + + + + + + + + + + + + + + + + + + + + + + + + + + + +nst-plugin-marshal + + + + + + + +@TYPE_NAME: +@TypeName: +@type_name: + + + + + + +@obj: + + + + + + + + + + + + + + + + + + +@cajasendtoplugin: the object which received the signal. +@arg1: +@arg2: +@arg3: +@arg4: + + + + + + +@cajasendtoplugin: the object which received the signal. +@arg1: +@arg2: + + + + + + +@g_iface: +@supports_mime_types: +@send_files: +@add_widget: +@can_send: + + + + + + +@NST_SEND_STATUS_SUCCESS: +@NST_SEND_STATUS_SUCCESS_DONE: +@NST_SEND_STATUS_FAILED: + + + + + + + + + + + + + + + + + + +@parent: + + + + + + + + + + + + + + + + + + + + + + + + +@file_list: +@dest: +@Returns: + + + + + + +@plugin: +@Returns: + + + + + + +@plugin: +@file_list: +@Returns: + + + + + + +@plugin: +@file_list: +@callback: +@user_data: + + + + + + +@plugin: +@res: +@error: +@Returns: + + + + + + +@plugin: +@file_list: +@mime_types: +@Returns: + + + + + + +@void: +@Returns: + + + + + + +@widget: +@Returns: + + + + + + +@widget: +@Returns: + + + + + + +@void: +@Returns: + + + + + + +@widget: +@file_list: +@Returns: + + + + + + +@widget: +@enabled: + + + + + + +@widget: +@force_enabled: + + + + + + +@widget: +@file_list: + + + + + + +@closure: +@return_value: +@n_param_values: +@param_values: +@invocation_hint: +@marshal_data: + + + + + + +@closure: +@return_value: +@n_param_values: +@param_values: +@invocation_hint: +@marshal_data: + + + + + + +@mimetypes: +@num_files: +@num_dirs: +@Returns: + diff --git a/sendto/docs/tmpl/nst-common.sgml b/sendto/docs/tmpl/nst-common.sgml new file mode 100644 index 0000000..295aa9a --- /dev/null +++ b/sendto/docs/tmpl/nst-common.sgml @@ -0,0 +1,31 @@ + +nst-common + + + + + + + + + + + + + + + + + + + + + + + + +@file_list: +@dest: +@Returns: + + diff --git a/sendto/docs/tmpl/nst-enum-types.sgml b/sendto/docs/tmpl/nst-enum-types.sgml new file mode 100644 index 0000000..abba0dc --- /dev/null +++ b/sendto/docs/tmpl/nst-enum-types.sgml @@ -0,0 +1,38 @@ + +nst-enum-types + + + + + + + + + + + + + + + + + + + + + + + + + +@void: +@Returns: + + + + + + + + + diff --git a/sendto/docs/tmpl/nst-plugin-marshal.sgml b/sendto/docs/tmpl/nst-plugin-marshal.sgml new file mode 100644 index 0000000..9731804 --- /dev/null +++ b/sendto/docs/tmpl/nst-plugin-marshal.sgml @@ -0,0 +1,50 @@ + +nst-plugin-marshal + + + + + + + + + + + + + + + + + + + + + + + + + + + +@closure: +@return_value: +@n_param_values: +@param_values: +@invocation_hint: +@marshal_data: + + + + + + + +@closure: +@return_value: +@n_param_values: +@param_values: +@invocation_hint: +@marshal_data: + + diff --git a/sendto/docs/version.xml.in b/sendto/docs/version.xml.in new file mode 100644 index 0000000..d78bda9 --- /dev/null +++ b/sendto/docs/version.xml.in @@ -0,0 +1 @@ +@VERSION@ diff --git a/sendto/org.mate.Caja.Sendto.gschema.xml.in b/sendto/org.mate.Caja.Sendto.gschema.xml.in new file mode 100644 index 0000000..cc48a5d --- /dev/null +++ b/sendto/org.mate.Caja.Sendto.gschema.xml.in @@ -0,0 +1,21 @@ + + + + + '' + Last plugin used to send + + Used to store which plugin was used the last time + files were sent using caja-sendto. + + + + 0 + Last type of archive used + + Used to store which type of archive was used the last time + (0: zip, 1: tar.gz, 2: tar.bz2). + + + + diff --git a/sendto/plugins/Makefile.am b/sendto/plugins/Makefile.am new file mode 100644 index 0000000..10097e8 --- /dev/null +++ b/sendto/plugins/Makefile.am @@ -0,0 +1,16 @@ +SUBDIRS = . \ + caja-burn \ + emailclient \ + gajim \ + pidgin \ + removable-devices \ + upnp + +NST_COMMON_SOURCES = nst-common.c nst-common.h + +noinst_LTLIBRARIES = libnstcommon.la +libnstcommon_la_SOURCES = $(NST_COMMON_SOURCES) +libnstcommon_la_CFLAGS = $(SENDTO_CFLAGS) +libnstcommon_la_LIBADD = $(SENDTO_LIBS) + +EXTRA_DIST = $(NST_COMMON_SOURCES) diff --git a/sendto/plugins/caja-burn/Makefile.am b/sendto/plugins/caja-burn/Makefile.am new file mode 100644 index 0000000..50c309b --- /dev/null +++ b/sendto/plugins/caja-burn/Makefile.am @@ -0,0 +1,19 @@ +plugindir = $(libdir)/caja-sendto/plugins + +AM_CPPFLAGS = \ + -DDATADIR=\"$(datadir)\" \ + -DICONDIR=\"$(icondir)\" \ + -DLOCALEDIR="\"$(datadir)/locale\"" \ + -I$(top_srcdir)/sendto \ + -I$(top_builddir) \ + -I$(srcdir)/../ \ + $(SENDTO_CFLAGS) \ + $(WARN_CFLAGS) \ + $(DISABLE_DEPRECATED) + +plugin_LTLIBRARIES = libnstburn.la + +libnstburn_la_SOURCES = caja-burn.c +libnstburn_la_LDFLAGS = -module -avoid-version +libnstburn_la_LIBADD = $(SENDTO_LIBS) $(builddir)/../libnstcommon.la + diff --git a/sendto/plugins/caja-burn/caja-burn.c b/sendto/plugins/caja-burn/caja-burn.c new file mode 100644 index 0000000..07d2e41 --- /dev/null +++ b/sendto/plugins/caja-burn/caja-burn.c @@ -0,0 +1,189 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2008 Jader Henrique da Silva + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 + * General Public License for more av. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Author: Jader Henrique da Silva + */ + +#include "config.h" +#include +#include +#include "nst-common.h" +#include "caja-sendto-plugin.h" + +enum { + COL_PIXBUF, + COL_LABEL, + NUM_COLS, +}; + +#define COMBOBOX_OPTION_NEW_DVD 0 +#define COMBOBOX_OPTION_EXISTING_DVD 1 + +static GFile *burn = NULL; + +static +gboolean init (NstPlugin *plugin) +{ + GtkIconTheme *it; + char *cmd; + + g_print ("Init caja burn plugin\n"); + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + + it = gtk_icon_theme_get_default (); + gtk_icon_theme_append_search_path (it, DATADIR "/brasero/icons"); + + cmd = g_find_program_in_path ("brasero"); + if (cmd == NULL) + return FALSE; + g_free (cmd); + + burn = g_file_new_for_uri ("burn:/"); + + return TRUE; +} + +static +GtkWidget* get_contacts_widget (NstPlugin *plugin) +{ + GtkWidget *widget; + GtkCellRenderer *renderer; + GtkListStore *store; + GtkTreeModel *model; + GFileEnumerator *fenum; + GFileInfo *file_info = NULL; + int selection = COMBOBOX_OPTION_NEW_DVD; + + fenum = g_file_enumerate_children (burn, + G_FILE_ATTRIBUTE_STANDARD_NAME, + G_FILE_QUERY_INFO_NONE, + NULL, + NULL); + + if (fenum != NULL) { + file_info = g_file_enumerator_next_file (fenum, NULL, NULL); + g_object_unref (fenum); + } + + store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_STRING); + + gtk_list_store_insert_with_values (store, NULL, + INT_MAX, + COL_PIXBUF, "media-optical-blank", + COL_LABEL, _("New CD/DVD"), + -1); + + if (file_info != NULL) { + gtk_list_store_insert_with_values (store, NULL, + INT_MAX, + COL_PIXBUF, "media-optical-data-new", + COL_LABEL, _("Existing CD/DVD"), + -1); + g_object_unref (file_info); + selection = COMBOBOX_OPTION_EXISTING_DVD; + } + + model = GTK_TREE_MODEL (store); + widget = gtk_combo_box_new_with_model (model); + renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), + renderer, + FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget), + renderer, + "icon-name", COL_PIXBUF, + NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), + renderer, + TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget), + renderer, + "text", COL_LABEL, + NULL); + + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), selection); + + return widget; +} + +static +gboolean send_files (NstPlugin *plugin, + GtkWidget *burntype_widget, + GList *file_list) +{ + GFileEnumerator *fenum; + GFileInfo *file_info; + GFile *child; + + if (gtk_combo_box_get_active (GTK_COMBO_BOX (burntype_widget)) == COMBOBOX_OPTION_NEW_DVD) { + fenum = g_file_enumerate_children (burn, + G_FILE_ATTRIBUTE_STANDARD_NAME, + G_FILE_QUERY_INFO_NONE, + NULL, + NULL); + + if (fenum != NULL) { + while ((file_info = g_file_enumerator_next_file (fenum, NULL, NULL)) != NULL) { + child = g_file_get_child (burn, + g_file_info_get_name(file_info)); + + g_object_unref (file_info); + g_file_delete (child, NULL, NULL); + g_object_unref (child); + } + g_object_unref (fenum); + } + } + + copy_files_to (file_list, burn); + + gtk_show_uri (NULL, "burn:///", GDK_CURRENT_TIME, NULL); + + return TRUE; +} + +static +gboolean destroy (NstPlugin *plugin){ + + g_object_unref (burn); + burn = NULL; + return TRUE; + +} + +static +NstPluginInfo plugin_info = { + "brasero", + "caja-burn", + N_("CD/DVD Creator"), + NULL, + CAJA_CAPS_SEND_DIRECTORIES, + init, + get_contacts_widget, + NULL, + send_files, + destroy +}; + +NST_INIT_PLUGIN (plugin_info) + diff --git a/sendto/plugins/emailclient/Makefile.am b/sendto/plugins/emailclient/Makefile.am new file mode 100644 index 0000000..31ba40e --- /dev/null +++ b/sendto/plugins/emailclient/Makefile.am @@ -0,0 +1,17 @@ +plugindir = $(libdir)/caja-sendto/plugins + +AM_CPPFLAGS = \ + -DDATADIR=\"$(datadir)\" \ + -DICONDIR=\"$(icondir)\" \ + -DLOCALEDIR="\"$(datadir)/locale\"" \ + -I$(top_srcdir)/sendto \ + -I$(top_builddir) \ + $(SENDTO_CFLAGS) \ + $(DISABLE_DEPRECATED) \ + $(WARN_CFLAGS) + +plugin_LTLIBRARIES = libnstemailclient.la + +libnstemailclient_la_SOURCES = emailclient.c +libnstemailclient_la_LDFLAGS = -module -avoid-version +libnstemailclient_la_LIBADD = $(SENDTO_LIBS) diff --git a/sendto/plugins/emailclient/emailclient.c b/sendto/plugins/emailclient/emailclient.c new file mode 100644 index 0000000..14cb998 --- /dev/null +++ b/sendto/plugins/emailclient/emailclient.c @@ -0,0 +1,274 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2004 Roberto Majadas + * Copyright (C) 2012 Stefano Karapetsas + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 + * General Public License for more av. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Authors: Roberto Majadas + * Stefano Karapetsas + */ + +#include "config.h" + +#include +#include +#include "caja-sendto-plugin.h" +#include + +typedef enum { + MAILER_UNKNOWN, + MAILER_EVO, + MAILER_BALSA, + MAILER_SYLPHEED, + MAILER_THUNDERBIRD, +} MailerType; + +static char *mail_cmd = NULL; +static MailerType type = MAILER_UNKNOWN; + +static char * +get_evo_cmd (void) +{ + char *tmp = NULL; + char *retval; + char *cmds[] = {"evolution", + "evolution-2.0", + "evolution-2.2", + "evolution-2.4", + "evolution-2.6", + "evolution-2.8", /* for the future */ + "evolution-3.0", /* but how far to go ? */ + NULL}; + guint i; + + + for (i = 0; cmds[i] != NULL; i++) { + tmp = g_find_program_in_path (cmds[i]); + if (tmp != NULL) + break; + } + + if (tmp == NULL) + return NULL; + + retval = g_strdup_printf ("%s --component=mail %%s", tmp); + g_free (tmp); + return retval; +} + +static gboolean +init (NstPlugin *plugin) +{ + GAppInfo *app_info = NULL; + + g_print ("Init email client plugin\n"); + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + + app_info = g_app_info_get_default_for_uri_scheme ("mailto"); + if (app_info) { + mail_cmd = g_strdup(g_app_info_get_executable (app_info)); + g_object_unref (app_info); + } + + if (mail_cmd == NULL || *mail_cmd == '\0') { + g_free (mail_cmd); + mail_cmd = get_evo_cmd (); + type = MAILER_EVO; + } else { + /* Find what the default mailer is */ + if (strstr (mail_cmd, "balsa")) + type = MAILER_BALSA; + else if (strstr (mail_cmd, "thunder") || strstr (mail_cmd, "seamonkey")) { + char **strv; + + type = MAILER_THUNDERBIRD; + + /* Thunderbird sucks, see + * https://bugzilla.gnome.org/show_bug.cgi?id=614222 */ + strv = g_strsplit (mail_cmd, " ", -1); + g_free (mail_cmd); + mail_cmd = g_strdup_printf ("%s %%s", strv[0]); + g_strfreev (strv); + } else if (strstr (mail_cmd, "sylpheed") || strstr (mail_cmd, "claws")) + type = MAILER_SYLPHEED; + else if (strstr (mail_cmd, "anjal")) + type = MAILER_EVO; + } + + if (mail_cmd == NULL) + return FALSE; + + return TRUE; +} + +static +GtkWidget* get_contacts_widget (NstPlugin *plugin) +{ + GtkWidget *entry; + + // TODO: add an email address format check + entry = gtk_entry_new(); + + return entry; +} + +static void +get_evo_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list) +{ + GList *l; + + g_string_append (mailto, "mailto:"); + + const char *text; + + text = gtk_entry_get_text (GTK_ENTRY (contact_widget)); + if (text != NULL && *text != '\0') + g_string_append_printf (mailto, "\"%s\"", text); + else + g_string_append (mailto, "\"\""); + + g_string_append_printf (mailto,"?attach=\"%s\"", (char *)file_list->data); + for (l = file_list->next ; l; l=l->next){ + g_string_append_printf (mailto,"&attach=\"%s\"", (char *)l->data); + } +} + +static void +get_balsa_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list) +{ + GList *l; + + if (strstr (mail_cmd, " -m ") == NULL && strstr (mail_cmd, " --compose=") == NULL) + g_string_append (mailto, " --compose="); + + const char *text; + + text = gtk_entry_get_text (GTK_ENTRY (contact_widget)); + if (text != NULL && *text != '\0') + g_string_append_printf (mailto, "\"%s\"", text); + else + g_string_append (mailto, "\"\""); + + g_string_append_printf (mailto," --attach=\"%s\"", (char *)file_list->data); + for (l = file_list->next ; l; l=l->next){ + g_string_append_printf (mailto," --attach=\"%s\"", (char *)l->data); + } +} + +static void +get_thunderbird_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list) +{ + GList *l; + + g_string_append (mailto, "-compose \""); + + const char *text; + + text = gtk_entry_get_text (GTK_ENTRY (contact_widget)); + if (text != NULL && *text != '\0') + g_string_append_printf (mailto, "to='%s',", text); + + g_string_append_printf (mailto,"attachment='%s", (char *)file_list->data); + for (l = file_list->next ; l; l=l->next){ + g_string_append_printf (mailto,",%s", (char *)l->data); + } + g_string_append (mailto, "'\""); +} + +static void +get_sylpheed_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list) +{ + GList *l; + + g_string_append (mailto, "--compose "); + + const char *text; + + text = gtk_entry_get_text (GTK_ENTRY (contact_widget)); + if (text != NULL && *text != '\0') + g_string_append_printf (mailto, "\"%s\" ", text); + else + g_string_append (mailto, "\"\""); + + g_string_append_printf (mailto,"--attach \"%s\"", (char *)file_list->data); + for (l = file_list->next ; l; l=l->next){ + g_string_append_printf (mailto," \"%s\"", (char *)l->data); + } +} + +static gboolean +send_files (NstPlugin *plugin, + GtkWidget *contact_widget, + GList *file_list) +{ + gchar *cmd; + GString *mailto; + + mailto = g_string_new (""); + switch (type) { + case MAILER_BALSA: + get_balsa_mailto (contact_widget, mailto, file_list); + break; + case MAILER_SYLPHEED: + get_sylpheed_mailto (contact_widget, mailto, file_list); + break; + case MAILER_THUNDERBIRD: + get_thunderbird_mailto (contact_widget, mailto, file_list); + break; + case MAILER_EVO: + default: + get_evo_mailto (contact_widget, mailto, file_list); + } + + cmd = g_strdup_printf (mail_cmd, mailto->str); + g_string_free (mailto, TRUE); + + g_message ("Mailer type: %d", type); + g_message ("Command: %s", cmd); + + g_spawn_command_line_async (cmd, NULL); + g_free (cmd); + + return TRUE; +} + +static +gboolean destroy (NstPlugin *plugin){ + g_free (mail_cmd); + mail_cmd = NULL; + return TRUE; +} + +static +NstPluginInfo plugin_info = { + "emblem-mail", + "emailclient", + N_("Email"), + NULL, + CAJA_CAPS_NONE, + init, + get_contacts_widget, + NULL, + send_files, + destroy +}; + +NST_INIT_PLUGIN (plugin_info) + diff --git a/sendto/plugins/gajim/Makefile.am b/sendto/plugins/gajim/Makefile.am new file mode 100644 index 0000000..5acd5b0 --- /dev/null +++ b/sendto/plugins/gajim/Makefile.am @@ -0,0 +1,18 @@ +plugindir = $(libdir)/caja-sendto/plugins + +AM_CPPFLAGS = \ + -DDATADIR=\"$(datadir)\" \ + -DICONDIR=\"$(icondir)\" \ + -DLOCALEDIR="\"$(datadir)/locale\"" \ + -I$(top_srcdir)/sendto \ + -I$(top_builddir) \ + $(SENDTO_CFLAGS) \ + $(DISABLE_DEPRECATED) \ + $(WARN_CFLAGS) + +plugin_LTLIBRARIES = libnstgajim.la + +libnstgajim_la_SOURCES = gajim.c +libnstgajim_la_LDFLAGS = -module -avoid-version +libnstgajim_la_LIBADD = $(SENDTO_LIBS) + diff --git a/sendto/plugins/gajim/gajim.c b/sendto/plugins/gajim/gajim.c new file mode 100644 index 0000000..bb00d1d --- /dev/null +++ b/sendto/plugins/gajim/gajim.c @@ -0,0 +1,516 @@ +/* + * gajim.c + * gajim plugin for caja-sendto + * + * Copyright (C) 2006 Dimitur Kirov + * 2006 Roberto Majadas + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 + * General Public License for more av. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "config.h" +#include +#include +#include +#include "caja-sendto-plugin.h" + +#define OBJ_PATH "/org/gajim/dbus/RemoteObject" +#define INTERFACE "org.gajim.dbus.RemoteInterface" +#define SERVICE "org.gajim.dbus" + +const gchar *COMPLETION_PROPS[] = {"name", "jid"}; +/* list of contacts, which are not offline */ +static GHashTable *jid_table = NULL; +static gchar *iconset; + + +DBusGProxy *proxy = NULL; + +/* + * contact cb, gets property from contact dict + * and put online contacts to jid_table + */ +static void +_foreach_contact(gpointer contact, gpointer user_data) +{ + const gchar *show; + + GValue *value; + GHashTable *contact_table; + + /* holds contact props of already exisiting jid/nick */ + GHashTable *existing_contact; + + /* name of the contact in completion list + it may be jid, nick, jid (account), or nick(account) */ + GString *contact_str; + + gchar *jid; + gchar *account; + gint i; + + if (contact == NULL) { + g_warning("Null contact in the list"); + return; + } + contact_table = (GHashTable *) contact; + account = (gchar *) user_data; + + value = g_hash_table_lookup(contact_table, "show"); + if (value == NULL || !G_VALUE_HOLDS_STRING(value)) { + g_warning("String expected (contact - show)"); + g_hash_table_destroy(contact_table); + return; + } + show = g_value_get_string ((GValue *)value); + if(g_str_equal(show, "offline") || g_str_equal(show, "error")) { + g_hash_table_destroy(contact_table); + return; + } + /* remove unneeded item with key resource and add account + to contact properties */ + g_hash_table_insert(contact_table, "account", account); + g_hash_table_remove(contact_table, "resource"); + + /* add nick the same way as jid */ + for(i=0;i<2;i++) { + value = g_hash_table_lookup(contact_table, COMPLETION_PROPS[i]); + if(value == NULL || !G_VALUE_HOLDS_STRING(value)) { + g_warning("String expected (contact - name)"); + return; + } + jid = g_value_dup_string((GValue *)value); + existing_contact = g_hash_table_lookup(jid_table, jid); + if(existing_contact) { + /* add existing contact as nick (account) */ + contact_str = g_string_new(jid); + g_string_append(contact_str, " ("); + g_string_append(contact_str, + g_hash_table_lookup(existing_contact, "account")); + g_string_append(contact_str, ")"); + g_hash_table_insert(jid_table, contact_str->str, + existing_contact); + g_string_free(contact_str, FALSE); + + /* add current contact as nick (account) */ + contact_str = g_string_new(jid); + g_string_append(contact_str, " ("); + g_string_append(contact_str, + g_hash_table_lookup(contact_table, "account")); + g_string_append(contact_str, ")"); + g_hash_table_insert(jid_table, contact_str->str, + contact_table); + g_string_free(contact_str, FALSE); + } + else { + g_hash_table_insert(jid_table, jid, contact_table); + } + } + +} + +/* + * connect to session bus, onsuccess return TRUE + */ +static gboolean +init_dbus (void) +{ + DBusGConnection *connection; + GError *error; + gchar **accounts; + + error = NULL; + connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + if(error != NULL) { + g_warning("[Gajim] unable to get session bus, error was:\n %s", error->message); + g_error_free(error); + return FALSE; + } + proxy = dbus_g_proxy_new_for_name(connection, + SERVICE, + OBJ_PATH, + INTERFACE); + dbus_g_connection_unref(connection); + if (proxy == NULL){ + return FALSE; + } + + error = NULL; + if (!dbus_g_proxy_call (proxy, "list_accounts", &error, G_TYPE_INVALID, + G_TYPE_STRV, &accounts, G_TYPE_INVALID)) + { + g_object_unref(proxy); + g_error_free(error); + return FALSE; + } + g_strfreev(accounts); + return TRUE; +} + +/* + * Print appropriate warnings when dbus raised error + * on queries + */ +static void +_handle_dbus_exception (GError *error, gboolean empty_list_messages) +{ + if (error == NULL) { + g_warning("[Gajim] unable to parse result"); + return; + } + else if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) { + g_warning ("[Gajim] caught remote method exception %s: %s", + dbus_g_error_get_name (error), + error->message); + } + else if(empty_list_messages) { + /* empty list and error goes here */ + g_warning ("[Gajim] empty result set: %d %d %s\n", error->domain, + error->code, error->message); + } + g_error_free (error); +} + +/* + * query object, about the contact list for each account + * and fill all available contacts in the contacts table + */ +static gboolean +_get_contacts (void) +{ + GError *error; + GSList *contacts_list; + GHashTable *prefs_map; + gchar **accounts; + gchar **account_iter; + gchar *account; + + error = NULL; + + if (proxy == NULL) { + g_warning("[Gajim] unable to connect to session bus"); + return FALSE; + } + /* get gajim prefs and lookup for iconset */ + if (!dbus_g_proxy_call(proxy, "prefs_list", &error, G_TYPE_INVALID, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), + &prefs_map, G_TYPE_INVALID)) + { + _handle_dbus_exception(error, TRUE); + return FALSE; + } + gpointer iconset_ptr = g_hash_table_lookup(prefs_map, "iconset"); + if (iconset_ptr != NULL) { + iconset = g_strdup((gchar *)iconset_ptr); + } else { + g_warning("[Gajim] unable to get prefs value for iconset"); + return FALSE; + } + g_hash_table_destroy(prefs_map); + /* END get gajim prefs */ + error= NULL; + if (!dbus_g_proxy_call (proxy, "list_accounts", &error, G_TYPE_INVALID, + G_TYPE_STRV, + &accounts, G_TYPE_INVALID)) + { + _handle_dbus_exception(error, TRUE); + return FALSE; + } + for(account_iter = accounts; *account_iter ; account_iter++) { + account = g_strdup(*account_iter); + error = NULL; + /* query gajim remote object and put results in 'contacts_list' */ + if (!dbus_g_proxy_call (proxy, "list_contacts", &error, + G_TYPE_STRING, account, /* call arguments */ + G_TYPE_INVALID, /* delimiter */ + /* return value is collection of maps */ + dbus_g_type_get_collection ("GSList", + dbus_g_type_get_map ("GHashTable", + G_TYPE_STRING, G_TYPE_VALUE)), + &contacts_list, G_TYPE_INVALID)) + { + _handle_dbus_exception(error, FALSE); + error = NULL; + continue; + } + g_slist_foreach (contacts_list, _foreach_contact, account); + g_slist_free(contacts_list); + } + g_strfreev (accounts); + return TRUE; +} + +static gboolean +init (NstPlugin *plugin) +{ + g_print ("Init gajim plugin\n"); + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + + /* connect to gajim dbus service */ + jid_table = g_hash_table_new (g_str_hash, g_str_equal); + if (!init_dbus()) { + return FALSE; + } + return TRUE; +} + + +static void +_set_pixbuf_from_status (const gchar *show, GdkPixbuf **pixbuf) +{ + GString *pixbuf_path; + GError *error; + + pixbuf_path = g_string_new(GAJIM_SHARE_DIR); + g_string_append_c(pixbuf_path, '/'); + g_string_append(pixbuf_path, "data"); + g_string_append_c(pixbuf_path, '/'); + g_string_append(pixbuf_path, "iconsets"); + g_string_append_c(pixbuf_path, '/'); + g_string_append(pixbuf_path, iconset); + g_string_append_c(pixbuf_path, '/'); + g_string_append(pixbuf_path, "16x16"); + g_string_append_c(pixbuf_path, '/'); + g_string_append(pixbuf_path, show); + g_string_append(pixbuf_path, ".png"); + if(g_file_test(pixbuf_path->str, G_FILE_TEST_EXISTS) && + g_file_test(pixbuf_path->str, G_FILE_TEST_IS_REGULAR)) { + error = NULL; + *pixbuf = gdk_pixbuf_new_from_file(pixbuf_path->str, &error); + if(error != NULL) { + g_error_free(error); + } + } + g_string_free(pixbuf_path, FALSE); +} + +static void +_add_contact_to_model(gpointer key, gpointer value, gpointer user_data) +{ + GtkTreeIter *iter; + GtkListStore *store; + GdkPixbuf *pixbuf; + GValue *val; + GHashTable *contact_props; + const gchar *show; + + contact_props = (GHashTable *) value; + pixbuf = NULL; + val = g_hash_table_lookup(contact_props, "show"); + if (value == NULL || !G_VALUE_HOLDS_STRING(val)) { + g_warning("String expected (contact - show)"); + pixbuf = NULL; + } else { + show = g_value_get_string ((GValue *)val); + _set_pixbuf_from_status(show, &pixbuf); + } + + store = (GtkListStore *) user_data; + iter = g_malloc (sizeof(GtkTreeIter)); + gtk_list_store_append (store, iter); + gtk_list_store_set (store, iter, 0, pixbuf, 1, key, -1); + g_free (iter); +} + +/* + * put gajim contacts to jid_list + * filtering only these which are connected + */ +static gboolean +add_gajim_contacts_to_model (GtkListStore *store) +{ + if(!_get_contacts()) { + return FALSE; + } + if(g_hash_table_size(jid_table) == 0) { + return FALSE; + } + g_hash_table_foreach(jid_table, _add_contact_to_model, store); + return TRUE; +} + +/* + * fill completion model for the entry, using list of + * available gajim contacts + */ +static GtkWidget * +get_contacts_widget (NstPlugin *plugin) +{ + GtkWidget *entry; + GtkEntryCompletion *completion; + GtkListStore *store; + GtkCellRenderer *renderer; + GtkTreeModel *completion_model; + + entry = gtk_entry_new (); + completion = gtk_entry_completion_new (); + + renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), + renderer, + FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion), renderer, + "pixbuf", 0, NULL); + + + store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_STRING); + if(!add_gajim_contacts_to_model (store)) { + gtk_widget_set_sensitive(entry, FALSE); + } + completion_model = GTK_TREE_MODEL (store); + gtk_entry_completion_set_model (completion, completion_model); + gtk_entry_set_completion (GTK_ENTRY (entry), completion); + gtk_entry_completion_set_text_column (completion, 1); + g_object_unref (completion_model); + g_object_unref (completion); + return entry; +} + +static void +show_error (const gchar *title, const gchar *message) +{ + GtkWidget *dialog; + + dialog = gtk_message_dialog_new_with_markup(NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, NULL); + gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), + g_markup_printf_escaped("%s\n\n%s", title, message)); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + +} + +static gboolean +send_files (NstPlugin *plugin, + GtkWidget *contact_widget, + GList *file_list) +{ + GError *error; + GValue *value; + GList *file_iter; + GHashTable *contact_props; + + gchar *send_to; + gchar *jid; + gchar *account; + gchar *file_path; + + if(proxy == NULL) { + show_error(_("Unable to send file"), + _("There is no connection to gajim remote service.")); + return FALSE; + } + send_to = (gchar *) gtk_entry_get_text (GTK_ENTRY(contact_widget)); + g_debug("[Gajim] sending to: %s", send_to); + if (strlen (send_to) != 0){ + contact_props = g_hash_table_lookup (jid_table, send_to); + if(contact_props == NULL) { + jid = send_to; + account = NULL; + } + else { + value = g_hash_table_lookup(contact_props, "jid"); + if(value == NULL || !G_VALUE_HOLDS_STRING(value)) { + g_warning("[Gajim] string expected (contact - jid)"); + return FALSE; + } + + jid = g_value_dup_string((GValue *)value); + account = g_hash_table_lookup(contact_props, "account"); + } + } + else { + g_warning("[Gajim] missing recipient"); + show_error(_("Sending file failed"), + _("Recipient is missing.")); + return FALSE; + } + + error= NULL; + for(file_iter = file_list; file_iter != NULL; file_iter = file_iter->next) { + char *uri = file_iter->data; + + g_debug("[Gajim] file: %s", uri); + error= NULL; + file_path = g_filename_from_uri(uri, NULL, &error); + if(error != NULL) { + g_warning("%d Unable to convert URI `%s' to absolute file path", + error->code, uri); + g_error_free(error); + continue; + } + + g_debug("[Gajim] file: %s", file_path); + if(account) { + dbus_g_proxy_call (proxy, "send_file", &error, + G_TYPE_STRING, file_path, + G_TYPE_STRING, jid, + G_TYPE_STRING, account, + G_TYPE_INVALID, + G_TYPE_INVALID); + } else { + dbus_g_proxy_call (proxy, "send_file", &error, + G_TYPE_STRING, file_path, + G_TYPE_STRING, jid, + G_TYPE_INVALID, + G_TYPE_INVALID); + } + g_free(file_path); + if(error != NULL) + { + if(error->domain != DBUS_GERROR || error->code != DBUS_GERROR_INVALID_ARGS) { + g_warning("[Gajim] sending file %s to %s failed:", uri, send_to); + g_error_free(error); + show_error(_("Sending file failed"), _("Unknown recipient.")); + return FALSE; + } + g_error_free(error); + } + } + return TRUE; +} + +static gboolean +destroy (NstPlugin *plugin) +{ + if (proxy != NULL) { + g_object_unref(proxy); + } + g_hash_table_destroy(jid_table); + return TRUE; +} + +static +NstPluginInfo plugin_info = { + "im-jabber", + "gajim", + N_("Instant Message (Gajim)"), + NULL, + CAJA_CAPS_NONE, + init, + get_contacts_widget, + NULL, + send_files, + destroy +}; + +NST_INIT_PLUGIN (plugin_info) + diff --git a/sendto/plugins/nst-common.c b/sendto/plugins/nst-common.c new file mode 100644 index 0000000..2d2f102 --- /dev/null +++ b/sendto/plugins/nst-common.c @@ -0,0 +1,98 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 + * General Public License for more av. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Author: Maxim Ermilov + */ + +#include + +static gboolean +copy_fobject (GFile* source, GFile* dst) +{ + GFileEnumerator* en; + GFileInfo* info; + GError *err = NULL; + char *file_name; + GFile *dest; + + file_name = g_file_get_basename (source); + dest = g_file_get_child (dst, file_name); + g_free (file_name); + + if (g_file_query_file_type (source, G_FILE_QUERY_INFO_NONE, NULL) != G_FILE_TYPE_DIRECTORY) { + gboolean ret; + ret = g_file_copy (source, dest, G_FILE_COPY_NONE, NULL, NULL, NULL, NULL); + + g_object_unref (dest); + + return ret; + } + + en = g_file_enumerate_children (source, "*", G_FILE_QUERY_INFO_NONE, NULL, NULL); + if (!g_file_make_directory (dest, NULL, NULL)) { + g_object_unref (en); + g_object_unref (dest); + return FALSE; + } + + while ((info = g_file_enumerator_next_file (en, NULL, &err)) != NULL) { + const char *name; + + name = g_file_info_get_name (G_FILE_INFO (info)); + + if (name != NULL) { + GFile *child; + + child = g_file_get_child (source, name); + + if (!copy_fobject (child, dest)) { + g_object_unref (en); + g_object_unref (dest); + g_object_unref (child); + + return FALSE; + } + g_object_unref (child); + } + + g_object_unref (info); + } + g_object_unref (en); + g_object_unref (dest); + + if (err != NULL) + return FALSE; + return TRUE; +} + +gboolean +copy_files_to (GList *file_list, GFile *dest) +{ + GList *l; + gboolean retval = TRUE; + + for (l = file_list; l != NULL; l = l->next) { + GFile *source; + + source = g_file_new_for_commandline_arg (l->data); + if (copy_fobject (source, dest) == FALSE) + retval = FALSE; + g_object_unref (source); + } + + return retval; +} diff --git a/sendto/plugins/nst-common.h b/sendto/plugins/nst-common.h new file mode 100644 index 0000000..5a5e1dd --- /dev/null +++ b/sendto/plugins/nst-common.h @@ -0,0 +1,23 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 + * General Public License for more av. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Author: Maxim Ermilov + */ + +#include + +gboolean copy_files_to (GList *file_list, GFile *dest); diff --git a/sendto/plugins/pidgin/Makefile.am b/sendto/plugins/pidgin/Makefile.am new file mode 100644 index 0000000..b7f650a --- /dev/null +++ b/sendto/plugins/pidgin/Makefile.am @@ -0,0 +1,18 @@ +plugindir = $(libdir)/caja-sendto/plugins + +AM_CPPFLAGS = \ + -DDATADIR=\"$(datadir)\" \ + -DICONDIR=\"$(icondir)\" \ + -DLOCALEDIR="\"$(datadir)/locale\"" \ + -I$(top_srcdir)/sendto \ + -I$(top_builddir) \ + $(SENDTO_CFLAGS) \ + $(DISABLE_DEPRECATED) \ + $(WARN_CFLAGS) + +plugin_LTLIBRARIES = libnstpidgin.la + +libnstpidgin_la_SOURCES = pidgin.c +libnstpidgin_la_LDFLAGS = -module -avoid-version +libnstpidgin_la_LIBADD = $(SENDTO_LIBS) + diff --git a/sendto/plugins/pidgin/pidgin.c b/sendto/plugins/pidgin/pidgin.c new file mode 100644 index 0000000..941d2b6 --- /dev/null +++ b/sendto/plugins/pidgin/pidgin.c @@ -0,0 +1,475 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * pidgin.c + * pidgin plugin for caja-sendto + * + * Copyright (C) 2004 Roberto Majadas + * Copyright (C) 2009 Pascal Terjan + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 + * General Public License for more av. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Author: Roberto Majadas + */ + +#include "config.h" +#include +#include +#include +#include "caja-sendto-plugin.h" + +#define OBJ_PATH "/im/pidgin/purple/PurpleObject" +#define INTERFACE "im.pidgin.purple.PurpleInterface" +#define SERVICE "im.pidgin.purple.PurpleService" + +static DBusGProxy *proxy = NULL; +static GHashTable *contact_hash = NULL; + +typedef struct _ContactData { + int account; + int id; + char *name; + char *alias; +} ContactData; + +enum { + COL_ICON, + COL_ALIAS, + NUM_COLS +}; + +/* + * Print appropriate warnings when dbus raised error + * on queries + */ +static void +handle_dbus_exception(GError *error) +{ + if (error == NULL) { + g_warning("[Pidgin] unable to parse result"); + return; + } + else if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) { + g_warning ("[Pidgin] caught remote method exception %s: %s", + dbus_g_error_get_name (error), + error->message); + } + g_error_free (error); +} + +static gboolean +init (NstPlugin *plugin) +{ + DBusGConnection *connection; + GError *error; + GArray *accounts; + + g_print ("Init pidgin plugin\n"); + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + + error = NULL; + connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + if(error != NULL) { + g_warning("[Pidgin] unable to get session bus, error was:\n %s", error->message); + g_error_free(error); + return FALSE; + } + + proxy = dbus_g_proxy_new_for_name(connection, + SERVICE, + OBJ_PATH, + INTERFACE); + dbus_g_connection_unref(connection); + if (proxy == NULL) + return FALSE; + + error = NULL; + if (!dbus_g_proxy_call (proxy, "PurpleAccountsGetAllActive", &error, G_TYPE_INVALID, + DBUS_TYPE_G_INT_ARRAY, &accounts, G_TYPE_INVALID)) { + g_object_unref(proxy); + g_error_free(error); + return FALSE; + } + g_array_free(accounts, TRUE); + + return TRUE; +} + +static GdkPixbuf * +get_buddy_icon(int id) +{ + GError *error; + GdkPixbuf *pixbuf = NULL; + gchar *path = NULL; + int icon; + + error=NULL; + if (!dbus_g_proxy_call (proxy, "PurpleBuddyGetIcon", &error, + G_TYPE_INT, id, + G_TYPE_INVALID, + G_TYPE_INT, &icon, G_TYPE_INVALID)) { + handle_dbus_exception(error); + } + if (icon) { + if (!dbus_g_proxy_call (proxy, "PurpleBuddyIconGetFullPath", &error, + G_TYPE_INT, icon, + G_TYPE_INVALID, + G_TYPE_STRING, &path, G_TYPE_INVALID)) { + handle_dbus_exception(error); + } + //FIXME Get the size from somewhere + pixbuf = gdk_pixbuf_new_from_file_at_scale(path, 24, 24, TRUE, NULL); + } + + return pixbuf; +} + +static void +add_pidgin_contacts_to_model (GtkTreeStore *store, + GtkTreeIter *iter, + GtkTreeIter *parent) +{ + GError *error; + GArray *contacts_list; + GArray *accounts; + int i, j; + + GdkPixbuf *icon; + GHashTableIter hiter; + GPtrArray *contacts_group; + ContactData *dat; + GValue val = {0,}; + + if(proxy == NULL) + return; + + error = NULL; + if (!dbus_g_proxy_call (proxy, "PurpleAccountsGetAllActive", &error, G_TYPE_INVALID, + DBUS_TYPE_G_INT_ARRAY, + &accounts, G_TYPE_INVALID)) { + handle_dbus_exception(error); + return; + } + + contact_hash = g_hash_table_new (g_str_hash, g_str_equal); + + for(i = 0; i < accounts->len; i++) { + int account = g_array_index(accounts, int, i); + error = NULL; + if (!dbus_g_proxy_call (proxy, "PurpleFindBuddies", &error, + G_TYPE_INT, account, + G_TYPE_STRING, NULL, + G_TYPE_INVALID, + DBUS_TYPE_G_INT_ARRAY, &contacts_list, G_TYPE_INVALID)) { + handle_dbus_exception(error); + continue; + } + for(j = 0; j < contacts_list->len ; j++) { + int id = g_array_index(contacts_list, int, j); + int online; + + error = NULL; + if (!dbus_g_proxy_call (proxy, "PurpleBuddyIsOnline", &error, + G_TYPE_INT, id, + G_TYPE_INVALID, + G_TYPE_INT, &online, G_TYPE_INVALID)) { + handle_dbus_exception(error); + continue; + } + if (!online) + continue; + + dat = g_new0 (ContactData, 1); + + dat->account = account; + dat->id = id; + + error = NULL; + if (!dbus_g_proxy_call (proxy, "PurpleBuddyGetName", &error, + G_TYPE_INT, id, + G_TYPE_INVALID, + G_TYPE_STRING, &dat->name, G_TYPE_INVALID)) { + handle_dbus_exception(error); + g_free(dat); + continue; + } + if (!dbus_g_proxy_call (proxy, "PurpleBuddyGetAlias", &error, + G_TYPE_INT, id, + G_TYPE_INVALID, + G_TYPE_STRING, &dat->alias, G_TYPE_INVALID)) { + handle_dbus_exception(error); + } + + contacts_group = g_hash_table_lookup (contact_hash, dat->alias); + if (contacts_group == NULL){ + GPtrArray *new_group = g_ptr_array_new (); + g_ptr_array_add (new_group, dat); + g_hash_table_insert (contact_hash, dat->alias, new_group); + } else { + g_ptr_array_add (contacts_group, dat); + } + } + g_array_free(contacts_list, TRUE); + } + g_array_free (accounts, TRUE); + + g_hash_table_iter_init (&hiter, contact_hash); + while (g_hash_table_iter_next (&hiter, NULL, (gpointer)&contacts_group)) { + gint accounts; + + dat = g_ptr_array_index (contacts_group, 0); + + accounts = contacts_group->len; + + gtk_tree_store_append (store, parent, NULL); + gtk_tree_store_set (store, parent, COL_ICON, NULL, COL_ALIAS, dat->alias, -1); + + gint i; + for (i = 0; i < accounts; ++i) { + dat = g_ptr_array_index (contacts_group, i); + + icon = get_buddy_icon(dat->id); + + if (accounts == 1) { + g_value_init(&val, GDK_TYPE_PIXBUF); + g_value_set_object (&val, (gpointer)icon); + gtk_tree_store_set_value (store, parent, COL_ICON, &val); + g_value_unset (&val); + break; + } + gtk_tree_store_append (store, iter, parent); + gtk_tree_store_set (store, iter, + COL_ICON, icon, + COL_ALIAS, dat->alias, + -1); + } + } +} + +static void +customize (GtkCellLayout *cell_layout, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, + GtkTreeIter *iter, + gpointer text) +{ + gboolean has_child; + has_child = gtk_tree_model_iter_has_child (tree_model, iter); + if (text) { + if (has_child) + g_object_set (G_OBJECT(cell), "xpad", 18, NULL); + else + g_object_set (G_OBJECT(cell), "xpad", 2, NULL); + } + g_object_set (G_OBJECT(cell), "sensitive", !has_child, NULL); +} + +static GtkWidget * +get_contacts_widget (NstPlugin *plugin) +{ + GtkWidget *cb; + GtkCellRenderer *renderer; + GtkTreeStore *store; + GtkTreeModel *model; + GtkTreeIter *iter, *iter2; + + iter = g_malloc (sizeof(GtkTreeIter)); + iter2 = g_malloc (sizeof(GtkTreeIter)); + store = gtk_tree_store_new (NUM_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING); + add_pidgin_contacts_to_model (store, iter, iter2); + model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store)); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), COL_ALIAS, + GTK_SORT_ASCENDING); + cb = gtk_combo_box_new_with_model (model); + + renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb), + renderer, + FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cb), + renderer, + "pixbuf", COL_ICON, + NULL); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (cb), renderer, + customize, + (gboolean *)FALSE, NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb), + renderer, + TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cb), + renderer, + "text", COL_ALIAS, + NULL); + g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (cb), renderer, + customize, + (gboolean *)TRUE, NULL); + + gtk_combo_box_set_active (GTK_COMBO_BOX (cb), 0); + gtk_combo_box_get_active_iter (GTK_COMBO_BOX(cb), iter); + if (gtk_tree_model_iter_has_child (model, iter)) { + GtkTreePath *path = gtk_tree_path_new_from_indices (0, 0, -1); + gtk_tree_model_get_iter (model, iter2, path); + gtk_tree_path_free (path); + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (cb), iter2); + } + + g_free (iter); + g_free (iter2); + return cb; +} + +static +gboolean send_file(int account, const char *who, const char *filename) +{ + GError *error; + int connection; + + error = NULL; + if (!dbus_g_proxy_call(proxy, "PurpleAccountGetConnection", &error, + G_TYPE_INT, account, + G_TYPE_INVALID, + G_TYPE_INT, &connection, G_TYPE_INVALID)) { + handle_dbus_exception(error); + return FALSE; + } + + if (!connection) { + g_warning("[Pidgin] account is not connected"); + return FALSE; + } + + error = NULL; + if (!dbus_g_proxy_call(proxy, "ServSendFile", &error, + G_TYPE_INT, connection, + G_TYPE_STRING, who, + G_TYPE_STRING, filename, + G_TYPE_INVALID, G_TYPE_INVALID)) { + handle_dbus_exception(error); + return FALSE; + } + return TRUE; +} + +static +gboolean send_files (NstPlugin *plugin, GtkWidget *contact_widget, + GList *file_list) +{ + GError *error; + GList *file_iter; + + GFile *file; + gchar *file_path; + + gint depth; + GtkTreeIter iter; + GtkTreePath *path; + gint *indices; + const gchar *alias; + GPtrArray *contacts_group; + ContactData *dat; + GValue val = {0,}; + + + if(proxy == NULL) + return FALSE; + + gtk_combo_box_get_active_iter (GTK_COMBO_BOX (contact_widget), &iter); + path = gtk_tree_model_get_path (GTK_TREE_MODEL ( + gtk_combo_box_get_model (GTK_COMBO_BOX( + contact_widget))), &iter); + depth = gtk_tree_path_get_depth(path); + indices = gtk_tree_path_get_indices(path); + gtk_tree_path_free (path); + gtk_tree_model_get_value (GTK_TREE_MODEL (gtk_combo_box_get_model ( + GTK_COMBO_BOX(contact_widget))), + &iter, COL_ALIAS, &val); + alias = g_value_get_string (&val); + contacts_group = g_hash_table_lookup (contact_hash, alias); + g_value_unset (&val); + dat = g_ptr_array_index (contacts_group, (depth == 2)?indices[1]:0); + + for(file_iter = file_list; file_iter != NULL; + file_iter = g_list_next(file_iter)) { + error= NULL; + + file = g_file_new_for_uri ((gchar *)file_iter->data); + file_path = g_file_get_path (file); + g_object_unref (file); + + if(file_path == NULL) { + g_warning("[Pidgin] %d Unable to convert URI `%s' to absolute file path", + error->code, (gchar *)file_iter->data); + g_error_free(error); + continue; + } + + if(!send_file(dat->account, dat->name, file_path)) + g_warning("[Pidgin] Failed to send %s file to %s", file_path, dat->name); + } + return TRUE; +} + +static void +free_contact (ContactData *dat) +{ + g_free(dat->name); + g_free(dat->alias); + g_free(dat); +} + +static gboolean +destroy (NstPlugin *plugin) +{ + GHashTableIter iter; + GPtrArray *contacts_group; + ContactData *dat; + + g_hash_table_iter_init (&iter, contact_hash); + while (g_hash_table_iter_next (&iter, NULL, (gpointer)&contacts_group)) { + gint accounts; + accounts = contacts_group->len; + + gint i; + for (i = 0; i < accounts; ++i) { + dat = g_ptr_array_index (contacts_group, i); + free_contact (dat); + } + g_ptr_array_free (contacts_group, TRUE); + } + g_hash_table_destroy (contact_hash); + return TRUE; +} + +static +NstPluginInfo plugin_info = { + "im", + "pidgin", + N_("Instant Message (Pidgin)"), + NULL, + CAJA_CAPS_NONE, + init, + get_contacts_widget, + NULL, + send_files, + destroy +}; + +NST_INIT_PLUGIN (plugin_info) + diff --git a/sendto/plugins/removable-devices/Makefile.am b/sendto/plugins/removable-devices/Makefile.am new file mode 100644 index 0000000..294ca90 --- /dev/null +++ b/sendto/plugins/removable-devices/Makefile.am @@ -0,0 +1,19 @@ +plugindir = $(libdir)/caja-sendto/plugins + +AM_CPPFLAGS = \ + -DDATADIR=\"$(datadir)\" \ + -DICONDIR=\"$(icondir)\" \ + -DLOCALEDIR="\"$(datadir)/locale\"" \ + -I$(top_srcdir)/sendto \ + -I$(top_builddir) \ + -I$(srcdir)/../ \ + $(SENDTO_CFLAGS) \ + $(DISABLE_DEPRECATED) \ + $(WARN_CFLAGS) + +plugin_LTLIBRARIES = libnstremovable_devices.la + +libnstremovable_devices_la_SOURCES = removable-devices.c +libnstremovable_devices_la_LDFLAGS = -module -avoid-version +libnstremovable_devices_la_LIBADD = $(SENDTO_LIBS) $(builddir)/../libnstcommon.la + diff --git a/sendto/plugins/removable-devices/removable-devices.c b/sendto/plugins/removable-devices/removable-devices.c new file mode 100644 index 0000000..0ecea14 --- /dev/null +++ b/sendto/plugins/removable-devices/removable-devices.c @@ -0,0 +1,259 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 + * General Public License for more av. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Authors: Maxim Ermilov + * Bastien Nocera + */ + +#include "config.h" +#include +#include +#include +#include "nst-common.h" +#include "caja-sendto-plugin.h" + +enum { + NAME_COL, + ICON_COL, + MOUNT_COL, + NUM_COLS, +}; + +GVolumeMonitor* vol_monitor = NULL; +GtkWidget *cb; + +static void +cb_mount_removed (GVolumeMonitor *volume_monitor, + GMount *mount, + NstPlugin *plugin) +{ + GtkTreeIter iter; + GtkListStore *store; + gboolean b, found; + + store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (cb))); + b = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); + found = FALSE; + + while (b) { + GMount *m; + gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, MOUNT_COL, &m, -1); + if (m == mount) { + gtk_list_store_remove (store, &iter); + g_object_unref (m); + found = TRUE; + break; + } + g_object_unref (m); + b = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); + } + + /* If a mount was removed */ + if (found != FALSE) { + /* And it was the selected one */ + if (gtk_combo_box_get_active (GTK_COMBO_BOX (cb)) == -1) { + /* Select the first item in the list */ + gtk_combo_box_set_active (GTK_COMBO_BOX (cb), 0); + } + } +} + +static void +cb_mount_changed (GVolumeMonitor *volume_monitor, + GMount *mount, + NstPlugin *plugin) +{ + GtkTreeIter iter; + gboolean b; + GtkListStore *store; + + if (g_mount_is_shadowed (mount) != FALSE) { + cb_mount_removed (volume_monitor, mount, plugin); + return; + } + + store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (cb))); + b = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); + + while (b) { + GMount *m; + gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, MOUNT_COL, &m, -1); + + if (m == mount) { + char *name; + + name = g_mount_get_name (mount); + gtk_list_store_set (store, &iter, + NAME_COL, name, + ICON_COL, g_mount_get_icon (mount), + -1); + g_free (name); + g_object_unref (m); + break; + } + g_object_unref (m); + b = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); + } +} + +static void +cb_mount_added (GVolumeMonitor *volume_monitor, + GMount *mount, + NstPlugin *plugin) +{ + char *name; + GtkTreeIter iter; + GtkTreeModel *model; + gboolean select_added; + + if (g_mount_is_shadowed (mount) != FALSE) + return; + + name = g_mount_get_name (mount); + model = gtk_combo_box_get_model (GTK_COMBO_BOX (cb)); + + select_added = gtk_tree_model_iter_n_children (model, NULL) == 0; + + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + NAME_COL, name, + ICON_COL, g_mount_get_icon (mount), + MOUNT_COL, mount, + -1); + + g_free (name); + + if (select_added != FALSE) + gtk_combo_box_set_active (GTK_COMBO_BOX (cb), 0); + +} + +static gboolean +init (NstPlugin *plugin) +{ + g_print ("Init removable-devices plugin\n"); + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + + vol_monitor = g_volume_monitor_get (); + cb = gtk_combo_box_new (); + + return TRUE; +} + +static GtkWidget* +get_contacts_widget (NstPlugin *plugin) +{ + GtkListStore *store; + GList *l, *mounts; + GtkTreeIter iter; + GtkCellRenderer *text_renderer, *icon_renderer; + + mounts = g_volume_monitor_get_mounts (vol_monitor); + + store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_ICON, G_TYPE_OBJECT); + + for (l = mounts; l != NULL; l = l->next) { + char *name; + + if (g_mount_is_shadowed (l->data) != FALSE) { + g_object_unref (l->data); + continue; + } + + name = g_mount_get_name (l->data); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + NAME_COL, name, + ICON_COL, g_mount_get_icon (l->data), + MOUNT_COL, l->data, + -1); + g_free (name); + + g_object_unref (l->data); + } + g_list_free (mounts); + + gtk_cell_layout_clear (GTK_CELL_LAYOUT (cb)); + gtk_combo_box_set_model (GTK_COMBO_BOX (cb), GTK_TREE_MODEL (store)); + + text_renderer = gtk_cell_renderer_text_new (); + icon_renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb), icon_renderer, FALSE); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb), text_renderer, TRUE); + + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cb), text_renderer, "text", 0, NULL); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cb), icon_renderer, "gicon", 1, NULL); + gtk_combo_box_set_active (GTK_COMBO_BOX (cb), 0); + + g_signal_connect (G_OBJECT (vol_monitor), "mount-removed", G_CALLBACK (cb_mount_removed), plugin); + g_signal_connect (G_OBJECT (vol_monitor), "mount-added", G_CALLBACK (cb_mount_added), plugin); + g_signal_connect (G_OBJECT (vol_monitor), "mount-changed", G_CALLBACK (cb_mount_changed), plugin); + + return cb; +} + +static gboolean +send_files (NstPlugin *plugin, GtkWidget *contact_widget, + GList *file_list) +{ + GtkListStore *store; + GtkTreeIter iter; + GMount *dest_mount; + GFile *mount_root; + + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (contact_widget), &iter) == FALSE) + return TRUE; + + store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (cb))); + gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, MOUNT_COL, &dest_mount, -1); + mount_root = g_mount_get_root (dest_mount); + + copy_files_to (file_list, mount_root); + + g_object_unref (mount_root); + + return TRUE; +} + +static gboolean +destroy (NstPlugin *plugin) +{ + gtk_widget_destroy (cb); + + g_object_unref (vol_monitor); + return TRUE; +} + +static +NstPluginInfo plugin_info = { + "folder-remote", + "folder-remote", + N_("Removable disks and shares"), + NULL, + CAJA_CAPS_SEND_DIRECTORIES, + init, + get_contacts_widget, + NULL, + send_files, + destroy +}; + +NST_INIT_PLUGIN (plugin_info) + diff --git a/sendto/plugins/upnp/Makefile.am b/sendto/plugins/upnp/Makefile.am new file mode 100644 index 0000000..4127abd --- /dev/null +++ b/sendto/plugins/upnp/Makefile.am @@ -0,0 +1,18 @@ +plugindir = $(libdir)/caja-sendto/plugins + +AM_CPPFLAGS = \ + -DDATADIR=\"$(datadir)\" \ + -DICONDIR=\"$(icondir)\" \ + -DLOCALEDIR="\"$(datadir)/locale\"" \ + -I$(top_srcdir)/sendto \ + -I$(top_builddir) \ + $(SENDTO_CFLAGS) \ + $(DISABLE_DEPRECATED) \ + $(WARN_CFLAGS) + +plugin_LTLIBRARIES = libnstupnp.la + +libnstupnp_la_SOURCES = upnp.c +libnstupnp_la_LDFLAGS = -module -avoid-version +libnstupnp_la_LIBADD = $(SENDTO_LIBS) + diff --git a/sendto/plugins/upnp/upnp.c b/sendto/plugins/upnp/upnp.c new file mode 100644 index 0000000..b381587 --- /dev/null +++ b/sendto/plugins/upnp/upnp.c @@ -0,0 +1,320 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2008 Zeeshan Ali (Khattak) + * Copyright (C) 2006 Peter Enseleit + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 + * General Public License for more av. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Author: Zeeshan Ali (Khattak) + * Peter Enseleit + * Roberto Majadas + * + */ + +#include "config.h" + +#include +#include +#include "caja-sendto-plugin.h" + +#define MEDIA_SERVER "urn:schemas-upnp-org:device:MediaServer:1" +#define CDS "urn:schemas-upnp-org:service:ContentDirectory" + +enum { + UDN_COL, + NAME_COL, + INTERFACE_COL, + NUM_COLS +}; + +static GtkWidget *combobox; +static GtkTreeModel *model; +static GUPnPContextManager *context_manager; + +static gboolean +find_device (const gchar *udn, + GtkTreeIter *iter) +{ + gboolean found = FALSE; + + if (!gtk_tree_model_get_iter_first (model, iter)) + return FALSE; + + do { + gchar *tmp; + + gtk_tree_model_get (model, + iter, + UDN_COL, &tmp, + -1); + + if (tmp != NULL && strcmp (tmp, udn) == 0) + found = TRUE; + + g_free (tmp); + } while (!found && gtk_tree_model_iter_next (model, iter)); + + return found; +} + +static gboolean +check_required_actions (GUPnPServiceIntrospection *introspection) +{ + if (gupnp_service_introspection_get_action (introspection, + "CreateObject") == NULL) + return FALSE; + if (gupnp_service_introspection_get_action (introspection, + "ImportResource") == NULL) + return FALSE; + return TRUE; +} + +static void +get_introspection_cb (GUPnPServiceInfo *service_info, + GUPnPServiceIntrospection *introspection, const GError *error, + gpointer user_data) +{ + GUPnPDeviceInfo *device_info; + gchar *name; + const gchar *udn, *interface; + GtkTreeIter iter; + GUPnPContext *context; + + device_info = GUPNP_DEVICE_INFO (user_data); + + if (introspection != NULL) { + /* If introspection is available, make sure required actions + * are implemented. + */ + if (!check_required_actions (introspection)) + goto error; + } + + udn = gupnp_device_info_get_udn (device_info); + if (G_UNLIKELY (udn == NULL)) + goto error; + + /* First check if the device is already added */ + if (find_device (udn, &iter)) + goto error; + + name = gupnp_device_info_get_friendly_name (device_info); + if (name == NULL) + name = g_strdup (udn); + + context = gupnp_device_info_get_context (device_info); + interface = gssdp_client_get_interface (GSSDP_CLIENT (context)); + + gtk_list_store_insert_with_values (GTK_LIST_STORE (model), NULL, -1, + UDN_COL, udn, + NAME_COL, name, + INTERFACE_COL, interface, + -1); + + g_free (name); + +error: + /* We don't need the proxy objects anymore */ + g_object_unref (service_info); + g_object_ref (device_info); +} + +static void +device_proxy_available_cb (GUPnPControlPoint *cp, + GUPnPDeviceProxy *proxy) +{ + GUPnPServiceInfo *info; + + info = gupnp_device_info_get_service (GUPNP_DEVICE_INFO (proxy), CDS); + if (G_UNLIKELY (info == NULL)) { + /* No ContentDirectory implemented? Not interesting. */ + return; + } + + gupnp_service_info_get_introspection_async (info, + get_introspection_cb, + g_object_ref (proxy)); +} + +static void +device_proxy_unavailable_cb (GUPnPControlPoint *cp, + GUPnPDeviceProxy *proxy) +{ + GtkTreeIter iter; + const gchar *udn; + + udn = gupnp_device_info_get_udn (GUPNP_DEVICE_INFO (proxy)); + if (udn == NULL) + return; + + /* First check if the device is already added */ + if (find_device (udn, &iter)) + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); +} + +static void +on_context_available (GUPnPContextManager *context_manager, + GUPnPContext *context, + gpointer user_data) +{ + GUPnPControlPoint *cp; + + cp = gupnp_control_point_new (context, MEDIA_SERVER); + + g_signal_connect (cp, + "device-proxy-available", + G_CALLBACK (device_proxy_available_cb), + NULL); + g_signal_connect (cp, + "device-proxy-unavailable", + G_CALLBACK (device_proxy_unavailable_cb), + NULL); + + gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (cp), TRUE); + + /* Let context manager take care of the control point life cycle */ + gupnp_context_manager_manage_control_point (context_manager, cp); + g_object_unref (cp); +} + +static gboolean +init (NstPlugin *plugin) +{ + GtkListStore *store; + GtkCellRenderer *renderer; + char *upload_cmd; + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + + upload_cmd = g_find_program_in_path ("gupnp-upload"); + if (upload_cmd == NULL) + return FALSE; + g_free (upload_cmd); + + context_manager = gupnp_context_manager_new (NULL, 0); + g_assert (context_manager != NULL); + g_signal_connect (context_manager, "context-available", + G_CALLBACK (on_context_available), NULL); + + combobox = gtk_combo_box_new (); + + store = gtk_list_store_new (NUM_COLS, + G_TYPE_STRING, /* UDN */ + G_TYPE_STRING, /* Name */ + G_TYPE_STRING); /* Network Interface */ + model = GTK_TREE_MODEL (store); + gtk_combo_box_set_model (GTK_COMBO_BOX (combobox), model); + + renderer = gtk_cell_renderer_text_new (); + + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), + renderer, + TRUE); + gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox), + renderer, + "text", NAME_COL); + + return TRUE; +} + +static GtkWidget* +get_contacts_widget (NstPlugin *plugin) +{ + return combobox; +} + +static gboolean +send_files (NstPlugin *plugin, + GtkWidget *contact_widget, + GList *file_list) +{ + gchar *upload_cmd, *udn, *interface; + GPtrArray *argv; + gboolean ret; + GList *l; + GtkTreeIter iter; + GError *err = NULL; + + if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combobox), &iter)) + return FALSE; + + gtk_tree_model_get (model, &iter, UDN_COL, &udn, INTERFACE_COL, + &interface, -1); + + upload_cmd = g_find_program_in_path ("gupnp-upload"); + if (upload_cmd == NULL) + return FALSE; + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, upload_cmd); + g_ptr_array_add (argv, "-t"); + g_ptr_array_add (argv, "15"); /* discovery timeout (seconds) */ + g_ptr_array_add (argv, "-e"); + g_ptr_array_add (argv, interface); + g_ptr_array_add (argv, udn); + for (l = file_list ; l; l=l->next) { + gchar *file_path; + + file_path = g_filename_from_uri (l->data, NULL, NULL); + g_ptr_array_add (argv, file_path); + } + g_ptr_array_add (argv, NULL); + + ret = g_spawn_async (NULL, (gchar **) argv->pdata, + NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &err); + + if (ret == FALSE) { + g_warning ("Could not send files to MediaServer: %s", + err->message); + g_error_free (err); + } + + g_ptr_array_free (argv, TRUE); + g_free (upload_cmd); + g_free (udn); + + return ret; +} + +static gboolean +destroy (NstPlugin *plugin) +{ + gtk_widget_destroy (combobox); + g_object_unref (model); + + g_object_unref (context_manager); + + return TRUE; +} + +static +NstPluginInfo plugin_info = { + "folder-remote", + "upnp", + N_("UPnP Media Server"), + NULL, + CAJA_CAPS_NONE, + init, + get_contacts_widget, + NULL, + send_files, + destroy +}; + +NST_INIT_PLUGIN (plugin_info) + -- cgit v1.2.1