diff options
author | Ting-Wei Lan <lantw44@gmail.com> | 2013-09-08 00:33:03 +0800 |
---|---|---|
committer | LAN-TW <lantw44@gmail.com> | 2013-09-08 00:33:03 +0800 |
commit | 005a154b9490a49dcc255409d50c8a54c35aa80b (patch) | |
tree | 6ba6535a4da8bcd0b6eb460cf82e654b1c971b7a | |
parent | 956477b8de3226bbd9c51233d6572218280f579d (diff) | |
download | gsoc2013-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.c | 253 |
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 |