*
* 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
* Authors: Mikael Hallendal <micke@imendio.com>
* Richard Hult <richard@imendio.com>
* Martyn Russell <martyn@imendio.com>
* Xavier Claessens <xclaesse@gmail.com>
- *
+ * Jonny Lamb <jonny.lamb@collabora.co.uk>
+ *
* Part of this file is copied from GtkSourceView (gtksourceiter.c):
* Paolo Maggi
* Jeroen Zwartepoorte
#include <string.h>
#include <X11/Xatom.h>
#include <gdk/gdkx.h>
-#include <glib/gi18n.h>
+#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
-#include <glade/glade.h>
#include <libmissioncontrol/mc-profile.h>
-#include <libempathy/empathy-debug.h>
-
#include "empathy-ui-utils.h"
#include "empathy-images.h"
+#include "empathy-conf.h"
-#define DEBUG_DOMAIN "UiUtils"
-
-struct SizeData {
- gint width;
- gint height;
- gboolean preserve_aspect_ratio;
-};
+#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
+#include <libempathy/empathy-debug.h>
+#include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-dispatcher.h>
+#include <libempathy/empathy-idle.h>
+#include <libempathy/empathy-ft-factory.h>
+
+#define SCHEMES "(https?|s?ftps?|nntp|news|javascript|about|ghelp|apt|telnet|"\
+ "file|webcal|mailto)"
+#define BODY "([^\\ \\n]+)"
+#define END_BODY "([^\\ \\n]*[^,;\?><()\\ \"\\.\\n])"
+#define URI_REGEX "("SCHEMES"://"END_BODY")" \
+ "|((mailto:)?"BODY"@"BODY"\\."END_BODY")"\
+ "|((www|ftp)\\."END_BODY")"
-static GladeXML *
-get_glade_file (const gchar *filename,
- const gchar *root,
- const gchar *domain,
- const gchar *first_required_widget,
- va_list args)
+void
+empathy_gtk_init (void)
{
- GladeXML *gui;
- gchar *path;
- const char *name;
- GtkWidget **widget_ptr;
-
- path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), "libempathy-gtk",
- filename, NULL);
- if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
- g_free (path);
- path = g_build_filename (DATADIR, "empathy", filename, NULL);
- }
- empathy_debug (DEBUG_DOMAIN, "Loading glade file %s", path);
+ static gboolean initialized = FALSE;
- gui = glade_xml_new (path, root, domain);
- g_free (path);
+ if (initialized)
+ return;
- if (!gui) {
- g_warning ("Couldn't find necessary glade file '%s'", filename);
- }
+ empathy_init ();
+ gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
+ PKGDATADIR G_DIR_SEPARATOR_S "icons");
- for (name = first_required_widget; name; name = va_arg (args, char *)) {
- widget_ptr = va_arg (args, void *);
+ initialized = TRUE;
+}
- *widget_ptr = glade_xml_get_widget (gui, name);
+GRegex *
+empathy_uri_regex_dup_singleton (void)
+{
+ static GRegex *uri_regex = NULL;
- if (!*widget_ptr) {
- g_warning ("Glade file '%s' is missing widget '%s'.",
- filename, name);
- continue;
- }
+ /* We intentionally leak the regex so it's not recomputed */
+ if (!uri_regex) {
+ uri_regex = g_regex_new (URI_REGEX, 0, 0, NULL);
}
- return gui;
+ return g_regex_ref (uri_regex);
}
-void
-empathy_glade_get_file_simple (const gchar *filename,
- const gchar *root,
- const gchar *domain,
- const gchar *first_required_widget, ...)
+static GtkBuilder *
+builder_get_file_valist (const gchar *filename,
+ const gchar *first_object,
+ va_list args)
{
- va_list args;
- GladeXML *gui;
+ GtkBuilder *gui;
+ const gchar *name;
+ GObject **object_ptr;
+ GError *error = NULL;
- va_start (args, first_required_widget);
+ DEBUG ("Loading file %s", filename);
- gui = get_glade_file (filename,
- root,
- domain,
- first_required_widget,
- args);
+ gui = gtk_builder_new ();
+ if (!gtk_builder_add_from_file (gui, filename, &error)) {
+ g_critical ("GtkBuilder Error: %s", error->message);
+ g_clear_error (&error);
+ g_object_unref (gui);
+ return NULL;
+ }
- va_end (args);
+ for (name = first_object; name; name = va_arg (args, const gchar *)) {
+ object_ptr = va_arg (args, GObject**);
- if (gui) {
- g_object_unref (gui);
+ *object_ptr = gtk_builder_get_object (gui, name);
+
+ if (!*object_ptr) {
+ g_warning ("File is missing object '%s'.", name);
+ continue;
+ }
}
+
+ return gui;
}
-GladeXML *
-empathy_glade_get_file (const gchar *filename,
- const gchar *root,
- const gchar *domain,
- const gchar *first_required_widget, ...)
+GtkBuilder *
+empathy_builder_get_file (const gchar *filename,
+ const gchar *first_object,
+ ...)
{
- va_list args;
- GladeXML *gui;
-
- va_start (args, first_required_widget);
-
- gui = get_glade_file (filename,
- root,
- domain,
- first_required_widget,
- args);
+ GtkBuilder *gui;
+ va_list args;
+ va_start (args, first_object);
+ gui = builder_get_file_valist (filename, first_object, args);
va_end (args);
- if (!gui) {
- return NULL;
- }
-
return gui;
}
void
-empathy_glade_connect (GladeXML *gui,
- gpointer user_data,
- gchar *first_widget, ...)
+empathy_builder_connect (GtkBuilder *gui,
+ gpointer user_data,
+ gchar *first_object,
+ ...)
{
va_list args;
const gchar *name;
const gchar *signal;
- GtkWidget *widget;
- gpointer *callback;
-
- va_start (args, first_widget);
+ GObject *object;
+ GCallback callback;
- for (name = first_widget; name; name = va_arg (args, char *)) {
- signal = va_arg (args, void *);
- callback = va_arg (args, void *);
+ va_start (args, first_object);
+ for (name = first_object; name; name = va_arg (args, const gchar *)) {
+ signal = va_arg (args, const gchar *);
+ callback = va_arg (args, GCallback);
- widget = glade_xml_get_widget (gui, name);
- if (!widget) {
- g_warning ("Glade file is missing widget '%s', aborting",
- name);
+ object = gtk_builder_get_object (gui, name);
+ if (!object) {
+ g_warning ("File is missing object '%s'.", name);
continue;
}
- g_signal_connect (widget,
- signal,
- G_CALLBACK (callback),
- user_data);
+ g_signal_connect (object, signal, callback, user_data);
}
va_end (args);
}
-void
-empathy_glade_setup_size_group (GladeXML *gui,
- GtkSizeGroupMode mode,
- gchar *first_widget, ...)
+GtkWidget *
+empathy_builder_unref_and_keep_widget (GtkBuilder *gui,
+ GtkWidget *widget)
{
- va_list args;
- GtkWidget *widget;
- GtkSizeGroup *size_group;
- const gchar *name;
+ /* On construction gui sinks the initial reference to widget. When gui
+ * is finalized it will drop its ref to widget. We take our own ref to
+ * prevent widget being finalised. The widget is forced to have a
+ * floating reference, like when it was initially unowned so that it can
+ * be used like any other GtkWidget. */
- va_start (args, first_widget);
+ g_object_ref (widget);
+ g_object_force_floating (G_OBJECT (widget));
+ g_object_unref (gui);
- size_group = gtk_size_group_new (mode);
-
- for (name = first_widget; name; name = va_arg (args, char *)) {
- widget = glade_xml_get_widget (gui, name);
- if (!widget) {
- g_warning ("Glade file is missing widget '%s'", name);
- continue;
- }
-
- gtk_size_group_add_widget (size_group, widget);
- }
-
- g_object_unref (size_group);
-
- va_end (args);
+ return widget;
}
const gchar *
-empathy_icon_name_from_account (McAccount *account)
+empathy_icon_name_from_account (EmpathyAccount *account)
{
McProfile *profile;
- profile = mc_account_get_profile (account);
+ profile = empathy_account_get_profile (account);
return mc_profile_get_icon_name (profile);
}
const gchar *
-empathy_icon_name_for_presence (McPresence presence)
+empathy_icon_name_for_presence (TpConnectionPresenceType presence)
{
switch (presence) {
- case MC_PRESENCE_AVAILABLE:
+ case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE:
return EMPATHY_IMAGE_AVAILABLE;
- case MC_PRESENCE_DO_NOT_DISTURB:
+ case TP_CONNECTION_PRESENCE_TYPE_BUSY:
return EMPATHY_IMAGE_BUSY;
- case MC_PRESENCE_AWAY:
+ case TP_CONNECTION_PRESENCE_TYPE_AWAY:
return EMPATHY_IMAGE_AWAY;
- case MC_PRESENCE_EXTENDED_AWAY:
+ case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY:
return EMPATHY_IMAGE_EXT_AWAY;
- case MC_PRESENCE_HIDDEN:
+ case TP_CONNECTION_PRESENCE_TYPE_HIDDEN:
return EMPATHY_IMAGE_HIDDEN;
- case MC_PRESENCE_OFFLINE:
- case MC_PRESENCE_UNSET:
+ case TP_CONNECTION_PRESENCE_TYPE_OFFLINE:
+ case TP_CONNECTION_PRESENCE_TYPE_ERROR:
+ case TP_CONNECTION_PRESENCE_TYPE_UNKNOWN:
return EMPATHY_IMAGE_OFFLINE;
- default:
- g_assert_not_reached ();
+ case TP_CONNECTION_PRESENCE_TYPE_UNSET:
+ return NULL;
}
return NULL;
const gchar *
empathy_icon_name_for_contact (EmpathyContact *contact)
{
- McPresence presence;
+ TpConnectionPresenceType presence;
g_return_val_if_fail (EMPATHY_IS_CONTACT (contact),
EMPATHY_IMAGE_OFFLINE);
GdkPixbuf *
empathy_pixbuf_from_data (gchar *data,
gsize data_size)
+{
+ return empathy_pixbuf_from_data_and_mime (data, data_size, NULL);
+}
+
+GdkPixbuf *
+empathy_pixbuf_from_data_and_mime (gchar *data,
+ gsize data_size,
+ gchar **mime_type)
{
GdkPixbufLoader *loader;
+ GdkPixbufFormat *format;
GdkPixbuf *pixbuf = NULL;
+ gchar **mime_types;
GError *error = NULL;
if (!data) {
loader = gdk_pixbuf_loader_new ();
if (!gdk_pixbuf_loader_write (loader, data, data_size, &error)) {
- empathy_debug (DEBUG_DOMAIN, "Failed to write to pixbuf loader: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- g_object_unref (loader);
- return NULL;
+ DEBUG ("Failed to write to pixbuf loader: %s",
+ error ? error->message : "No error given");
+ goto out;
}
if (!gdk_pixbuf_loader_close (loader, &error)) {
- empathy_debug (DEBUG_DOMAIN, "Failed to close pixbuf loader: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- g_object_unref (loader);
- return NULL;
+ DEBUG ("Failed to close pixbuf loader: %s",
+ error ? error->message : "No error given");
+ goto out;
}
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
if (pixbuf) {
g_object_ref (pixbuf);
+
+ if (mime_type != NULL) {
+ format = gdk_pixbuf_loader_get_format (loader);
+ mime_types = gdk_pixbuf_format_get_mime_types (format);
+
+ *mime_type = g_strdup (*mime_types);
+ if (mime_types[1] != NULL) {
+ DEBUG ("Loader supports more than one mime "
+ "type! Picking the first one, %s",
+ *mime_type);
+ }
+ g_strfreev (mime_types);
+ }
}
+out:
+ g_clear_error (&error);
g_object_unref (loader);
return pixbuf;
}
+struct SizeData {
+ gint width;
+ gint height;
+ gboolean preserve_aspect_ratio;
+};
+
static void
pixbuf_from_avatar_size_prepared_cb (GdkPixbufLoader *loader,
int width,
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
- if (width > max_size || height > max_size) {
+ if (width > 0 && (width > max_size || height > max_size)) {
factor = (gdouble) max_size / MAX (width, height);
width = width * factor;
}
GdkPixbuf *
-empathy_pixbuf_from_icon_name (const gchar *icon_name,
- GtkIconSize icon_size)
+empathy_pixbuf_from_icon_name_sized (const gchar *icon_name,
+ gint size)
{
- GtkIconTheme *theme;
- GdkPixbuf *pixbuf = NULL;
- GError *error = NULL;
- gint w, h;
- gint size = 48;
+ GtkIconTheme *theme;
+ GdkPixbuf *pixbuf;
+ GError *error = NULL;
if (!icon_name) {
return NULL;
theme = gtk_icon_theme_get_default ();
- if (gtk_icon_size_lookup (icon_size, &w, &h)) {
- size = (w + h) / 2;
- }
-
pixbuf = gtk_icon_theme_load_icon (theme,
icon_name,
size,
0,
&error);
if (error) {
- empathy_debug (DEBUG_DOMAIN, "Error loading icon: %s", error->message);
+ DEBUG ("Error loading icon: %s", error->message);
g_clear_error (&error);
}
return pixbuf;
}
+GdkPixbuf *
+empathy_pixbuf_from_icon_name (const gchar *icon_name,
+ GtkIconSize icon_size)
+{
+ gint w, h;
+ gint size = 48;
+
+ if (!icon_name) {
+ return NULL;
+ }
+
+ if (gtk_icon_size_lookup (icon_size, &w, &h)) {
+ size = (w + h) / 2;
+ }
+
+ return empathy_pixbuf_from_icon_name_sized (icon_name, size);
+}
+
+gchar *
+empathy_filename_from_icon_name (const gchar *icon_name,
+ GtkIconSize icon_size)
+{
+ GtkIconTheme *icon_theme;
+ GtkIconInfo *icon_info;
+ gint w, h;
+ gint size = 48;
+ gchar *ret;
+
+ icon_theme = gtk_icon_theme_get_default ();
+
+ if (gtk_icon_size_lookup (icon_size, &w, &h)) {
+ size = (w + h) / 2;
+ }
+
+ icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, size, 0);
+ ret = g_strdup (gtk_icon_info_get_filename (icon_info));
+ gtk_icon_info_free (icon_info);
+
+ return ret;
+}
+
/* Stolen from GtkSourceView, hence the weird intendation. Please keep it like
* that to make it easier to apply changes from the original code.
*/
if (needle_len == 0)
{
- ret = (gchar *)haystack;
+ ret = (gchar *) haystack;
goto finally_1;
}
goto finally_1;
}
- p = (gchar*)caseless_haystack;
+ p = (gchar *) caseless_haystack;
needle_len = strlen (needle);
i = 0;
/* being UTF8 correct sucks; this accounts for extra
offsets coming from canonical decompositions of
UTF8 characters (e.g. accented characters) which
- g_utf8_normalize() performs */
+ g_utf8_normalize () performs */
gchar *normal;
gchar buffer[6];
gint buffer_len;
}
} while (gtk_text_iter_forward_line (&search));
- g_strfreev ((gchar**)lines);
+ g_strfreev ((gchar **) lines);
return retval;
}
if (needle_len == 0)
{
- ret = (gchar *)haystack;
+ ret = (gchar *) haystack;
goto finally_1;
}
}
}
- g_strfreev ((gchar**)lines);
+ g_strfreev ((gchar **) lines);
return retval;
}
g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
- gdk_window = GTK_WIDGET (window)->window;
+ gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
if (!gdk_window) {
return FALSE;
}
return TRUE;
}
-void
+void
empathy_window_iconify (GtkWindow *window, GtkStatusIcon *status_icon)
{
GdkRectangle icon_location;
GdkWindow *gdk_window;
gtk_status_icon_get_geometry (status_icon, NULL, &icon_location, NULL);
- gdk_window = GTK_WIDGET (window)->window;
+ gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
dpy = gdk_x11_drawable_get_xdisplay (gdk_window);
data[0] = icon_location.x;
}
timestamp = gtk_get_current_event_time ();
- gtk_window_set_skip_taskbar_hint (window, FALSE);
gtk_window_present_with_time (window, timestamp);
+ gtk_window_set_skip_taskbar_hint (window, FALSE);
/* FIXME: This shouldn't be required as gtk_window_present's doc says
* it deiconify automatically. */
gtk_window_deiconify (window);
static gchar *
fixup_url (const gchar *url)
{
- if (!g_str_has_prefix (url, "http://") &&
- !strstr (url, ":/") &&
- !strstr (url, "@")) {
- return g_strdup_printf ("http://%s", url);
- } else {
+ g_return_val_if_fail (url != NULL, NULL);
+
+ if (g_str_has_prefix (url, "ghelp:") ||
+ g_str_has_prefix (url, "mailto:") ||
+ strstr (url, ":/")) {
return NULL;
}
+
+ if (strstr (url, "@")) {
+ return g_strdup_printf ("mailto:%s", url);
+ }
+
+ return g_strdup_printf ("http://%s", url);
}
void
-empathy_url_show (const char *url)
+empathy_url_show (GtkWidget *parent,
+ const char *url)
{
- gchar *real_url;
- gboolean res;
- GError *error;
+ gchar *real_url;
+ GError *error = NULL;
+
+ g_return_if_fail (parent == NULL || GTK_IS_WIDGET (parent));
+ g_return_if_fail (url != NULL);
real_url = fixup_url (url);
if (real_url) {
url = real_url;
}
- /* FIXME: this does not work for multihead, we should use
- * GdkAppLaunchContext for that, when we can depend on GTK+ trunk
- */
- res = g_app_info_launch_default_for_uri (url, NULL, &error);
- if (!res) {
- empathy_debug (DEBUG_DOMAIN, "Couldn't show URL %s: %s",
- url, error->message);
- g_clear_error (error);
+
+ gtk_show_uri (parent ? gtk_widget_get_screen (parent) : NULL, url,
+ gtk_get_current_event_time (), &error);
+
+ if (error) {
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (NULL, 0,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ _("Unable to open URI"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", error->message);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+ gtk_window_present (GTK_WINDOW (dialog));
+
+ g_clear_error (&error);
}
g_free (real_url);
const gchar *link,
gpointer user_data)
{
- empathy_url_show (link);
+ empathy_url_show (GTK_WIDGET (button), link);
}
GtkWidget *
g_signal_handlers_unblock_by_func (widget, callback, user_data);
}
-GtkTextTag *
-empathy_text_buffer_tag_set (GtkTextBuffer *buffer,
- const gchar *tag_name,
- const gchar *first_property_name,
- ...)
+static void
+file_manager_send_file_response_cb (GtkDialog *widget,
+ gint response_id,
+ EmpathyContact *contact)
{
- GtkTextTagTable *table;
- GtkTextTag *tag;
+ EmpathyFTFactory *factory;
+ GFile *file;
+ gchar *uri;
+ GtkRecentManager *manager;
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
- g_return_val_if_fail (tag_name != NULL, NULL);
+ if (response_id == GTK_RESPONSE_OK) {
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (widget));
+ uri = g_file_get_uri (file);
- table = gtk_text_buffer_get_tag_table (buffer);
- tag = gtk_text_tag_table_lookup (table, tag_name);
+ factory = empathy_ft_factory_dup_singleton ();
- if (!tag) {
- tag = gtk_text_tag_new (tag_name);
- gtk_text_tag_table_add (table, tag);
- g_object_unref (tag);
- } else {
- /* Clear the old values so that we don't affect the new theme. */
- g_object_set (tag,
- "background-set", FALSE,
- "foreground-set", FALSE,
- "invisible-set", FALSE,
- "justification-set", FALSE,
- "paragraph-background-set", FALSE,
- "pixels-above-lines-set", FALSE,
- "pixels-below-lines-set", FALSE,
- "rise-set", FALSE,
- "scale-set", FALSE,
- "size-set", FALSE,
- "style-set", FALSE,
- "weight-set", FALSE,
- NULL);
+ empathy_ft_factory_new_transfer_outgoing (factory, contact,
+ file);
+
+ manager = gtk_recent_manager_get_default ();
+ gtk_recent_manager_add_item (manager, uri);
+
+ g_free (uri);
+ g_object_unref (factory);
+ g_object_unref (file);
}
- if (first_property_name) {
- va_list list;
+ gtk_widget_destroy (GTK_WIDGET (widget));
+}
+
+void
+empathy_send_file_with_file_chooser (EmpathyContact *contact)
+{
+ GtkWidget *widget;
+ GtkWidget *button;
+
+ g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+
+ DEBUG ("Creating selection file chooser");
+
+ widget = gtk_file_chooser_dialog_new (_("Select a file"),
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ NULL);
+
+ /* send button */
+ button = gtk_button_new_with_mnemonic (_("_Send"));
+ gtk_button_set_image (GTK_BUTTON (button),
+ gtk_image_new_from_icon_name (EMPATHY_IMAGE_DOCUMENT_SEND,
+ GTK_ICON_SIZE_BUTTON));
+ gtk_widget_show (button);
+ gtk_dialog_add_action_widget (GTK_DIALOG (widget), button,
+ GTK_RESPONSE_OK);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_dialog_set_default_response (GTK_DIALOG (widget),
+ GTK_RESPONSE_OK);
+
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), FALSE);
+
+ g_signal_connect (widget, "response",
+ G_CALLBACK (file_manager_send_file_response_cb),
+ contact);
+
+ gtk_widget_show (widget);
+}
+
+static void
+file_manager_receive_file_response_cb (GtkDialog *dialog,
+ GtkResponseType response,
+ EmpathyFTHandler *handler)
+{
+ EmpathyFTFactory *factory;
+ GFile *file;
+
+ if (response == GTK_RESPONSE_OK) {
+ factory = empathy_ft_factory_dup_singleton ();
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
- va_start (list, first_property_name);
- g_object_set_valist (G_OBJECT (tag), first_property_name, list);
- va_end (list);
+ empathy_ft_factory_set_destination_for_incoming_handler
+ (factory, handler, file);
+
+ g_object_unref (factory);
+ g_object_unref (file);
+ } else {
+ /* unref the handler, as we dismissed the file chooser,
+ * and refused the transfer.
+ */
+ g_object_unref (handler);
}
- return tag;
+ gtk_widget_destroy (GTK_WIDGET (dialog));
}
+void
+empathy_receive_file_with_file_chooser (EmpathyFTHandler *handler)
+{
+ GtkWidget *widget;
+
+ widget = gtk_file_chooser_dialog_new (_("Select a destination"),
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE,
+ GTK_RESPONSE_OK,
+ NULL);
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (widget),
+ empathy_ft_handler_get_filename (handler));
+ gtk_file_chooser_set_do_overwrite_confirmation
+ (GTK_FILE_CHOOSER (widget), TRUE);
+
+ g_signal_connect (widget, "response",
+ G_CALLBACK (file_manager_receive_file_response_cb), handler);
+
+ gtk_widget_show (widget);
+}