aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing-Wei Lan <lantw44@gmail.com>2013-09-08 00:33:03 +0800
committerLAN-TW <lantw44@gmail.com>2013-09-08 00:33:03 +0800
commit005a154b9490a49dcc255409d50c8a54c35aa80b (patch)
tree6ba6535a4da8bcd0b6eb460cf82e654b1c971b7a
parent956477b8de3226bbd9c51233d6572218280f579d (diff)
downloadgsoc2013-empathy-005a154b9490a49dcc255409d50c8a54c35aa80b.tar
gsoc2013-empathy-005a154b9490a49dcc255409d50c8a54c35aa80b.tar.gz
gsoc2013-empathy-005a154b9490a49dcc255409d50c8a54c35aa80b.tar.bz2
gsoc2013-empathy-005a154b9490a49dcc255409d50c8a54c35aa80b.tar.lz
gsoc2013-empathy-005a154b9490a49dcc255409d50c8a54c35aa80b.tar.xz
gsoc2013-empathy-005a154b9490a49dcc255409d50c8a54c35aa80b.tar.zst
gsoc2013-empathy-005a154b9490a49dcc255409d50c8a54c35aa80b.zip
Automatically create an archive if necessary when sending a file
These codes may still have some bugs because sending two or more files at the same time may cause Telepathy internal error. Temporary archives and directories are not removed after transfer are completed.
-rw-r--r--libempathy-gtk/empathy-ui-utils.c253
1 files changed, 251 insertions, 2 deletions
diff --git a/libempathy-gtk/empathy-ui-utils.c b/libempathy-gtk/empathy-ui-utils.c
index 69b50e266..088518c94 100644
--- a/libempathy-gtk/empathy-ui-utils.c
+++ b/libempathy-gtk/empathy-ui-utils.c
@@ -664,6 +664,20 @@ empathy_pixbuf_protocol_from_contact_scaled (EmpathyContact *contact,
return pixbuf;
}
+struct SendData
+{
+ GFile *file;
+ GFile *destination;
+ GCancellable *cancellable;
+ EmpathyContact *contact;
+ GtkWidget *dialog;
+ GtkProgressBar *progress;
+ GtkLabel *progress_label;
+ GtkLabel *filename_label;
+ gboolean dialog_shown;
+ gint64 last_notify;
+};
+
void
empathy_url_show (GtkWidget *parent,
const char *url)
@@ -701,8 +715,8 @@ empathy_url_show (GtkWidget *parent,
g_free (real_url);
}
-void
-empathy_send_file (EmpathyContact *contact,
+static void
+send_file (EmpathyContact *contact,
GFile *file)
{
EmpathyFTFactory *factory;
@@ -725,6 +739,226 @@ empathy_send_file (EmpathyContact *contact,
g_object_unref (factory);
}
+static void
+send_data_free (struct SendData *send_data)
+{
+ g_clear_object (&(send_data->file));
+ g_clear_object (&(send_data->destination));
+ g_clear_object (&(send_data->contact));
+ g_clear_object (&(send_data->cancellable));
+ if (send_data->dialog != NULL)
+ gtk_widget_destroy (send_data->dialog);
+ g_free (send_data);
+}
+
+static void
+send_file_autoar_decide_dest_cb (AutoarCreate *arcreate,
+ GFile *destination,
+ struct SendData *send_data)
+{
+ send_data->destination = g_object_ref (destination);
+}
+
+static void
+send_file_autoar_dialog_response_cb (GtkDialog *dialog,
+ gint response_id,
+ struct SendData *send_data)
+{
+ if (response_id == GTK_RESPONSE_CANCEL)
+ g_cancellable_cancel (send_data->cancellable);
+}
+
+static void
+send_file_autoar_create_dialog (struct SendData *send_data)
+{
+ GtkWidget *content;
+ GtkBox *vbox;
+ char *str, *filename, *destname;
+
+ send_data->dialog = gtk_dialog_new_with_buttons (
+ _("Creating Archives…"), NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ _("Cancel"), GTK_RESPONSE_CANCEL,
+ NULL);
+ send_data->progress = GTK_PROGRESS_BAR (gtk_progress_bar_new ());
+ send_data->progress_label = GTK_LABEL (gtk_label_new (NULL));
+
+ str = g_strdup_printf ("%s -> %s",
+ filename = autoar_common_g_file_get_name (send_data->file),
+ destname = autoar_common_g_file_get_name (send_data->destination));
+ send_data->filename_label = GTK_LABEL (gtk_label_new (str));
+
+ vbox = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 5));
+ gtk_box_pack_start (vbox, GTK_WIDGET (send_data->filename_label),
+ FALSE, FALSE, 0);
+ gtk_box_pack_start (vbox, GTK_WIDGET (send_data->progress),
+ FALSE, FALSE, 0);
+ gtk_box_pack_start (vbox, GTK_WIDGET (send_data->progress_label),
+ FALSE, FALSE, 0);
+ content = gtk_dialog_get_content_area (GTK_DIALOG (send_data->dialog));
+ gtk_container_add (GTK_CONTAINER (content), GTK_WIDGET (vbox));
+
+ g_signal_connect (send_data->dialog, "response",
+ G_CALLBACK (send_file_autoar_dialog_response_cb), send_data);
+
+ g_free (str);
+ g_free (filename);
+ g_free (destname);
+}
+
+static void
+send_file_autoar_progress_cb (AutoarCreate *arcreate,
+ guint64 completed_size,
+ guint completed_files,
+ struct SendData *send_data)
+{
+ gint64 mtime;
+
+ DEBUG ("%s: size = %" G_GUINT64_FORMAT ", files = %u",
+ __func__, completed_size, completed_files);
+
+ mtime = g_get_monotonic_time ();
+ if (mtime - send_data->last_notify < 200000)
+ return;
+
+ send_data->last_notify = mtime;
+
+ if (!(send_data->dialog_shown))
+ {
+ if (send_data->dialog == NULL)
+ send_file_autoar_create_dialog (send_data);
+ gtk_widget_show_all (send_data->dialog);
+ send_data->dialog_shown = TRUE;
+ }
+
+ if (send_data->progress != NULL)
+ gtk_progress_bar_pulse (send_data->progress);
+
+ if (send_data->progress_label != NULL)
+ {
+ gchar *msg, *size;
+ msg = g_strdup_printf (
+ _("%u files (%s) are archived"),
+ completed_files, size = g_format_size (completed_size));
+ gtk_label_set_text (send_data->progress_label, msg);
+ g_free (msg);
+ g_free (size);
+ }
+}
+
+static void
+send_file_autoar_cancelled_cb (AutoarCreate *arcreate,
+ struct SendData *send_data)
+{
+ send_data_free (send_data);
+}
+
+static void
+send_file_autoar_completed_cb (AutoarCreate *arcreate,
+ struct SendData *send_data)
+{
+ send_file (send_data->contact, send_data->destination);
+ send_data_free (send_data);
+}
+
+static void
+send_file_autoar_error_cb (AutoarCreate *arcreate,
+ GError *error,
+ struct SendData *send_data)
+{
+ GtkWidget *error_dialog;
+ char *filename;
+
+ error_dialog = gtk_message_dialog_new_with_markup (
+ NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ "<big><b>%s</b></big>",
+ filename = autoar_common_g_file_get_name (send_data->file));
+ gtk_message_dialog_format_secondary_text (
+ GTK_MESSAGE_DIALOG (error_dialog), "%s", error->message);
+ gtk_widget_show_all (error_dialog);
+ g_signal_connect_swapped (error_dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), error_dialog);
+
+ send_data_free (send_data);
+ g_free (filename);
+}
+
+static void
+send_file_info_ready_cb (GFile *file,
+ GAsyncResult *res,
+ EmpathyContact *contact)
+{
+ GFileInfo *file_info;
+ GFileType file_type;
+
+ file_info = g_file_query_info_finish (file, res, NULL);
+ if (file_info == NULL)
+ return;
+
+ file_type = g_file_info_get_file_type (file_info);
+ g_object_unref (file_info);
+
+ if (file_type == G_FILE_TYPE_DIRECTORY)
+ {
+ struct SendData *send_data;
+ AutoarPref *arpref;
+ AutoarCreate *arcreate;
+ gchar *template;
+ GFile *archive_dir;
+ gchar *archive_dir_path;
+
+ arpref = g_object_get_data (G_OBJECT (contact), "autoar-pref");
+ template = g_strdup_printf ("empathy-%s-XXXXXX", g_get_user_name ());
+ archive_dir_path = g_dir_make_tmp (template, NULL);
+ if (archive_dir_path == NULL)
+ {
+ g_free (template);
+ return;
+ }
+
+ DEBUG ("tmpdir = %s", archive_dir_path);
+ archive_dir = g_file_new_for_path (archive_dir_path);
+ arcreate = autoar_create_new_file (arpref, archive_dir, file, NULL);
+ send_data = g_new0 (struct SendData, 1);
+ send_data->contact = g_object_ref (contact);
+ send_data->file = g_object_ref (file);
+ send_data->cancellable = g_cancellable_new ();
+ send_data->last_notify = g_get_monotonic_time ();
+
+ g_signal_connect (arcreate, "decide-dest",
+ G_CALLBACK (send_file_autoar_decide_dest_cb), send_data);
+ g_signal_connect (arcreate, "progress",
+ G_CALLBACK (send_file_autoar_progress_cb), send_data);
+ g_signal_connect (arcreate, "cancelled",
+ G_CALLBACK (send_file_autoar_cancelled_cb), send_data);
+ g_signal_connect (arcreate, "completed",
+ G_CALLBACK (send_file_autoar_completed_cb), send_data);
+ g_signal_connect (arcreate, "error",
+ G_CALLBACK (send_file_autoar_error_cb), send_data);
+ autoar_create_start_async (arcreate, send_data->cancellable);
+
+ g_free (template);
+ g_free (archive_dir_path);
+ g_object_unref (archive_dir);
+ g_object_unref (arcreate);
+ }
+ else
+ {
+ send_file (contact, file);
+ }
+}
+
+void
+empathy_send_file (EmpathyContact *contact,
+ GFile *file)
+{
+ g_file_query_info_async (file,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT,
+ NULL, (GAsyncReadyCallback) send_file_info_ready_cb, contact);
+}
+
void
empathy_send_file_from_uri_list (EmpathyContact *contact,
const gchar *uri_list)
@@ -764,11 +998,20 @@ file_manager_send_file_response_cb (GtkDialog *widget,
EmpathyContact *contact)
{
GFile *file;
+ GtkWidget *format;
+ AutoarPref *arpref;
+ int arformat, arfilter;
if (response_id == GTK_RESPONSE_OK || response_id == EMPATHY_RESPONSE_SEND)
{
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (widget));
+ arpref = g_object_get_data (G_OBJECT (contact), "autoar-pref");
+ format = g_object_get_data (G_OBJECT (contact), "autoar-format");
+ autoar_gtk_format_filter_simple_get (format, &arformat, &arfilter);
+ autoar_pref_set_default_format (arpref, arformat);
+ autoar_pref_set_default_filter (arpref, arfilter);
+
empathy_send_file (contact, file);
g_object_unref (file);
@@ -860,8 +1103,14 @@ empathy_send_file_with_file_chooser (EmpathyContact *contact)
g_signal_connect (widget, "response",
G_CALLBACK (file_manager_send_file_response_cb), g_object_ref (contact));
+ g_object_set_data_full (G_OBJECT (contact), "autoar-pref",
+ g_object_ref (arpref), g_object_unref);
+ g_object_set_data_full (G_OBJECT (contact), "autoar-format",
+ g_object_ref (format_combo), g_object_unref);
gtk_widget_show (widget);
+ g_object_unref (settings);
+ g_object_unref (arpref);
}
static void