[eog] Fixed Bug 615376 - if saving an image fails it's done silently.
- From: Felix Riemann <friemann src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [eog] Fixed Bug 615376 - if saving an image fails it's done silently.
- Date: Sun, 17 Jul 2011 10:02:36 +0000 (UTC)
commit 3da565496c3e9aa623d6287fa1c1aea5158b3f61
Author: Javier SÃnchez <jsanchez deskblue com>
Date: Fri Jul 15 13:09:39 2011 +0200
Fixed Bug 615376 - if saving an image fails it's done silently.
- Refactored EogErrorMessageArea to include new buttons like CANCEL,
RELOAD and SAVEAS.
- Added new custom responses to EogErrorMessageArea for new buttons.
- Refactored EogCloseConfirmationDialog to include new buttons like
CLOSE, CANCEL, SAVE and SAVE AS.
- Added new custom responses to EogCloseConfirmationDialog for new
buttons.
- Refactored EogWindow to handle new EogErrorMessageArea and
EogCloseConfirmationDialog responses.
- Refactored EogImage to include write permission verification in
SAVE and SAVE AS processes.
- Added a new method to EogImage API called eog-image-is-file-writable
to determine is when the user has write permission on the image
file.
https://bugzilla.gnome.org/show_bug.cgi?id=615376
src/eog-close-confirmation-dialog.c | 220 +++++++++++++++++++++--------------
src/eog-close-confirmation-dialog.h | 31 ++++-
src/eog-error-message-area.c | 96 +++++++++++++---
src/eog-error-message-area.h | 24 ++++-
src/eog-image.c | 106 ++++++++++++++++-
src/eog-image.h | 3 +
src/eog-jobs.c | 9 +-
src/eog-window.c | 209 +++++++++++++++++++++++++---------
8 files changed, 525 insertions(+), 173 deletions(-)
---
diff --git a/src/eog-close-confirmation-dialog.c b/src/eog-close-confirmation-dialog.c
index 5b66929..c9f874d 100644
--- a/src/eog-close-confirmation-dialog.c
+++ b/src/eog-close-confirmation-dialog.c
@@ -6,7 +6,7 @@
*
* Based on gedit code (gedit/gedit-close-confirmation.c) by gedit Team
*
- * Copyright (C) 2004-2009 GNOME Foundation
+ * Copyright (C) 2004-2009 GNOME Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,13 +15,13 @@
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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.
+ * Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
@@ -33,10 +33,18 @@
#include "eog-close-confirmation-dialog.h"
#include <eog-window.h>
+typedef enum {
+ EOG_CLOSE_CONFIRMATION_DIALOG_NO_BUTTONS = 0,
+ EOG_CLOSE_CONFIRMATION_DIALOG_CLOSE_BUTTON = 1 << 0,
+ EOG_CLOSE_CONFIRMATION_DIALOG_CANCEL_BUTTON = 1 << 1,
+ EOG_CLOSE_CONFIRMATION_DIALOG_SAVE_BUTTON = 1 << 2,
+ EOG_CLOSE_CONFIRMATION_DIALOG_SAVEAS_BUTTON = 1 << 3
+} EogCloseConfirmationDialogButtons;
+
/* Properties */
-enum
+enum
{
- PROP_0,
+ PROP_0,
PROP_UNSAVED_IMAGES
};
@@ -57,11 +65,11 @@ enum
N_COLUMNS
};
-struct _EogCloseConfirmationDialogPrivate
+struct _EogCloseConfirmationDialogPrivate
{
- GList *unsaved_images;
-
- GList *selected_images;
+ GList *unsaved_images;
+
+ GList *selected_images;
GtkTreeModel *list_store;
GtkCellRenderer *toggle_renderer;
@@ -80,10 +88,10 @@ struct _EogCloseConfirmationDialogPrivate
G_DEFINE_TYPE(EogCloseConfirmationDialog, eog_close_confirmation_dialog, GTK_TYPE_DIALOG)
-static void set_unsaved_image (EogCloseConfirmationDialog *dlg,
- const GList *list);
+static void set_unsaved_image (EogCloseConfirmationDialog *dlg,
+ const GList *list);
-static GList *get_selected_imgs (GtkTreeModel *store);
+static GList *get_selected_imgs (GtkTreeModel *store);
static GdkPixbuf *
eog_close_confirmation_dialog_get_icon (const gchar *icon_name)
@@ -116,28 +124,29 @@ get_nothumb_pixbuf (void)
return GDK_PIXBUF (g_object_ref (nothumb_once.retval));
}
-/* Since we connect in the costructor we are sure this handler will be called
+/* Since we connect in the costructor we are sure this handler will be called
* before the user ones
*/
static void
response_cb (EogCloseConfirmationDialog *dlg,
- gint response_id,
- gpointer data)
+ gint response_id,
+ gpointer data)
{
EogCloseConfirmationDialogPrivate *priv;
g_return_if_fail (EOG_IS_CLOSE_CONFIRMATION_DIALOG (dlg));
priv = dlg->priv;
-
+
if (priv->selected_images != NULL)
g_list_free (priv->selected_images);
- if (response_id == GTK_RESPONSE_YES)
+ if (response_id == EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_SAVE ||
+ response_id == EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_SAVEAS)
{
if (GET_MODE (priv) == SINGLE_IMG_MODE)
{
- priv->selected_images =
+ priv->selected_images =
g_list_copy (priv->unsaved_images);
}
else
@@ -153,35 +162,51 @@ response_cb (EogCloseConfirmationDialog *dlg,
}
static void
-add_buttons (EogCloseConfirmationDialog *dlg)
+add_buttons (EogCloseConfirmationDialog *dlg,
+ EogCloseConfirmationDialogButtons buttons)
{
- gtk_dialog_add_button (GTK_DIALOG (dlg),
- _("Close _without Saving"),
- GTK_RESPONSE_NO);
-
- gtk_dialog_add_button (GTK_DIALOG (dlg),
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
-
- gtk_dialog_add_button (GTK_DIALOG (dlg),
- GTK_STOCK_SAVE,
- GTK_RESPONSE_YES);
-
- gtk_dialog_set_default_response (GTK_DIALOG (dlg),
- GTK_RESPONSE_YES);
+ /* add requested buttons to the dialog */
+ if (buttons & EOG_CLOSE_CONFIRMATION_DIALOG_CLOSE_BUTTON) {
+ gtk_dialog_add_button (GTK_DIALOG (dlg),
+ _("Close _without Saving"),
+ EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_CLOSE);
+ }
+
+ if (buttons & EOG_CLOSE_CONFIRMATION_DIALOG_CANCEL_BUTTON) {
+ gtk_dialog_add_button (GTK_DIALOG (dlg),
+ GTK_STOCK_CANCEL,
+ EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_CANCEL);
+ }
+
+ if (buttons & EOG_CLOSE_CONFIRMATION_DIALOG_SAVE_BUTTON) {
+ gtk_dialog_add_button (GTK_DIALOG (dlg),
+ GTK_STOCK_SAVE,
+ EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_SAVE);
+ }
+
+ if (buttons & EOG_CLOSE_CONFIRMATION_DIALOG_SAVEAS_BUTTON) {
+ gtk_dialog_add_button (GTK_DIALOG (dlg),
+ GTK_STOCK_SAVE_AS,
+ EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_SAVEAS);
+ }
+
+ /* set default response */
+ gtk_dialog_set_default_response (GTK_DIALOG (dlg),
+ EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_SAVE);
}
-static void
+static void
eog_close_confirmation_dialog_init (EogCloseConfirmationDialog *dlg)
{
AtkObject *atk_obj;
dlg->priv = EOG_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE (dlg);
- gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
+ gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), 14);
gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE);
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dlg), TRUE);
-
+
gtk_window_set_title (GTK_WINDOW (dlg), "");
gtk_window_set_modal (GTK_WINDOW (dlg), TRUE);
@@ -190,14 +215,14 @@ eog_close_confirmation_dialog_init (EogCloseConfirmationDialog *dlg)
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (dlg));
atk_object_set_role (atk_obj, ATK_ROLE_ALERT);
atk_object_set_name (atk_obj, _("Question"));
-
+
g_signal_connect (dlg,
"response",
G_CALLBACK (response_cb),
NULL);
}
-static void
+static void
eog_close_confirmation_dialog_finalize (GObject *object)
{
EogCloseConfirmationDialogPrivate *priv;
@@ -215,9 +240,9 @@ eog_close_confirmation_dialog_finalize (GObject *object)
}
static void
-eog_close_confirmation_dialog_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
+eog_close_confirmation_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
GParamSpec *pspec)
{
EogCloseConfirmationDialog *dlg;
@@ -229,7 +254,7 @@ eog_close_confirmation_dialog_set_property (GObject *object,
case PROP_UNSAVED_IMAGES:
set_unsaved_image (dlg, g_value_get_pointer (value));
break;
-
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -237,9 +262,9 @@ eog_close_confirmation_dialog_set_property (GObject *object,
}
static void
-eog_close_confirmation_dialog_get_property (GObject *object,
- guint prop_id,
- GValue *value,
+eog_close_confirmation_dialog_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
GParamSpec *pspec)
{
EogCloseConfirmationDialogPrivate *priv;
@@ -258,7 +283,7 @@ eog_close_confirmation_dialog_get_property (GObject *object,
}
}
-static void
+static void
eog_close_confirmation_dialog_class_init (EogCloseConfirmationDialogClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
@@ -272,16 +297,16 @@ eog_close_confirmation_dialog_class_init (EogCloseConfirmationDialogClass *klass
g_object_class_install_property (gobject_class,
PROP_UNSAVED_IMAGES,
g_param_spec_pointer ("unsaved_images",
- "Unsaved Images",
+ "Unsaved Images",
"List of Unsaved Images",
- (G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY)));
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY)));
}
static GList *
get_selected_imgs (GtkTreeModel *store)
{
- GList *list;
+ GList *list;
gboolean valid;
GtkTreeIter iter;
@@ -293,7 +318,7 @@ get_selected_imgs (GtkTreeModel *store)
gboolean to_save;
EogImage *img;
- gtk_tree_model_get (store, &iter,
+ gtk_tree_model_get (store, &iter,
SAVE_COLUMN, &to_save,
IMG_COLUMN, &img,
-1);
@@ -317,7 +342,7 @@ eog_close_confirmation_dialog_get_selected_images (EogCloseConfirmationDialog *d
}
GtkWidget *
-eog_close_confirmation_dialog_new (GtkWindow *parent,
+eog_close_confirmation_dialog_new (GtkWindow *parent,
GList *unsaved_images)
{
GtkWidget *dlg;
@@ -326,8 +351,8 @@ eog_close_confirmation_dialog_new (GtkWindow *parent,
g_return_val_if_fail (unsaved_images != NULL, NULL);
dlg = GTK_WIDGET (g_object_new (EOG_TYPE_CLOSE_CONFIRMATION_DIALOG,
- "unsaved_images", unsaved_images,
- NULL));
+ "unsaved_images", unsaved_images,
+ NULL));
g_return_val_if_fail (dlg != NULL, NULL);
if (parent != NULL)
@@ -340,26 +365,26 @@ eog_close_confirmation_dialog_new (GtkWindow *parent,
* group. It makes no difference if it is already. */
gtk_window_group_add_window (wg, parent);
gtk_window_group_add_window (wg, GTK_WINDOW (dlg));
-
- gtk_window_set_transient_for (GTK_WINDOW (dlg), parent);
+
+ gtk_window_set_transient_for (GTK_WINDOW (dlg), parent);
}
return dlg;
}
GtkWidget *
-eog_close_confirmation_dialog_new_single (GtkWindow *parent,
+eog_close_confirmation_dialog_new_single (GtkWindow *parent,
EogImage *image)
{
GtkWidget *dlg;
GList *unsaved_images;
g_return_val_if_fail (image != NULL, NULL);
-
+
unsaved_images = g_list_prepend (NULL, image);
- dlg = eog_close_confirmation_dialog_new (parent,
+ dlg = eog_close_confirmation_dialog_new (parent,
unsaved_images);
-
+
g_list_free (unsaved_images);
return dlg;
@@ -369,9 +394,9 @@ static gchar *
get_text_secondary_label (EogImage *image)
{
gchar *secondary_msg;
-
+
secondary_msg = g_strdup (_("If you don't save, your changes will be lost."));
-
+
return secondary_msg;
}
@@ -385,14 +410,16 @@ build_single_img_dialog (EogCloseConfirmationDialog *dlg)
GtkWidget *image;
EogImage *img;
const gchar *image_name;
- gchar *str;
- gchar *markup_str;
+ gchar *str;
+ gchar *markup_str;
+
+ EogCloseConfirmationDialogButtons buttons;
g_return_if_fail (dlg->priv->unsaved_images->data != NULL);
img = EOG_IMAGE (dlg->priv->unsaved_images->data);
/* Image */
- image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
+ image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
GTK_ICON_SIZE_DIALOG);
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
@@ -428,20 +455,31 @@ build_single_img_dialog (EogCloseConfirmationDialog *dlg)
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
vbox = gtk_vbox_new (FALSE, 12);
-
+
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), primary_label, FALSE, FALSE, 0);
-
+
gtk_box_pack_start (GTK_BOX (vbox), secondary_label, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
- hbox,
- FALSE,
- FALSE,
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
+ hbox,
+ FALSE,
+ FALSE,
0);
- add_buttons (dlg);
+ if (eog_image_is_file_writable (img)) {
+ buttons = EOG_CLOSE_CONFIRMATION_DIALOG_CLOSE_BUTTON |
+ EOG_CLOSE_CONFIRMATION_DIALOG_CANCEL_BUTTON |
+ EOG_CLOSE_CONFIRMATION_DIALOG_SAVE_BUTTON;
+ } else {
+ buttons = EOG_CLOSE_CONFIRMATION_DIALOG_CLOSE_BUTTON |
+ EOG_CLOSE_CONFIRMATION_DIALOG_CANCEL_BUTTON |
+ EOG_CLOSE_CONFIRMATION_DIALOG_SAVEAS_BUTTON;
+ }
+
+ add_buttons (dlg, buttons);
+
gtk_widget_show_all (hbox);
}
@@ -478,7 +516,7 @@ populate_model (GtkTreeModel *store, GList *imgs)
IMAGE_COLUMN, buf_scaled,
NAME_COLUMN, name,
IMG_COLUMN, img,
- -1);
+ -1);
imgs = g_list_next (imgs);
g_object_unref (buf_scaled);
@@ -525,7 +563,7 @@ create_treeview (EogCloseConfirmationDialogPrivate *priv)
g_object_unref (store);
priv->list_store = GTK_TREE_MODEL (store);
-
+
/* Add columns */
priv->toggle_renderer = renderer = gtk_cell_renderer_toggle_new ();
g_signal_connect (renderer, "toggled",
@@ -547,7 +585,7 @@ create_treeview (EogCloseConfirmationDialogPrivate *priv)
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
-
+
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Name",
@@ -573,18 +611,20 @@ build_multiple_imgs_dialog (EogCloseConfirmationDialog *dlg)
GtkWidget *scrolledwindow;
GtkWidget *treeview;
GtkWidget *secondary_label;
- gchar *str;
- gchar *markup_str;
+ gchar *str;
+ gchar *markup_str;
+
+ EogCloseConfirmationDialogButtons buttons;
priv = dlg->priv;
hbox = gtk_hbox_new (FALSE, 12);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
- gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
hbox, TRUE, TRUE, 0);
/* Image */
- image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
+ image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
GTK_ICON_SIZE_DIALOG);
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
@@ -609,11 +649,11 @@ build_multiple_imgs_dialog (EogCloseConfirmationDialog *dlg)
markup_str = g_strconcat ("<span weight=\"bold\" size=\"larger\">", str, "</span>", NULL);
g_free (str);
-
+
gtk_label_set_markup (GTK_LABEL (primary_label), markup_str);
g_free (markup_str);
gtk_box_pack_start (GTK_BOX (vbox), primary_label, FALSE, FALSE, 0);
-
+
vbox2 = gtk_vbox_new (FALSE, 8);
gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0);
@@ -625,10 +665,10 @@ build_multiple_imgs_dialog (EogCloseConfirmationDialog *dlg)
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_box_pack_start (GTK_BOX (vbox2), scrolledwindow, TRUE, TRUE, 0);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
- GTK_POLICY_AUTOMATIC,
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
+ GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_SHADOW_IN);
treeview = create_treeview (priv);
@@ -645,18 +685,22 @@ build_multiple_imgs_dialog (EogCloseConfirmationDialog *dlg)
gtk_label_set_mnemonic_widget (GTK_LABEL (select_label), treeview);
- add_buttons (dlg);
+ buttons = EOG_CLOSE_CONFIRMATION_DIALOG_CLOSE_BUTTON |
+ EOG_CLOSE_CONFIRMATION_DIALOG_CANCEL_BUTTON |
+ EOG_CLOSE_CONFIRMATION_DIALOG_SAVE_BUTTON;
+
+ add_buttons (dlg, buttons);
gtk_widget_show_all (hbox);
}
static void
set_unsaved_image (EogCloseConfirmationDialog *dlg,
- const GList *list)
+ const GList *list)
{
EogCloseConfirmationDialogPrivate *priv;
- g_return_if_fail (list != NULL);
+ g_return_if_fail (list != NULL);
priv = dlg->priv;
g_return_if_fail (priv->unsaved_images == NULL);
@@ -670,7 +714,7 @@ set_unsaved_image (EogCloseConfirmationDialog *dlg,
else
{
build_multiple_imgs_dialog (dlg);
- }
+ }
}
const GList *
diff --git a/src/eog-close-confirmation-dialog.h b/src/eog-close-confirmation-dialog.h
index a4fb35e..0696933 100644
--- a/src/eog-close-confirmation-dialog.h
+++ b/src/eog-close-confirmation-dialog.h
@@ -6,7 +6,7 @@
*
* Based on gedit code (gedit/gedit-close-confirmation.h) by gedit Team
*
- * Copyright (C) 2004-2009 GNOME Foundation
+ * Copyright (C) 2004-2009 GNOME Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,8 +20,8 @@
*
* 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.
+ * Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
*/
#ifndef __EOG_CLOSE_CONFIRMATION_DIALOG_H__
@@ -43,7 +43,7 @@ typedef struct _EogCloseConfirmationDialog EogCloseConfirmationDialog;
typedef struct _EogCloseConfirmationDialogClass EogCloseConfirmationDialogClass;
typedef struct _EogCloseConfirmationDialogPrivate EogCloseConfirmationDialogPrivate;
-struct _EogCloseConfirmationDialog
+struct _EogCloseConfirmationDialog
{
GtkDialog parent;
@@ -51,11 +51,30 @@ struct _EogCloseConfirmationDialog
EogCloseConfirmationDialogPrivate *priv;
};
-struct _EogCloseConfirmationDialogClass
+struct _EogCloseConfirmationDialogClass
{
GtkDialogClass parent_class;
};
+/**
+ * EogCloseConfirmationDialogResponseType:
+ * @EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_NONE: Returned if the dialog has no response id,
+ * or if the message area gets programmatically hidden or destroyed
+ * @EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_CLOSE: Returned by CLOSE button in the dialog
+ * @EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_CANCEL: Returned by CANCEL button in the dialog
+ * @EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_SAVE: Returned by SAVE button in the dialog
+ * @EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_SAVEAS: Returned by SAVE AS button in the dialog
+ *
+ */
+typedef enum
+{
+ EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_NONE = 0,
+ EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_CLOSE = 1,
+ EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_CANCEL = 2,
+ EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_SAVE = 3,
+ EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_SAVEAS = 4
+} EogCloseConfirmationDialogResponseType;
+
G_GNUC_INTERNAL
GType eog_close_confirmation_dialog_get_type (void) G_GNUC_CONST;
@@ -63,7 +82,7 @@ G_GNUC_INTERNAL
GtkWidget *eog_close_confirmation_dialog_new (GtkWindow *parent,
GList *unsaved_documents);
G_GNUC_INTERNAL
-GtkWidget *eog_close_confirmation_dialog_new_single (GtkWindow *parent,
+GtkWidget *eog_close_confirmation_dialog_new_single (GtkWindow *parent,
EogImage *image);
G_GNUC_INTERNAL
diff --git a/src/eog-error-message-area.c b/src/eog-error-message-area.c
index 29a89c0..85ba54e 100644
--- a/src/eog-error-message-area.c
+++ b/src/eog-error-message-area.c
@@ -34,6 +34,13 @@
#include <glib-object.h>
#include <gtk/gtk.h>
+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
+} EogErrorMessageAreaButtons;
+
static void
set_message_area_text_and_icon (GtkInfoBar *message_area,
const gchar *icon_stock_id,
@@ -97,22 +104,36 @@ set_message_area_text_and_icon (GtkInfoBar *message_area,
}
static GtkWidget *
-create_error_message_area (const gchar *primary_text,
- const gchar *secondary_text,
- gboolean recoverable)
+create_error_message_area (const gchar *primary_text,
+ const gchar *secondary_text,
+ EogErrorMessageAreaButtons buttons)
{
GtkWidget *message_area;
- if (recoverable)
- message_area = gtk_info_bar_new_with_buttons (_("_Retry"),
- GTK_RESPONSE_OK,
- NULL);
- else
- message_area = gtk_info_bar_new ();
+ /* 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"),
+ EOG_ERROR_MESSAGE_AREA_RESPONSE_CANCEL);
+
+ if (buttons & EOG_ERROR_MESSAGE_AREA_RELOAD_BUTTON)
+ gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
+ _("_Reload"),
+ EOG_ERROR_MESSAGE_AREA_RESPONSE_RELOAD);
+ if (buttons & EOG_ERROR_MESSAGE_AREA_SAVEAS_BUTTON)
+ gtk_info_bar_add_button (GTK_INFO_BAR (message_area),
+ _("Save _Asâ"),
+ EOG_ERROR_MESSAGE_AREA_RESPONSE_SAVEAS);
+
+ /* set message type */
gtk_info_bar_set_message_type (GTK_INFO_BAR (message_area),
GTK_MESSAGE_ERROR);
+ /* set text and icon */
set_message_area_text_and_icon (GTK_INFO_BAR (message_area),
GTK_STOCK_DIALOG_ERROR,
primary_text,
@@ -123,10 +144,10 @@ create_error_message_area (const gchar *primary_text,
/**
* eog_image_load_error_message_area_new: (skip):
- * @caption:
- * @error:
+ * @caption:
+ * @error:
+ *
*
- *
*
* Returns: (transfer full): a new #GtkInfoBar
**/
@@ -154,7 +175,50 @@ eog_image_load_error_message_area_new (const gchar *caption,
message_area = create_error_message_area (error_message,
message_details,
- TRUE);
+ EOG_ERROR_MESSAGE_AREA_CANCEL_BUTTON);
+
+ g_free (pango_escaped_caption);
+ g_free (error_message);
+ g_free (message_details);
+
+ return message_area;
+}
+
+/**
+ * eog_image_save_error_message_area_new: (skip):
+ * @caption:
+ * @error:
+ *
+ *
+ *
+ * Returns: (transfer full): a new #GtkInfoBar
+ **/
+GtkWidget *
+eog_image_save_error_message_area_new (const gchar *caption,
+ const GError *error)
+{
+ GtkWidget *message_area;
+ gchar *error_message = NULL;
+ gchar *message_details = NULL;
+ gchar *pango_escaped_caption = NULL;
+
+ g_return_val_if_fail (caption != NULL, NULL);
+ g_return_val_if_fail (error != NULL, NULL);
+
+ /* Escape the caption string with respect to pango markup.
+ This is necessary because otherwise characters like "&" will
+ be interpreted as the beginning of a pango entity inside
+ the message area GtkLabel. */
+ pango_escaped_caption = g_markup_escape_text (caption, -1);
+ error_message = g_strdup_printf (_("Could not save image '%s'."),
+ pango_escaped_caption);
+
+ message_details = g_strdup (error->message);
+
+ message_area = create_error_message_area (error_message,
+ message_details,
+ EOG_ERROR_MESSAGE_AREA_CANCEL_BUTTON |
+ EOG_ERROR_MESSAGE_AREA_SAVEAS_BUTTON);
g_free (pango_escaped_caption);
g_free (error_message);
@@ -165,9 +229,9 @@ eog_image_load_error_message_area_new (const gchar *caption,
/**
* eog_no_images_error_message_area_new: (skip):
- * @file:
+ * @file:
+ *
*
- *
*
* Returns: (transfer full): a new #GtkInfoBar
**/
@@ -201,7 +265,7 @@ eog_no_images_error_message_area_new (GFile *file)
message_area = create_error_message_area (error_message,
NULL,
- FALSE);
+ EOG_ERROR_MESSAGE_AREA_NO_BUTTONS);
g_free (error_message);
diff --git a/src/eog-error-message-area.h b/src/eog-error-message-area.h
index d3aac06..0a6a23d 100644
--- a/src/eog-error-message-area.h
+++ b/src/eog-error-message-area.h
@@ -29,8 +29,28 @@
#include <gtk/gtk.h>
#include <gio/gio.h>
-GtkWidget *eog_image_load_error_message_area_new (const gchar *caption,
- const GError *error);
+/**
+ * EogErrorMessageAreaResponseType:
+ * @EOG_ERROR_MESSAGE_AREA_RESPONSE_NONE: Returned if the message area has no response id,
+ * or if the message area gets programmatically hidden or destroyed
+ * @EOG_ERROR_MESSAGE_AREA_RESPONSE_CANCEL: Returned by CANCEL button in the message area
+ * @EOG_ERROR_MESSAGE_AREA_RESPONSE_RELOAD: Returned by RELOAD button in the message area
+ * @EOG_ERROR_MESSAGE_AREA_RESPONSE_SAVEAS: Returned by SAVE AS button in the message area
+ *
+ */
+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
+} EogErrorMessageAreaResponseType;
+
+GtkWidget *eog_image_load_error_message_area_new (const gchar *caption,
+ const GError *error);
+
+GtkWidget *eog_image_save_error_message_area_new (const gchar *caption,
+ const GError *error);
GtkWidget *eog_no_images_error_message_area_new (GFile *file);
diff --git a/src/eog-image.c b/src/eog-image.c
index 0e06112..0d9fea5 100644
--- a/src/eog-image.c
+++ b/src/eog-image.c
@@ -1400,7 +1400,7 @@ eog_image_get_profile (EogImage *img)
* eog_image_get_thumbnail:
* @img: a #EogImage
*
- * Gets the thumbnail pixbuf for @img
+ * Gets the thumbnail pixbuf for @img
*
* Returns: (transfer full): a #GdkPixbuf with a thumbnail
**/
@@ -1625,6 +1625,59 @@ eog_image_link_with_target (EogImage *image, EogImageSaveInfo *target)
priv->file_type = g_strdup (target->format);
}
+static gboolean
+check_if_file_is_writable (GFile *file)
+{
+ GFile *file_to_check;
+ GFileInfo *file_info;
+ GError *error;
+ gboolean is_writable;
+
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+
+ /* check if file exists */
+ if (!g_file_query_exists (file, NULL)) {
+ g_warning ("%s don't exist. Checking parent directory.",
+ g_file_get_parse_name (file));
+
+ file_to_check = g_file_get_parent (file);
+
+ /* recover file information */
+ error = NULL;
+ file_info = g_file_query_info (file_to_check,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ &error);
+
+ g_object_unref (file_to_check);
+ } else {
+ file_to_check = g_file_dup (file);
+
+ /* recover file information */
+ error = NULL;
+ file_info = g_file_query_info (file_to_check,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ &error);
+ }
+
+ /* we assume that the image can't be saved when
+ we can't retrieve any file information */
+ if (file_info == NULL)
+ return FALSE;
+
+ /* check if file can be writed */
+ is_writable = g_file_info_get_attribute_boolean (file_info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
+
+ /* free objects */
+ g_object_unref (file_info);
+
+ return is_writable;
+}
+
gboolean
eog_image_save_by_info (EogImage *img, EogImageSaveInfo *source, GError **error)
{
@@ -1657,6 +1710,17 @@ eog_image_save_by_info (EogImage *img, EogImageSaveInfo *source, GError **error)
return FALSE;
}
+ /* fail if there is not write rights to save */
+ if (!check_if_file_is_writable (priv->file)) {
+ g_warning ("Could not save image '%s'.",
+ g_file_get_parse_name (priv->file));
+
+ g_set_error (error, EOG_IMAGE_ERROR,
+ EOG_IMAGE_ERROR_NOT_SAVED,
+ _("You do not have the permissions necessary to save the file."));
+ return FALSE;
+ }
+
/* generate temporary file */
tmp_file = tmp_file_get ();
@@ -1760,6 +1824,17 @@ eog_image_save_as_by_info (EogImage *img, EogImageSaveInfo *source, EogImageSave
return FALSE;
}
+ /* fail if there is not write rights to save on target */
+ if (!check_if_file_is_writable (target->file)) {
+ g_warning ("Could not save image '%s'.",
+ g_file_get_parse_name (target->file));
+
+ g_set_error (error, EOG_IMAGE_ERROR,
+ EOG_IMAGE_ERROR_NOT_SAVED,
+ _("You do not have the permissions necessary to save the file."));
+ return FALSE;
+ }
+
/* generate temporary file name */
tmp_file = tmp_file_get ();
@@ -2205,7 +2280,7 @@ eog_image_iter_advance (EogImage *img)
priv = img->priv;
if ((new_frame = gdk_pixbuf_animation_iter_advance (img->priv->anim_iter, NULL)) == TRUE)
- {
+ {
g_mutex_lock (priv->status_mutex);
g_object_unref (priv->image);
priv->image = gdk_pixbuf_animation_iter_get_pixbuf (priv->anim_iter);
@@ -2217,7 +2292,7 @@ eog_image_iter_advance (EogImage *img)
priv->image = transformed;
priv->width = gdk_pixbuf_get_width (transformed);
priv->height = gdk_pixbuf_get_height (transformed);
- }
+ }
g_mutex_unlock (priv->status_mutex);
/* Emit next frame signal so we can update the display */
g_signal_emit (img, signals[SIGNAL_NEXT_FRAME], 0,
@@ -2234,7 +2309,7 @@ eog_image_iter_advance (EogImage *img)
* Checks whether a given image is animated.
*
* Returns: #TRUE if it is an animated image, #FALSE otherwise.
- *
+ *
**/
gboolean
eog_image_is_animation (EogImage *img)
@@ -2249,7 +2324,7 @@ private_timeout (gpointer data)
EogImage *img = EOG_IMAGE (data);
EogImagePrivate *priv = img->priv;
- if (eog_image_is_animation (img) &&
+ if (eog_image_is_animation (img) &&
!g_source_is_destroyed (g_main_current_source ()) &&
priv->is_playing) {
while (eog_image_iter_advance (img) != TRUE) {}; /* cpu-sucking ? */
@@ -2339,3 +2414,24 @@ eog_image_is_file_changed (EogImage *img)
return img->priv->file_is_changed;
}
+
+/**
+ * eog_image_is_file_writable:
+ * @img: a #EogImage
+ *
+ * Evaluate if the user has write permission on the image file.
+ *
+ * Returns: %TRUE on success, %FALSE if the user hasn't write permissions on it,
+ * or @img is not an #EogImage.
+ **/
+gboolean
+eog_image_is_file_writable (EogImage *img)
+{
+ gboolean is_writable;
+
+ g_return_val_if_fail (EOG_IS_IMAGE (img), FALSE);
+
+ is_writable = check_if_file_is_writable (img->priv->file);
+
+ return is_writable;
+}
diff --git a/src/eog-image.h b/src/eog-image.h
index 85bf11e..d886278 100644
--- a/src/eog-image.h
+++ b/src/eog-image.h
@@ -68,6 +68,7 @@ typedef struct _EogImagePrivate EogImagePrivate;
typedef enum {
EOG_IMAGE_ERROR_SAVE_NOT_LOCAL,
EOG_IMAGE_ERROR_NOT_LOADED,
+ EOG_IMAGE_ERROR_NOT_SAVED,
EOG_IMAGE_ERROR_VFS,
EOG_IMAGE_ERROR_FILE_EXISTS,
EOG_IMAGE_ERROR_TMP_FILE_FAILED,
@@ -216,6 +217,8 @@ void eog_image_file_changed (EogImage *img);
gboolean eog_image_is_file_changed (EogImage *img);
+gboolean eog_image_is_file_writable (EogImage *img);
+
G_END_DECLS
#endif /* __EOG_IMAGE_H__ */
diff --git a/src/eog-jobs.c b/src/eog-jobs.c
index f415e6a..ed90725 100644
--- a/src/eog-jobs.c
+++ b/src/eog-jobs.c
@@ -771,7 +771,12 @@ eog_job_save_as_run (EogJob *ejob)
NULL,
NULL);
- file_permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE);
+ /* if we can't retrieve file permission apply default */
+ if (info != NULL) {
+ file_permissions = g_file_info_get_attribute_uint32 (info,
+ G_FILE_ATTRIBUTE_UNIX_MODE);
+ g_object_unref (info);
+ }
/* apply permission mask to file permissions */
file_permissions |= permissions_mask;
@@ -783,8 +788,6 @@ eog_job_save_as_run (EogJob *ejob)
NULL,
NULL);
- g_object_unref (info);
-
if (src_info)
g_object_unref (src_info);
diff --git a/src/eog-window.c b/src/eog-window.c
index 224a210..2735f99 100644
--- a/src/eog-window.c
+++ b/src/eog-window.c
@@ -194,6 +194,8 @@ struct _EogWindowPrivate {
static void eog_window_cmd_fullscreen (GtkAction *action, gpointer user_data);
static void eog_window_run_fullscreen (EogWindow *window, gboolean slideshow);
+static void eog_window_cmd_save (GtkAction *action, gpointer user_data);
+static void eog_window_cmd_save_as (GtkAction *action, gpointer user_data);
static void eog_window_cmd_slideshow (GtkAction *action, gpointer user_data);
static void eog_window_cmd_pause_slideshow (GtkAction *action, gpointer user_data);
static void eog_window_stop_fullscreen (EogWindow *window, gboolean slideshow);
@@ -239,7 +241,7 @@ _eog_zoom_shrink_to_boolean (GBinding *binding, const GValue *source,
is_fit = (mode == EOG_ZOOM_MODE_SHRINK_TO_FIT);
g_value_set_boolean (target, is_fit);
- return TRUE;
+ return TRUE;
}
static void
@@ -1044,7 +1046,7 @@ eog_window_update_openwith_menu (EogWindow *window, EogImage *image)
GTK_UI_MANAGER_MENUITEM,
FALSE);
- path = g_strdup_printf ("/MainMenu/Image/ImageOpenWith/Applications Placeholder/%s", name);
+ path = g_strdup_printf ("/MainMenu/Image/ImageOpenWith/Applications Placeholder/%s", name);
menuitem = gtk_ui_manager_get_widget (priv->ui_mgr, path);
@@ -1053,7 +1055,7 @@ eog_window_update_openwith_menu (EogWindow *window, EogImage *image)
g_free (path);
- path = g_strdup_printf ("/ThumbnailPopup/ImageOpenWith/Applications Placeholder/%s", name);
+ path = g_strdup_printf ("/ThumbnailPopup/ImageOpenWith/Applications Placeholder/%s", name);
menuitem = gtk_ui_manager_get_widget (priv->ui_mgr, path);
@@ -1062,7 +1064,7 @@ eog_window_update_openwith_menu (EogWindow *window, EogImage *image)
g_free (path);
- path = g_strdup_printf ("/ViewPopup/ImageOpenWith/Applications Placeholder/%s", name);
+ path = g_strdup_printf ("/ViewPopup/ImageOpenWith/Applications Placeholder/%s", name);
menuitem = gtk_ui_manager_get_widget (priv->ui_mgr, path);
@@ -1254,15 +1256,30 @@ eog_window_error_message_area_response (GtkInfoBar *message_area,
gint response_id,
EogWindow *window)
{
- if (response_id != GTK_RESPONSE_OK) {
- eog_window_set_message_area (window, NULL);
+ GtkAction *action_save_as;
- return;
- }
+ g_return_if_fail (GTK_IS_INFO_BAR (message_area));
+ g_return_if_fail (EOG_IS_WINDOW (window));
- /* Trigger loading for current image again */
- eog_thumb_view_select_single (EOG_THUMB_VIEW (window->priv->thumbview),
- EOG_THUMB_VIEW_SELECT_CURRENT);
+ /* remove message area */
+ eog_window_set_message_area (window, NULL);
+
+ /* evaluate message area response */
+ switch (response_id) {
+ case EOG_ERROR_MESSAGE_AREA_RESPONSE_NONE:
+ case EOG_ERROR_MESSAGE_AREA_RESPONSE_CANCEL:
+ /* nothing to do in this case */
+ break;
+ case EOG_ERROR_MESSAGE_AREA_RESPONSE_RELOAD:
+ /* TODO: trigger loading for current image again */
+ break;
+ case EOG_ERROR_MESSAGE_AREA_RESPONSE_SAVEAS:
+ /* trigger save as command for current image */
+ action_save_as = gtk_action_group_get_action (window->priv->actions_image,
+ "ImageSaveAs");
+ eog_window_cmd_save_as (action_save_as, window);
+ break;
+ }
}
static void
@@ -2258,12 +2275,54 @@ static void
eog_job_close_save_cb (EogJobSave *job, gpointer user_data)
{
EogWindow *window = EOG_WINDOW (user_data);
+ GtkAction *action_save;
g_signal_handlers_disconnect_by_func (job,
eog_job_close_save_cb,
window);
- gtk_widget_destroy (GTK_WIDGET (window));
+ /* clean the last save job */
+ g_object_unref (window->priv->save_job);
+ window->priv->save_job = NULL;
+
+ /* recover save action from actions group */
+ action_save = gtk_action_group_get_action (window->priv->actions_image,
+ "ImageSave");
+
+ /* check if job contains any error */
+ if (EOG_JOB (job)->error == NULL) {
+ gtk_widget_destroy (GTK_WIDGET (window));
+ } else {
+ GtkWidget *message_area;
+
+ eog_thumb_view_set_current_image (EOG_THUMB_VIEW (window->priv->thumbview),
+ job->current_image,
+ TRUE);
+
+ message_area = eog_image_save_error_message_area_new (
+ eog_image_get_caption (job->current_image),
+ EOG_JOB (job)->error);
+
+ g_signal_connect (message_area,
+ "response",
+ G_CALLBACK (eog_window_error_message_area_response),
+ window);
+
+ gtk_window_set_icon (GTK_WINDOW (window), NULL);
+ gtk_window_set_title (GTK_WINDOW (window),
+ eog_image_get_caption (job->current_image));
+
+ eog_window_set_message_area (window, message_area);
+
+ gtk_info_bar_set_default_response (GTK_INFO_BAR (message_area),
+ GTK_RESPONSE_CANCEL);
+
+ gtk_widget_show (message_area);
+
+ update_status_bar (window);
+
+ gtk_action_set_sensitive (action_save, TRUE);
+ }
}
static void
@@ -2271,38 +2330,49 @@ close_confirmation_dialog_response_handler (EogCloseConfirmationDialog *dlg,
gint response_id,
EogWindow *window)
{
- GList *selected_images;
+ GList *selected_images;
EogWindowPrivate *priv;
+ GtkAction *action_save_as;
priv = window->priv;
- switch (response_id)
- {
- case GTK_RESPONSE_YES:
- /* save selected images */
- selected_images = eog_close_confirmation_dialog_get_selected_images (dlg);
- eog_close_confirmation_dialog_set_sensitive (dlg, FALSE);
- if (eog_window_save_images (window, selected_images)) {
- g_signal_connect (priv->save_job,
- "finished",
- G_CALLBACK (eog_job_close_save_cb),
- window);
-
- eog_job_queue_add_job (priv->save_job);
- }
+ switch (response_id) {
+ case EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_SAVE:
+ selected_images = eog_close_confirmation_dialog_get_selected_images (dlg);
+ gtk_widget_destroy (GTK_WIDGET (dlg));
- break;
+ if (eog_window_save_images (window, selected_images)) {
+ g_signal_connect (priv->save_job,
+ "finished",
+ G_CALLBACK (eog_job_close_save_cb),
+ window);
- case GTK_RESPONSE_NO:
- /* dont save */
- gtk_widget_destroy (GTK_WIDGET (window));
- break;
+ eog_job_queue_add_job (priv->save_job);
+ }
- default:
- /* Cancel */
- gtk_widget_destroy (GTK_WIDGET (dlg));
- break;
- }
+ break;
+
+ case EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_SAVEAS:
+ selected_images = eog_close_confirmation_dialog_get_selected_images (dlg);
+ gtk_widget_destroy (GTK_WIDGET (dlg));
+
+ eog_thumb_view_set_current_image (EOG_THUMB_VIEW (priv->thumbview),
+ g_list_first (selected_images)->data,
+ TRUE);
+
+ action_save_as = gtk_action_group_get_action (priv->actions_image,
+ "ImageSaveAs");
+ eog_window_cmd_save_as (action_save_as, window);
+ break;
+
+ case EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_CLOSE:
+ gtk_widget_destroy (GTK_WIDGET (window));
+ break;
+
+ case EOG_CLOSE_CONFIRMATION_DIALOG_RESPONSE_CANCEL:
+ gtk_widget_destroy (GTK_WIDGET (dlg));
+ break;
+ }
}
static gboolean
@@ -2338,9 +2408,9 @@ eog_window_unsaved_images_confirm (EogWindow *window)
list = g_list_prepend (list, image);
}
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->store), &iter));
- }
+ }
- if (list) {
+ if (list) {
list = g_list_reverse (list);
dialog = eog_close_confirmation_dialog_new (GTK_WINDOW (window),
list);
@@ -2497,13 +2567,13 @@ eog_window_cmd_edit_toolbar (GtkAction *action, gpointer *user_data)
*/
if(tb_action)
g_object_bind_property (dialog, "visible",
- tb_action, "sensitive",
+ tb_action, "sensitive",
G_BINDING_SYNC_CREATE |
G_BINDING_INVERT_BOOLEAN);
/* Do the same for the EditToolbar action to avoid spawning
* additional (useless) editor windows. */
g_object_bind_property (dialog, "visible",
- action, "sensitive",
+ action, "sensitive",
G_BINDING_SYNC_CREATE |
G_BINDING_INVERT_BOOLEAN);
@@ -2763,13 +2833,46 @@ eog_job_save_cb (EogJobSave *job, gpointer user_data)
eog_job_save_progress_cb,
window);
+ /* clean the last save job */
g_object_unref (window->priv->save_job);
window->priv->save_job = NULL;
- update_status_bar (window);
+ /* recover save action from actions group */
action_save = gtk_action_group_get_action (window->priv->actions_image,
"ImageSave");
- gtk_action_set_sensitive (action_save, FALSE);
+
+ /* check if job contains any error */
+ if (EOG_JOB (job)->error == NULL) {
+ update_status_bar (window);
+
+ gtk_action_set_sensitive (action_save, FALSE);
+ } else {
+ GtkWidget *message_area;
+
+ message_area = eog_image_save_error_message_area_new (
+ eog_image_get_caption (job->current_image),
+ EOG_JOB (job)->error);
+
+ g_signal_connect (message_area,
+ "response",
+ G_CALLBACK (eog_window_error_message_area_response),
+ window);
+
+ gtk_window_set_icon (GTK_WINDOW (window), NULL);
+ gtk_window_set_title (GTK_WINDOW (window),
+ eog_image_get_caption (job->current_image));
+
+ eog_window_set_message_area (window, message_area);
+
+ gtk_info_bar_set_default_response (GTK_INFO_BAR (message_area),
+ GTK_RESPONSE_CANCEL);
+
+ gtk_widget_show (message_area);
+
+ update_status_bar (window);
+
+ gtk_action_set_sensitive (action_save, TRUE);
+ }
}
static void
@@ -2992,17 +3095,17 @@ eog_window_cmd_open_containing_folder (GtkAction *action, gpointer user_data)
{
EogWindow *window = EOG_WINDOW (user_data);
EogWindowPrivate *priv;
-
+
GtkWidget *eog_window_widget;
-
+
GFile *file;
GFile *parent = NULL;
-
- eog_window_widget = GTK_WIDGET (window);
+
+ eog_window_widget = GTK_WIDGET (window);
priv = window->priv;
-
- g_return_if_fail (priv->image != NULL);
-
+
+ g_return_if_fail (priv->image != NULL);
+
file = eog_image_get_file (priv->image);
if (file) {
@@ -3012,7 +3115,7 @@ eog_window_cmd_open_containing_folder (GtkAction *action, gpointer user_data)
if (parent) {
char *parent_uri;
-
+
parent_uri = g_file_get_uri (parent);
if (parent_uri) {
GdkScreen *screen;
@@ -3236,7 +3339,7 @@ show_move_to_trash_confirm_dialog (EogWindow *window, GList *images, gboolean ca
* asked and the trash is available */
if (can_trash && (dontaskagain || neverask))
return GTK_RESPONSE_OK;
-
+
n_images = g_list_length (images);
if (n_images == 1) {
@@ -4121,7 +4224,7 @@ eog_window_drag_data_received (GtkWidget *widget,
return;
}
- if (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_COPY)
+ if (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_COPY)
{
window = EOG_WINDOW (widget);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]