]> www.fi.muni.cz Git - evince.git/commitdiff
Allow multiple selection of attachments
authorCarlos Garcia Campos <carlosgc@gnome.org>
Sun, 30 Apr 2006 21:27:04 +0000 (21:27 +0000)
committerCarlos Garcia Campos <carlosgc@src.gnome.org>
Sun, 30 Apr 2006 21:27:04 +0000 (21:27 +0000)
2006-04-29  Carlos Garcia Campos  <carlosgc@gnome.org>
* backend/ev-attachment.c:
* shell/ev-attachment-bar.c:
* shell/ev-window.c:
Allow multiple selection of attachments

ChangeLog
backend/ev-attachment.c
shell/ev-attachment-bar.c
shell/ev-window.c

index 6dbe465366a6a832be4970f3b68ca525863aff44..28f4908d82e274b88b48809ff897413b70b5d5f4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2006-04-29  Carlos Garcia Campos  <carlosgc@gnome.org>
+
+       * backend/ev-attachment.c: 
+       * shell/ev-attachment-bar.c:
+       * shell/ev-window.c:
+
+       Allow multiple selection of attachments
+
 2006-04-29  Nickolay V. Shmyrev  <<nshmyrev@yandex.ru>>
 
        * shell/ev-view.c: (view_update_range_and_current_page),
index f0002f37230b362c22f835fe566351e23853895e..331473814f3a8cc95bcbe76c5bae0edf22cb6f0e 100644 (file)
@@ -367,10 +367,14 @@ ev_attachment_open (EvAttachment *attachment,
        gboolean                 retval = FALSE;
        GnomeVFSMimeApplication *default_app = NULL;
 
-       if (!attachment->priv->app)
+       g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), FALSE);
+       
+       if (!attachment->priv->app) {
                default_app = gnome_vfs_mime_get_default_application (attachment->priv->mime_type);
+               attachment->priv->app = default_app;
+       }
 
