[eog] Notify user when opening a multipage TIFF



commit f8c70c212e636b9417f5d8d27ed20e05c2260b77
Author: Felix Riemann <friemann gnome org>
Date:   Mon May 25 18:47:14 2015 +0200

    Notify user when opening a multipage TIFF
    
    Show an info bar that tries to steer the user to Evince, if available.
    This will work if at least gdk-pixbuf-2.31.1 is used.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=739654

 src/eog-error-message-area.c |  115 ++++++++++++++++++++++++++++++++++++++----
 src/eog-error-message-area.h |    6 ++-
 src/eog-image.c              |   30 +++++++++++
 src/eog-image.h              |    2 +
 src/eog-window.c             |   75 ++++++++++++++++++++++-----
 5 files changed, 203 insertions(+), 25 deletions(-)
---
diff --git a/src/eog-error-message-area.c b/src/eog-error-message-area.c
index cdbeda7..6dc9f76 100644
--- a/src/eog-error-message-area.c
+++ b/src/eog-error-message-area.c
@@ -33,12 +33,22 @@
 #include <glib/gi18n.h>
 #include <glib-object.h>
 #include <gtk/gtk.h>
+#include <gio/gdesktopappinfo.h>
+
+/* gboolean <-> gpointer conversion macros taken from gedit */
+#ifndef GBOOLEAN_TO_POINTER
+#define GBOOLEAN_TO_POINTER(i) (GINT_TO_POINTER ((i) ? 2 : 1))
+#endif
+#ifndef GPOINTER_TO_BOOLEAN
+#define GPOINTER_TO_BOOLEAN(i) ((gboolean) ((GPOINTER_TO_INT (i) == 2) ? TRUE : FALSE))
+#endif
 
 typedef enum {
        EOG_ERROR_MESSAGE_AREA_NO_BUTTONS    = 0,
        EOG_ERROR_MESSAGE_AREA_CANCEL_BUTTON = 1 << 0,
        EOG_ERROR_MESSAGE_AREA_RELOAD_BUTTON = 1 << 1,
-       EOG_ERROR_MESSAGE_AREA_SAVEAS_BUTTON = 1 << 2
+       EOG_ERROR_MESSAGE_AREA_SAVEAS_BUTTON = 1 << 2,
+       EOG_ERROR_MESSAGE_AREA_OPEN_WITH_EVINCE_BUTTON = 1 << 3
 } EogErrorMessageAreaButtons;
 
 static void
@@ -103,17 +113,10 @@ set_message_area_text_and_icon (GtkInfoBar   *message_area,
        gtk_box_pack_start (GTK_BOX (gtk_info_bar_get_content_area (GTK_INFO_BAR (message_area))), 
hbox_content, TRUE, TRUE, 0);
 }
 
-static GtkWidget *
-create_error_message_area (const gchar                 *primary_text,
-                          const gchar                 *secondary_text,
-                          EogErrorMessageAreaButtons   buttons)
+static void
+add_message_area_buttons (GtkWidget *message_area,
+                         EogErrorMessageAreaButtons buttons)
 {
-       GtkWidget *message_area;
-
-       /* create a new message area */
-       message_area = gtk_info_bar_new ();
-
-       /* add requested buttons to the message area */
        if (buttons & EOG_ERROR_MESSAGE_AREA_CANCEL_BUTTON)
                gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
                                         _("_Cancel"),
@@ -128,6 +131,24 @@ create_error_message_area (const gchar                 *primary_text,
                gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
                                         _("Save _As…"),
                                         EOG_ERROR_MESSAGE_AREA_RESPONSE_SAVEAS);
+       if (buttons & EOG_ERROR_MESSAGE_AREA_OPEN_WITH_EVINCE_BUTTON)
+               gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
+                                        _("Open with Document Viewer"),
+                                        EOG_ERROR_MESSAGE_AREA_RESPONSE_OPEN_WITH_EVINCE);
+}
+
+static GtkWidget *
+create_error_message_area (const gchar                 *primary_text,
+                          const gchar                 *secondary_text,
+                          EogErrorMessageAreaButtons   buttons)
+{
+       GtkWidget *message_area;
+
+       /* create a new message area */
+       message_area = gtk_info_bar_new ();
+
+       /* add requested buttons to the message area */
+       add_message_area_buttons (message_area, buttons);
 
        /* set message type */
        gtk_info_bar_set_message_type (GTK_INFO_BAR (message_area),
@@ -142,6 +163,32 @@ create_error_message_area (const gchar                 *primary_text,
        return message_area;
 }
 
+static GtkWidget *
+create_info_message_area (const gchar                 *primary_text,
+                         const gchar                 *secondary_text,
+                         EogErrorMessageAreaButtons   buttons)
+{
+       GtkWidget *message_area;
+
+       /* create a new message area */
+       message_area = gtk_info_bar_new ();
+
+       /* add requested buttons to the message area */
+       add_message_area_buttons (message_area, buttons);
+
+       /* set message type */
+       gtk_info_bar_set_message_type (GTK_INFO_BAR (message_area),
+                                      GTK_MESSAGE_INFO);
+
+       /* set text and icon */
+       set_message_area_text_and_icon (GTK_INFO_BAR (message_area),
+                                       "dialog-information",
+                                       primary_text,
+                                       secondary_text);
+
+       return message_area;
+}
+
 /**
  * eog_image_load_error_message_area_new: (skip):
  * @caption:
@@ -271,3 +318,49 @@ eog_no_images_error_message_area_new (GFile *file)
 
        return message_area;
 }
+
+static gpointer
+_check_evince_availability(gpointer data)
+{
+       gboolean result = FALSE;
+       GDesktopAppInfo *app_info;
+
+       app_info = g_desktop_app_info_new ("evince.desktop");
+       if (app_info) {
+               result = TRUE;
+               g_object_unref (app_info);
+       }
+       return GBOOLEAN_TO_POINTER(result);
+}
+
+GtkWidget *
+eog_multipage_error_message_area_new(void)
+{
+       static GOnce evince_is_available = G_ONCE_INIT;
+       EogErrorMessageAreaButtons buttons = EOG_ERROR_MESSAGE_AREA_NO_BUTTONS;
+       GtkWidget *message_area;
+       const gchar *info_message;
+
+       g_once (&evince_is_available, _check_evince_availability, NULL);
+
+       if (GPOINTER_TO_BOOLEAN (evince_is_available.retval))
+       {
+               buttons = EOG_ERROR_MESSAGE_AREA_OPEN_WITH_EVINCE_BUTTON;
+               info_message = N_("This image contains multiple pages. "
+                                 "Image Viewer displays only the first page.\n"
+                                 "Do you want to open the image with the Document Viewer to see all pages?");
+       } else {
+               buttons = EOG_ERROR_MESSAGE_AREA_NO_BUTTONS;
+               info_message = N_("This image contains multiple pages. "
+                                 "Image Viewer displays only the first page.\n"
+                                 "You may want to install the Document Viewer to see all pages.");
+       }
+
+       message_area = create_info_message_area (gettext (info_message),
+                                                NULL,
+                                                buttons);
+       gtk_info_bar_set_show_close_button (GTK_INFO_BAR (message_area),
+                                           TRUE);
+
+       return message_area;
+}
diff --git a/src/eog-error-message-area.h b/src/eog-error-message-area.h
index d19e8c9..bd642d9 100644
--- a/src/eog-error-message-area.h
+++ b/src/eog-error-message-area.h
@@ -43,7 +43,8 @@ typedef enum
        EOG_ERROR_MESSAGE_AREA_RESPONSE_NONE   = 0,
        EOG_ERROR_MESSAGE_AREA_RESPONSE_CANCEL = 1,
        EOG_ERROR_MESSAGE_AREA_RESPONSE_RELOAD = 2,
-       EOG_ERROR_MESSAGE_AREA_RESPONSE_SAVEAS = 3
+       EOG_ERROR_MESSAGE_AREA_RESPONSE_SAVEAS = 3,
+       EOG_ERROR_MESSAGE_AREA_RESPONSE_OPEN_WITH_EVINCE = 4
 } EogErrorMessageAreaResponseType;
 
 G_GNUC_INTERNAL
@@ -57,4 +58,7 @@ GtkWidget   *eog_image_save_error_message_area_new   (const gchar  *caption,
 G_GNUC_INTERNAL
 GtkWidget   *eog_no_images_error_message_area_new    (GFile *file);
 
+G_GNUC_INTERNAL
+GtkWidget   *eog_multipage_error_message_area_new    (void);
+
 #endif /* __EOG_ERROR_MESSAGE_AREA__ */
diff --git a/src/eog-image.c b/src/eog-image.c
index 028d93f..0ac6848 100644
--- a/src/eog-image.c
+++ b/src/eog-image.c
@@ -2501,3 +2501,33 @@ eog_image_is_jpeg (EogImage *img)
 
        return ((img->priv->file_type != NULL) && (g_ascii_strcasecmp (img->priv->file_type, 
EOG_FILE_FORMAT_JPEG) == 0));
 }
+
+/**
+ * eog_image_is_multipaged:
+ * @img: an #EogImage
+ *
+ * Check whether the image actually contains multiple images/pages.
+ * This can happen for TIFF files. GIF animations are not multipaged.
+ *
+ * Note that this only works if the image data is loaded.
+ *
+ * Returns: %TRUE if @img is multipaged, %FALSE if not or the image data wasn't loaded.
+ * Since: 3.18
+ **/
+gboolean
+eog_image_is_multipaged (EogImage *img)
+{
+       gboolean result = FALSE;
+
+       g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
+
+       if (img->priv->image != NULL)
+       {
+               const gchar* value = gdk_pixbuf_get_option (img->priv->image,
+                                                           "multipage");
+
+               result = (g_strcmp0 ("yes", value) == 0);
+       }
+
+       return result;
+}
diff --git a/src/eog-image.h b/src/eog-image.h
index d2fe428..de8feba 100644
--- a/src/eog-image.h
+++ b/src/eog-image.h
@@ -219,6 +219,8 @@ gboolean          eog_image_is_file_changed          (EogImage *img);
 
 gboolean          eog_image_is_file_writable         (EogImage *img);
 
+gboolean          eog_image_is_multipaged            (EogImage *img);
+
 G_END_DECLS
 
 #endif /* __EOG_IMAGE_H__ */
diff --git a/src/eog-window.c b/src/eog-window.c
index 529d4c8..30b7069 100644
--- a/src/eog-window.c
+++ b/src/eog-window.c
@@ -206,6 +206,9 @@ static gboolean eog_window_save_images (EogWindow *window, GList *images);
 static void eog_window_finish_saving (EogWindow *window);
 static void eog_window_zoom_scale_value_changed_cb (GtkRange *range,
                                                    gpointer user_data);
+static void eog_window_error_message_area_response (GtkInfoBar *message_area,
+                                                   gint        response_id,
+                                                   EogWindow  *window);
 
 static GQuark
 eog_window_error_quark (void)
@@ -968,6 +971,41 @@ eog_window_display_image (EogWindow *window, EogImage *image)
        update_status_bar (window);
 
        eog_window_update_open_with_menu (window, image);
+
+       if (eog_image_is_multipaged (image)) {
+               GtkWidget *info_bar;
+
+               eog_debug_message (DEBUG_IMAGE_DATA, "Image is multipaged");
+
+               info_bar = eog_multipage_error_message_area_new ();
+               g_signal_connect (info_bar,
+                                 "response",
+                                 G_CALLBACK (eog_window_error_message_area_response),
+                                 window);
+               gtk_widget_show (info_bar);
+               eog_window_set_message_area (window, info_bar);
+       }
+}
+
+static void
+_eog_window_launch_appinfo_with_files (EogWindow *window,
+                                      GAppInfo *appinfo,
+                                      GList *files)
+{
+       GdkAppLaunchContext *context;
+
+       context = gdk_display_get_app_launch_context (
+         gtk_widget_get_display (GTK_WIDGET (window)));
+       gdk_app_launch_context_set_screen (context,
+         gtk_widget_get_screen (GTK_WIDGET (window)));
+       gdk_app_launch_context_set_icon (context,
+         g_app_info_get_icon (appinfo));
+       gdk_app_launch_context_set_timestamp (context,
+         gtk_get_current_event_time ());
+
+       g_app_info_launch (appinfo, files, G_APP_LAUNCH_CONTEXT (context), NULL);
+
+       g_object_unref (context);
 }
 
 static void