-       if (!default_app) {
+       if (!attachment->priv->app) {
                g_set_error (error,
                             EV_ATTACHMENT_ERROR,
                             0,
@@ -380,8 +384,6 @@ ev_attachment_open (EvAttachment *attachment,
                return FALSE;
        }
 
-       attachment->priv->app = default_app;
-       
        if (attachment->priv->tmp_uri &&
            g_file_test (attachment->priv->tmp_uri, G_FILE_TEST_EXISTS)) {
                retval = ev_attachment_launch_app (attachment, error);
index b58f58388f2c0e731f0c0d2138698bb5b4db4adf..cdeba899fafac559c170331a3310af37f0726ce5 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
 #include <gtk/gtk.h>
@@ -200,14 +204,77 @@ ev_attachment_bar_get_attachment_at_pos (EvAttachmentBar *ev_attachbar,
        return attachment;
 }
 
+static gboolean
+ev_attachment_bar_popup_menu_show (EvAttachmentBar *ev_attachbar,
+                                  gint             x,
+                                  gint             y)
+{
+       GtkIconView *icon_view;
+       GtkTreePath *path;
+       GList       *selected = NULL, *l;
+       GList       *attach_list = NULL;
+
+       icon_view = GTK_ICON_VIEW (ev_attachbar->priv->icon_view);
+       
+       path = gtk_icon_view_get_path_at_pos (icon_view, x, y);
+       if (!path)
+               return FALSE;
+
+       if (!gtk_icon_view_path_is_selected (icon_view, path)) {
+               gtk_icon_view_unselect_all (icon_view);
+               gtk_icon_view_select_path (icon_view, path);
+       }
+
+       gtk_tree_path_free (path);
+       
+       selected = gtk_icon_view_get_selected_items (icon_view);
+       if (!selected)
+               return FALSE;
+
+       for (l = selected; l && l->data; l = g_list_next (l)) {
+               GtkTreeIter   iter;
+               EvAttachment *attachment = NULL;
+
+               path = (GtkTreePath *) l->data;
+
+               gtk_tree_model_get_iter (GTK_TREE_MODEL (ev_attachbar->priv->model),
+                                        &iter, path);
+               gtk_tree_model_get (GTK_TREE_MODEL (ev_attachbar->priv->model), &iter,
+                                   COLUMN_ATTACHMENT, &attachment,
+                                   -1);
+
+               if (attachment)
+                       attach_list = g_list_prepend (attach_list, attachment);
+
+               gtk_tree_path_free (path);
+       }
+
+       g_list_free (selected);
+
+       if (!attach_list)
+               return FALSE;
+
+       g_signal_emit (ev_attachbar, signals[SIGNAL_POPUP_MENU], 0, attach_list);
+
+       return TRUE;
+}
+
+static gboolean
+ev_attachment_bar_popup_menu (GtkWidget *widget)
+{
+       EvAttachmentBar *ev_attachbar = EV_ATTACHMENT_BAR (widget);
+       gint             x, y;
+
+       gtk_widget_get_pointer (widget, &x, &y);
+
+       return ev_attachment_bar_popup_menu_show (ev_attachbar, x, y);
+}
+
 static gboolean
 ev_attachment_bar_button_press (EvAttachmentBar *ev_attachbar,
                                GdkEventButton  *event,
                                GtkWidget       *icon_view)
 {
-       EvAttachment *attachment;
-       gboolean      handled = FALSE;
-
        if (!GTK_WIDGET_HAS_FOCUS (icon_view)) {
                gtk_widget_grab_focus (icon_view);
        }
@@ -215,37 +282,35 @@ ev_attachment_bar_button_press (EvAttachmentBar *ev_attachbar,
        if (event->button == 2)
                return FALSE;
 
-       attachment = ev_attachment_bar_get_attachment_at_pos (ev_attachbar,
-                                                             event->x,
-                                                             event->y);
-       if (!attachment)
-               return FALSE;
-
        switch (event->button) {
        case 1:
                if (event->type == GDK_2BUTTON_PRESS) {
                        GError *error = NULL;
-
+                       EvAttachment *attachment;
+
+                       attachment = ev_attachment_bar_get_attachment_at_pos (ev_attachbar,
+                                                                             event->x,
+                                                                             event->y);
+                       if (!attachment)
+                               return FALSE;
+                       
                        ev_attachment_open (attachment, &error);
 
                        if (error) {
                                g_warning (error->message);
                                g_error_free (error);
                        }
+
+                       g_object_unref (attachment);
                                            
-                       handled = TRUE;
+                       return TRUE;
                }
                break;
-       case 3:
-               g_signal_emit (ev_attachbar, signals[SIGNAL_POPUP_MENU], 0, attachment);
-               handled = TRUE;
-               
-               break;
+       case 3: 
+               return ev_attachment_bar_popup_menu_show (ev_attachbar, event->x, event->y);
        }
 
-       g_object_unref (attachment);
-
-       return handled;
+       return FALSE;
 }
 
 static gboolean
@@ -260,24 +325,6 @@ ev_attachment_bar_focus_in (GtkWidget     *widget,
        return TRUE;
 }
 
-static gboolean
-ev_attachment_bar_popup_menu (GtkWidget *widget)
-{
-       EvAttachmentBar *ev_attachbar = EV_ATTACHMENT_BAR (widget);
-       EvAttachment    *attachment;
-       gint             x, y;
-
-       gtk_widget_get_pointer (widget, &x, &y);
-       attachment = ev_attachment_bar_get_attachment_at_pos (ev_attachbar,
-                                                             x, y);
-       if (!attachment)
-               return FALSE;
-
-       g_signal_emit (ev_attachbar, signals[SIGNAL_POPUP_MENU], 0, attachment);
-
-       return TRUE;
-}
-
 static void
 ev_attachment_bar_update_icons (EvAttachmentBar *ev_attachbar,
                                gpointer         user_data)
@@ -327,69 +374,65 @@ ev_attachment_bar_drag_data_get (GtkWidget        *widget,
                                 gpointer          user_data)
 {
        EvAttachmentBar *ev_attachbar = EV_ATTACHMENT_BAR (user_data);
-       EvAttachment    *attachment;
-       GtkTreePath     *path;
-       GtkTreeIter      iter;
-       GList           *selected = NULL;
-       gchar           *uri, *filename;
-       GError          *error = NULL;
+       GString         *uri_list;
+       gchar           *uris = NULL;
+       GList           *selected = NULL, *l;
 
        selected = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (ev_attachbar->priv->icon_view));
        if (!selected)
                return;
 
-       path = (GtkTreePath *) selected->data;
+       uri_list = g_string_new (NULL);
+       
+       for (l = selected; l && l->data; l = g_list_next (l)) {
+               EvAttachment *attachment;
+               GtkTreePath  *path;
+               GtkTreeIter   iter;
+               gchar        *uri, *filename;
+               GError       *error = NULL;
+               
+               path = (GtkTreePath *) l->data;
 
-       gtk_tree_model_get_iter (GTK_TREE_MODEL (ev_attachbar->priv->model),
-                                &iter, path);
-       gtk_tree_model_get (GTK_TREE_MODEL (ev_attachbar->priv->model), &iter,
-                           COLUMN_ATTACHMENT, &attachment,
-                           -1);
+               gtk_tree_model_get_iter (GTK_TREE_MODEL (ev_attachbar->priv->model),
+                                        &iter, path);
+               gtk_tree_model_get (GTK_TREE_MODEL (ev_attachbar->priv->model), &iter,
+                                   COLUMN_ATTACHMENT, &attachment,
+                                   -1);
 
-       filename = g_build_filename (g_get_tmp_dir (),
-                                    ev_attachment_get_name (attachment),
-                                    NULL);
-       uri = g_filename_to_uri (filename, NULL, NULL);
+               filename = g_build_filename (g_get_tmp_dir (),
+                                            ev_attachment_get_name (attachment),
+                                            NULL);
+               
+               uri = g_filename_to_uri (filename, NULL, NULL);
 
-       g_object_set_data_full (G_OBJECT (drag_context),
-                               "tmp-filename", filename,
-                               g_free);
-       
+               if (ev_attachment_save (attachment, filename, &error)) {
+                       g_string_append (uri_list, uri);
+                       g_string_append_c (uri_list, '\n');
+               }
        
-       if (ev_attachment_save (attachment, uri, &error)) {
+               if (error) {
+                       g_warning (error->message);
+                       g_error_free (error);
+               }
+
+               g_free (uri);
+               gtk_tree_path_free (path);
+               g_object_unref (attachment);
+       }
+
+       uris = g_string_free (uri_list, FALSE);
+
+       if (uris) {
                gtk_selection_data_set (data,
                                        data->target,
                                        8,
-                                       (guchar *)uri,
-                                       strlen (uri));
-       }
-       
-       if (error) {
-               g_warning (error->message);
-               g_error_free (error);
+                                       (guchar *)uris,
+                                       strlen (uris));
        }
 
-       g_free (uri);
-       g_object_unref (attachment);
-       g_list_foreach (selected,
-                       (GFunc) gtk_tree_path_free,
-                       NULL);
        g_list_free (selected);
 }
 
-static void
-ev_attachment_bar_drag_data_delete (GtkWidget      *widget,
-                                   GdkDragContext *drag_context,
-                                   gpointer        user_data)
-{
-       gchar *filename;
-
-       filename = g_object_get_data (G_OBJECT (drag_context), "tmp-filename");
-       
-       if (filename && g_file_test (filename, G_FILE_TEST_EXISTS))
-               g_unlink (filename);
-}
-
 static void
 ev_attachment_bar_destroy (GtkObject *object)
 {
@@ -432,9 +475,9 @@ ev_attachment_bar_class_init (EvAttachmentBarClass *ev_attachbar_class)
                              G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                              G_STRUCT_OFFSET (EvAttachmentBarClass, popup_menu),
                              NULL, NULL,
-                             g_cclosure_marshal_VOID__OBJECT,
+                             g_cclosure_marshal_VOID__POINTER,
                              G_TYPE_NONE, 1,
-                             G_TYPE_OBJECT);
+                             G_TYPE_POINTER);
 }
 
 static void
@@ -462,6 +505,8 @@ ev_attachment_bar_init (EvAttachmentBar *ev_attachbar)
        /* Icon View */
        ev_attachbar->priv->icon_view =
                gtk_icon_view_new_with_model (GTK_TREE_MODEL (ev_attachbar->priv->model));
+       gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (ev_attachbar->priv->icon_view),
+                                         GTK_SELECTION_MULTIPLE);
        gtk_icon_view_set_columns (GTK_ICON_VIEW (ev_attachbar->priv->icon_view), -1);
        g_object_set (G_OBJECT (ev_attachbar->priv->icon_view),
                      "text-column", COLUMN_NAME,
@@ -506,10 +551,6 @@ ev_attachment_bar_init (EvAttachmentBar *ev_attachbar)
                          "drag-data-get",
                          G_CALLBACK (ev_attachment_bar_drag_data_get),
                          (gpointer) ev_attachbar);
-       g_signal_connect (G_OBJECT (ev_attachbar->priv->icon_view),
-                         "drag-data-delete",
-                         G_CALLBACK (ev_attachment_bar_drag_data_delete),
-                         (gpointer) ev_attachbar);
 
        g_signal_connect (G_OBJECT (ev_attachbar),
                          "notify::expanded",
index f0dc8bb3a57cda3bea0f485d7135347f6fbe7a11..71cf0ec403ed172517154773eeca045abf128ba0 100644 (file)
@@ -135,7 +135,7 @@ struct _EvWindowPrivate {
 
        /* Popup attachment */
        GtkWidget    *attachment_popup;
-       EvAttachment *attachment;
+       GList        *attach_list;
 
        /* Document */
        char *uri;
@@ -1137,7 +1137,7 @@ file_save_dialog_response_cb (GtkWidget *fc,
        gboolean success;
 
        if (response_id == GTK_RESPONSE_OK) {
-               const char *uri;
+               gchar *uri;
                GError *err = NULL;
 
                uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
@@ -1152,6 +1152,8 @@ file_save_dialog_response_cb (GtkWidget *fc,
                        ev_window_error_dialog (GTK_WINDOW (fc), msg, err);
                        g_free (msg);
                }
+
+               g_free (uri);
        }
 
        gtk_widget_destroy (fc);
@@ -2567,25 +2569,30 @@ view_menu_popup_cb (EvView         *view,
        return FALSE;
 }
 
-static void
+static gboolean
 attachment_bar_menu_popup_cb (EvAttachmentBar *attachbar,
-                             EvAttachment    *attachment,
+                             GList           *attach_list,
                              EvWindow        *ev_window)
 {
        GtkWidget *popup;
 
-       if (ev_window->priv->attachment)
-               g_object_unref (ev_window->priv->attachment);
-       if (attachment)
-               ev_window->priv->attachment = g_object_ref (attachment);
-       else
-               ev_window->priv->attachment = NULL;
+       g_assert (attach_list != NULL);
+
+       if (ev_window->priv->attach_list) {
+               g_list_foreach (ev_window->priv->attach_list,
+                               (GFunc) g_object_unref, NULL);
+               g_list_free (ev_window->priv->attach_list);
+       }
+       
+       ev_window->priv->attach_list = attach_list;
        
        popup = ev_window->priv->attachment_popup;
 
        gtk_menu_popup (GTK_MENU (popup), NULL, NULL,
                        NULL, NULL,
                        3, gtk_get_current_event_time ());
+
+       return TRUE;
 }
 
 static void
@@ -2781,9 +2788,12 @@ ev_window_dispose (GObject *object)
                priv->link = NULL;
        }
 
-       if (priv->attachment) {
-               g_object_unref (priv->attachment);
-               priv->attachment = NULL;
+       if (priv->attach_list) {
+               g_list_foreach (priv->attach_list,
+                               (GFunc) g_object_unref,
+                               NULL);
+               g_list_free (priv->attach_list);
+               priv->attach_list = NULL;
        }
 
        if (priv->find_bar) {
@@ -3313,18 +3323,25 @@ ev_view_popup_cmd_copy_link_address (GtkAction *action, EvWindow *window)
 static void
 ev_attachment_popup_cmd_open_attachment (GtkAction *action, EvWindow *window)
 {
-       GError *error = NULL;
+       GList *l;
        
-       if (!window->priv->attachment)
+       if (!window->priv->attach_list)
                return;
-       
-       ev_attachment_open (window->priv->attachment, &error);
 
-       if (error) {
-               ev_window_error_dialog (GTK_WINDOW (window),
-                                       _("Unable to open attachment"),
-                                       error);
-               g_error_free (error);
+       for (l = window->priv->attach_list; l && l->data; l = g_list_next (l)) {
+               EvAttachment *attachment;
+               GError       *error = NULL;
+               
+               attachment = (EvAttachment *) l->data;
+               
+               ev_attachment_open (attachment, &error);
+
+               if (error) {
+                       ev_window_error_dialog (GTK_WINDOW (window),
+                                               _("Unable to open attachment"),
+                                               error);
+                       g_error_free (error);
+               }
        }
 }
 
@@ -3333,37 +3350,72 @@ attachment_save_dialog_response_cb (GtkWidget *fc,
                                    gint       response_id,
                                    EvWindow  *ev_window)
 {
-       if (response_id == GTK_RESPONSE_OK) {
-               const char *uri;
-               GError     *error = NULL;
-
-               uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
+       gchar                *uri;
+       GList                *l;
+       GtkFileChooserAction  fc_action;
+       gboolean              is_dir;
+       
+       if (response_id != GTK_RESPONSE_OK) {
+               gtk_widget_destroy (fc);
+               return;
+       }
 
-               ev_attachment_save (ev_window->priv->attachment, uri, &error);
+       uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
+       
+       g_object_get (G_OBJECT (fc), "action", &fc_action, NULL);
+       is_dir = (fc_action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+       
+       for (l = ev_window->priv->attach_list; l && l->data; l = g_list_next (l)) {
+               EvAttachment *attachment;
+               gchar        *filename;
+               GError       *error = NULL;
+               
+               attachment = (EvAttachment *) l->data;
 
+               if (is_dir) {
+                       filename = g_strjoin ("/", uri,
+                                             ev_attachment_get_name (attachment),
+                                             NULL);
+               } else {
+                       filename = g_strdup (uri);
+               }
+               
+               ev_attachment_save (attachment, filename, &error);
+               g_free (filename);
+               
                if (error) {
                        ev_window_error_dialog (GTK_WINDOW (fc),
-                                                _("The attachment could not be saved."),
-                                                error);
+                                               _("The attachment could not be saved."),
+                                               error);
                        g_error_free (error);
                }
        }
 
+       g_free (uri);
+
        gtk_widget_destroy (fc);
 }
 
 static void
 ev_attachment_popup_cmd_save_attachment_as (GtkAction *action, EvWindow *window)
 {
-       GtkWidget *fc;
+       GtkWidget    *fc;
+       EvAttachment *attachment = NULL;
 
-       fc = gtk_file_chooser_dialog_new (_("Save a Copy"),
-                                         GTK_WINDOW (window),
-                                         GTK_FILE_CHOOSER_ACTION_SAVE,
-                                         GTK_STOCK_CANCEL,
-                                         GTK_RESPONSE_CANCEL,
-                                         GTK_STOCK_SAVE, GTK_RESPONSE_OK,
-                                         NULL);
+       if (!window->priv->attach_list)
+               return;
+
+       if (g_list_length (window->priv->attach_list) == 1)
+               attachment = (EvAttachment *) window->priv->attach_list->data;
+       
+       fc = gtk_file_chooser_dialog_new (
+               _("Save a Copy"),
+               GTK_WINDOW (window),
+               attachment ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+               GTK_STOCK_CANCEL,
+               GTK_RESPONSE_CANCEL,
+               GTK_STOCK_SAVE, GTK_RESPONSE_OK,
+               NULL);
 
        gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
 
@@ -3371,8 +3423,9 @@ ev_attachment_popup_cmd_save_attachment_as (GtkAction *action, EvWindow *window)
        gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
 #endif
 
-       gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc),
-                                          ev_attachment_get_name (window->priv->attachment));
+       if (attachment)
+               gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc),
+                                                  ev_attachment_get_name (attachment));
 
        g_signal_connect (fc, "response",
                          G_CALLBACK (attachment_save_dialog_response_cb),
@@ -3654,19 +3707,21 @@ ev_window_init (EvWindow *ev_window)
 
        ev_window->priv->attachment_popup = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
                                                                       "/AttachmentPopup");
-       ev_window->priv->attachment = NULL;
+       ev_window->priv->attach_list = NULL;
 
        /* Give focus to the document view */
        gtk_widget_grab_focus (ev_window->priv->view);
 
        /* Drag and Drop */
-       gtk_drag_dest_unset (GTK_WIDGET (ev_window));
-       gtk_drag_dest_set (GTK_WIDGET (ev_window), GTK_DEST_DEFAULT_ALL,
+       gtk_drag_dest_unset (GTK_WIDGET (ev_window->priv->view));
+       gtk_drag_dest_set (GTK_WIDGET (ev_window->priv->view),
+                          GTK_DEST_DEFAULT_ALL,
                           ev_drop_types,
                           sizeof (ev_drop_types) / sizeof (ev_drop_types[0]),
                           GDK_ACTION_COPY);
-       g_signal_connect (G_OBJECT (ev_window), "drag-data-received",
-                         G_CALLBACK (drag_data_received_cb), NULL);
+       g_signal_connect_swapped (G_OBJECT (ev_window->priv->view), "drag-data-received",
+                                 G_CALLBACK (drag_data_received_cb),
+                                 ev_window);
 
        /* Set it user interface params */