@@ -980,7 +1018,7 @@ eog_window_action_open_with (GSimpleAction *action,
        GFile *file;
        GList *files = NULL;
        guint32 index = -1;
-       GdkAppLaunchContext *context;
+
 
        g_return_if_fail (EOG_IS_WINDOW (user_data));
        window = EOG_WINDOW (user_data);
@@ -996,20 +1034,10 @@ eog_window_action_open_with (GSimpleAction *action,
        file = eog_image_get_file (window->priv->image);
        files = g_list_append (files, file);
 
-       context = gdk_display_get_app_launch_context (
-         gtk_widget_get_display (GTK_WIDGET (window)));
-       gdk_app_launch_context_set_screen (context,
-         gtk_widget_get_screen (GTK_WIDGET (window)));
-       gdk_app_launch_context_set_icon (context,
-         g_app_info_get_icon (app));
-       gdk_app_launch_context_set_timestamp (context,
-         gtk_get_current_event_time ());
-
-       g_app_info_launch (app, files, G_APP_LAUNCH_CONTEXT (context), NULL);
+       _eog_window_launch_appinfo_with_files (window, app, files);
 
-       g_object_unref (file);
-       g_object_unref (context);
        g_list_free (files);
+       g_object_unref (file);
 }
 
 static void
@@ -1277,6 +1305,7 @@ eog_window_error_message_area_response (GtkInfoBar       *message_area,
        switch (response_id) {
        case EOG_ERROR_MESSAGE_AREA_RESPONSE_NONE:
        case EOG_ERROR_MESSAGE_AREA_RESPONSE_CANCEL:
+       case GTK_RESPONSE_CLOSE:
                /* nothing to do in this case */
                break;
        case EOG_ERROR_MESSAGE_AREA_RESPONSE_RELOAD:
@@ -1289,6 +1318,26 @@ eog_window_error_message_area_response (GtkInfoBar       *message_area,
                                                              "save-as");
                eog_window_action_save_as (G_SIMPLE_ACTION (action_save_as), NULL, window);
                break;
+       case EOG_ERROR_MESSAGE_AREA_RESPONSE_OPEN_WITH_EVINCE:
+       {
+               GDesktopAppInfo *app_info;
+               GFile *img_file;
+               GList *img_files = NULL;
+
+               app_info = g_desktop_app_info_new ("evince.desktop");
+
+               if (app_info) {
+                       img_file = eog_image_get_file (window->priv->image);
+                       if (img_file) {
+                               img_files = g_list_append (img_files, img_file);
+                       }
+                       _eog_window_launch_appinfo_with_files (window,
+                                                              G_APP_INFO (app_info),
+                                                              img_files);
+                       g_list_free_full (img_files, g_object_unref);
+               }
+       }
+               break;
        }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]