summaryrefslogtreecommitdiff
path: root/src/eom-window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/eom-window.c')
-rw-r--r--src/eom-window.c5796
1 files changed, 5796 insertions, 0 deletions
diff --git a/src/eom-window.c b/src/eom-window.c
new file mode 100644
index 0000000..a5a85e9
--- /dev/null
+++ b/src/eom-window.c
@@ -0,0 +1,5796 @@
+/* Eye Of Mate - Main Window
+ *
+ * Copyright (C) 2000-2008 The Free Software Foundation
+ *
+ * Author: Lucas Rocha <[email protected]>
+ *
+ * Based on code by:
+ * - Federico Mena-Quintero <[email protected]>
+ * - Jens Finke <[email protected]>
+ * Based on evince code (shell/ev-window.c) by:
+ * - Martin Kretzschmar <[email protected]>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+
+#include "eom-window.h"
+#include "eom-scroll-view.h"
+#include "eom-debug.h"
+#include "eom-file-chooser.h"
+#include "eom-thumb-view.h"
+#include "eom-list-store.h"
+#include "eom-sidebar.h"
+#include "eom-statusbar.h"
+#include "eom-preferences-dialog.h"
+#include "eom-properties-dialog.h"
+#include "eom-print.h"
+#include "eom-error-message-area.h"
+#include "eom-application.h"
+#include "eom-thumb-nav.h"
+#include "eom-config-keys.h"
+#include "eom-job-queue.h"
+#include "eom-jobs.h"
+#include "eom-util.h"
+#include "eom-save-as-dialog-helper.h"
+#include "eom-plugin-engine.h"
+#include "eom-close-confirmation-dialog.h"
+
+#include "eom-enum-types.h"
+
+#include "egg-toolbar-editor.h"
+#include "egg-editable-toolbar.h"
+#include "egg-toolbars-model.h"
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <mateconf/mateconf-client.h>
+
+#if HAVE_LCMS
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
+#include <lcms.h>
+#endif
+
+#define EOM_WINDOW_GET_PRIVATE(object) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((object), EOM_TYPE_WINDOW, EomWindowPrivate))
+
+G_DEFINE_TYPE (EomWindow, eom_window, GTK_TYPE_WINDOW);
+
+#define EOM_WINDOW_MIN_WIDTH 440
+#define EOM_WINDOW_MIN_HEIGHT 350
+
+#define EOM_WINDOW_DEFAULT_WIDTH 540
+#define EOM_WINDOW_DEFAULT_HEIGHT 450
+
+#define EOM_WINDOW_FULLSCREEN_TIMEOUT 5 * 1000
+#define EOM_WINDOW_FULLSCREEN_POPUP_THRESHOLD 5
+
+#define EOM_RECENT_FILES_GROUP "Graphics"
+#define EOM_RECENT_FILES_APP_NAME "Eye of MATE Image Viewer"
+#define EOM_RECENT_FILES_LIMIT 5
+
+#define EOM_WALLPAPER_FILENAME "eom-wallpaper"
+
+#define is_rtl (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
+
+typedef enum {
+ EOM_WINDOW_STATUS_UNKNOWN,
+ EOM_WINDOW_STATUS_INIT,
+ EOM_WINDOW_STATUS_NORMAL
+} EomWindowStatus;
+
+enum {
+ PROP_0,
+ PROP_STARTUP_FLAGS
+};
+
+enum {
+ SIGNAL_PREPARED,
+ SIGNAL_LAST
+};
+
+static gint signals[SIGNAL_LAST];
+
+/* MateConfNotifications */
+enum {
+ EOM_WINDOW_NOTIFY_INTERPOLATE,
+ EOM_WINDOW_NOTIFY_EXTRAPOLATE,
+ EOM_WINDOW_NOTIFY_SCROLLWHEEL_ZOOM,
+ EOM_WINDOW_NOTIFY_ZOOM_MULTIPLIER,
+ EOM_WINDOW_NOTIFY_BACKGROUND_COLOR,
+ EOM_WINDOW_NOTIFY_USE_BG_COLOR,
+ EOM_WINDOW_NOTIFY_TRANSPARENCY,
+ EOM_WINDOW_NOTIFY_TRANS_COLOR,
+ EOM_WINDOW_NOTIFY_SCROLL_BUTTONS,
+ EOM_WINDOW_NOTIFY_COLLECTION_POS,
+ EOM_WINDOW_NOTIFY_COLLECTION_RESIZABLE,
+ EOM_WINDOW_NOTIFY_CAN_SAVE,
+ EOM_WINDOW_NOTIFY_PROPSDIALOG_NETBOOK_MODE,
+ EOM_WINDOW_NOTIFY_LENGTH
+};
+
+struct _EomWindowPrivate {
+ MateConfClient *client;
+ guint client_notifications[EOM_WINDOW_NOTIFY_LENGTH];
+
+ EomListStore *store;
+ EomImage *image;
+ EomWindowMode mode;
+ EomWindowStatus status;
+
+ GtkUIManager *ui_mgr;
+ GtkWidget *box;
+ GtkWidget *layout;
+ GtkWidget *cbox;
+ GtkWidget *view;
+ GtkWidget *sidebar;
+ GtkWidget *thumbview;
+ GtkWidget *statusbar;
+ GtkWidget *nav;
+ GtkWidget *message_area;
+ GtkWidget *toolbar;
+ GObject *properties_dlg;
+
+ GtkActionGroup *actions_window;
+ GtkActionGroup *actions_image;
+ GtkActionGroup *actions_collection;
+ GtkActionGroup *actions_recent;
+
+ GtkWidget *fullscreen_popup;
+ GSource *fullscreen_timeout_source;
+
+ gboolean slideshow_loop;
+ gint slideshow_switch_timeout;
+ GSource *slideshow_switch_source;
+
+ guint recent_menu_id;
+
+ EomJob *load_job;
+ EomJob *transform_job;
+ EomJob *save_job;
+ GFile *last_save_as_folder;
+ EomJob *copy_job;
+
+ guint image_info_message_cid;
+ guint tip_message_cid;
+ guint copy_file_cid;
+
+ EomStartupFlags flags;
+ GSList *file_list;
+
+ gint collection_position;
+ gboolean collection_resizable;
+
+ GtkActionGroup *actions_open_with;
+ guint open_with_menu_id;
+
+ gboolean save_disabled;
+ gboolean needs_reload_confirmation;
+
+#ifdef HAVE_LCMS
+ cmsHPROFILE *display_profile;
+#endif
+};
+
+static void eom_window_cmd_fullscreen (GtkAction *action, gpointer user_data);
+static void eom_window_run_fullscreen (EomWindow *window, gboolean slideshow);
+static void eom_window_cmd_slideshow (GtkAction *action, gpointer user_data);
+static void eom_window_cmd_pause_slideshow (GtkAction *action, gpointer user_data);
+static void eom_window_stop_fullscreen (EomWindow *window, gboolean slideshow);
+static void eom_job_load_cb (EomJobLoad *job, gpointer data);
+static void eom_job_save_progress_cb (EomJobSave *job, float progress, gpointer data);
+static void eom_job_progress_cb (EomJobLoad *job, float progress, gpointer data);
+static void eom_job_transform_cb (EomJobTransform *job, gpointer data);
+static void fullscreen_set_timeout (EomWindow *window);
+static void fullscreen_clear_timeout (EomWindow *window);
+static void update_action_groups_state (EomWindow *window);
+static void open_with_launch_application_cb (GtkAction *action, gpointer callback_data);
+static void eom_window_update_openwith_menu (EomWindow *window, EomImage *image);
+static void eom_window_list_store_image_added (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data);
+static void eom_window_list_store_image_removed (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ gpointer user_data);
+static void eom_window_set_wallpaper (EomWindow *window, const gchar *filename, const gchar *visible_filename);
+static gboolean eom_window_save_images (EomWindow *window, GList *images);
+static void eom_window_finish_saving (EomWindow *window);
+
+static GQuark
+eom_window_error_quark (void)
+{
+ static GQuark q = 0;
+
+ if (q == 0)
+ q = g_quark_from_static_string ("eom-window-error-quark");
+
+ return q;
+}
+
+static void
+eom_window_interp_in_type_changed_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ gboolean interpolate_in = TRUE;
+
+ eom_debug (DEBUG_PREFERENCES);
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ g_return_if_fail (EOM_IS_SCROLL_VIEW (priv->view));
+
+ if (entry->value != NULL && entry->value->type == MATECONF_VALUE_BOOL) {
+ interpolate_in = mateconf_value_get_bool (entry->value);
+ }
+
+ eom_scroll_view_set_antialiasing_in (EOM_SCROLL_VIEW (priv->view),
+ interpolate_in);
+}
+
+static void
+eom_window_interp_out_type_changed_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ gboolean interpolate_out = TRUE;
+
+ eom_debug (DEBUG_PREFERENCES);
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ g_return_if_fail (EOM_IS_SCROLL_VIEW (priv->view));
+
+ if (entry->value != NULL && entry->value->type == MATECONF_VALUE_BOOL) {
+ interpolate_out = mateconf_value_get_bool (entry->value);
+ }
+
+ eom_scroll_view_set_antialiasing_out (EOM_SCROLL_VIEW (priv->view),
+ interpolate_out);
+}
+
+static void
+eom_window_scroll_wheel_zoom_changed_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ gboolean scroll_wheel_zoom = FALSE;
+
+ eom_debug (DEBUG_PREFERENCES);
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ g_return_if_fail (EOM_IS_SCROLL_VIEW (priv->view));
+
+ if (entry->value != NULL && entry->value->type == MATECONF_VALUE_BOOL) {
+ scroll_wheel_zoom = mateconf_value_get_bool (entry->value);
+ }
+
+ eom_scroll_view_set_scroll_wheel_zoom (EOM_SCROLL_VIEW (priv->view),
+ scroll_wheel_zoom);
+}
+
+static void
+eom_window_zoom_multiplier_changed_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ gdouble multiplier = 0.05;
+
+ eom_debug (DEBUG_PREFERENCES);
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ g_return_if_fail (EOM_IS_SCROLL_VIEW (priv->view));
+
+ if (entry->value != NULL && entry->value->type == MATECONF_VALUE_FLOAT) {
+ multiplier = mateconf_value_get_float (entry->value);
+ }
+
+ eom_scroll_view_set_zoom_multiplier (EOM_SCROLL_VIEW (priv->view),
+ multiplier);
+}
+
+static void
+eom_window_transparency_changed_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ const char *value = NULL;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_PREFERENCES);
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ g_return_if_fail (EOM_IS_SCROLL_VIEW (priv->view));
+
+ if (entry->value != NULL && entry->value->type == MATECONF_VALUE_STRING) {
+ value = mateconf_value_get_string (entry->value);
+ }
+
+ if (value == NULL) {
+ return;
+ } else if (g_ascii_strcasecmp (value, "COLOR") == 0) {
+ GdkColor color;
+ char *color_str;
+
+ color_str = mateconf_client_get_string (priv->client,
+ EOM_CONF_VIEW_TRANS_COLOR, NULL);
+ if (gdk_color_parse (color_str, &color)) {
+ eom_scroll_view_set_transparency (EOM_SCROLL_VIEW (priv->view),
+ EOM_TRANSP_COLOR, &color);
+ }
+ g_free (color_str);
+ } else if (g_ascii_strcasecmp (value, "CHECK_PATTERN") == 0) {
+ eom_scroll_view_set_transparency (EOM_SCROLL_VIEW (priv->view),
+ EOM_TRANSP_CHECKED, NULL);
+ } else {
+ eom_scroll_view_set_transparency (EOM_SCROLL_VIEW (priv->view),
+ EOM_TRANSP_BACKGROUND, NULL);
+ }
+}
+
+static void
+eom_window_bg_color_changed_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ GdkColor color;
+ const char *color_str;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_PREFERENCES);
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ g_return_if_fail (EOM_IS_SCROLL_VIEW (priv->view));
+
+ if (entry->value != NULL && entry->value->type == MATECONF_VALUE_STRING) {
+ color_str = mateconf_value_get_string (entry->value);
+
+ if (gdk_color_parse (color_str, &color)) {
+ eom_scroll_view_set_background_color (EOM_SCROLL_VIEW (priv->view), &color);
+ }
+ }
+}
+
+static void
+eom_window_use_bg_color_changed_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ gboolean use_bg_color = TRUE;
+
+ eom_debug (DEBUG_PREFERENCES);
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ g_return_if_fail (EOM_IS_SCROLL_VIEW (priv->view));
+
+ if (entry->value != NULL && entry->value->type == MATECONF_VALUE_BOOL) {
+ use_bg_color = mateconf_value_get_bool (entry->value);
+ }
+
+ eom_scroll_view_set_use_bg_color (EOM_SCROLL_VIEW (priv->view),
+ use_bg_color);
+}
+
+
+static void
+eom_window_trans_color_changed_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ GdkColor color;
+ const char *color_str;
+ char *value;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_PREFERENCES);
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ g_return_if_fail (EOM_IS_SCROLL_VIEW (priv->view));
+
+ value = mateconf_client_get_string (priv->client,
+ EOM_CONF_VIEW_TRANSPARENCY,
+ NULL);
+
+ if (!value || g_ascii_strcasecmp (value, "COLOR") != 0) {
+ g_free (value);
+ return;
+ }
+
+ if (entry->value != NULL && entry->value->type == MATECONF_VALUE_STRING) {
+ color_str = mateconf_value_get_string (entry->value);
+
+ if (gdk_color_parse (color_str, &color)) {
+ eom_scroll_view_set_transparency (EOM_SCROLL_VIEW (priv->view),
+ EOM_TRANSP_COLOR, &color);
+ }
+ }
+ g_free (value);
+}
+
+static void
+eom_window_scroll_buttons_changed_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ gboolean show_buttons = TRUE;
+
+ eom_debug (DEBUG_PREFERENCES);
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ g_return_if_fail (EOM_IS_SCROLL_VIEW (priv->view));
+
+ if (entry->value != NULL && entry->value->type == MATECONF_VALUE_BOOL) {
+ show_buttons = mateconf_value_get_bool (entry->value);
+ }
+
+ eom_thumb_nav_set_show_buttons (EOM_THUMB_NAV (priv->nav),
+ show_buttons);
+}
+
+static void
+eom_window_collection_mode_changed_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ MateConfEntry *mode_entry;
+ GtkWidget *hpaned;
+ EomThumbNavMode mode = EOM_THUMB_NAV_MODE_ONE_ROW;
+ gint position = 0;
+ gboolean resizable = FALSE;
+
+ eom_debug (DEBUG_PREFERENCES);
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ mode_entry = mateconf_client_get_entry (priv->client,
+ EOM_CONF_UI_IMAGE_COLLECTION_POSITION,
+ NULL, TRUE, NULL);
+
+ if (G_LIKELY (mode_entry != NULL)) {
+ if (mode_entry->value != NULL &&
+ mode_entry->value->type == MATECONF_VALUE_INT) {
+ position = mateconf_value_get_int (mode_entry->value);
+ }
+ mateconf_entry_unref (mode_entry);
+ }
+
+ mode_entry = mateconf_client_get_entry (priv->client,
+ EOM_CONF_UI_IMAGE_COLLECTION_RESIZABLE,
+ NULL, TRUE, NULL);
+
+ if (G_LIKELY (mode_entry != NULL)) {
+ if (mode_entry->value != NULL &&
+ mode_entry->value->type == MATECONF_VALUE_BOOL) {
+ resizable = mateconf_value_get_bool (mode_entry->value);
+ }
+ mateconf_entry_unref (mode_entry);
+ }
+
+ if (priv->collection_position == position &&
+ priv->collection_resizable == resizable)
+ return;
+
+ priv->collection_position = position;
+ priv->collection_resizable = resizable;
+
+ hpaned = gtk_widget_get_parent (priv->sidebar);
+
+ g_object_ref (hpaned);
+ g_object_ref (priv->nav);
+
+ gtk_container_remove (GTK_CONTAINER (priv->layout), hpaned);
+ gtk_container_remove (GTK_CONTAINER (priv->layout), priv->nav);
+
+ gtk_widget_destroy (priv->layout);
+
+ switch (position) {
+ case 0:
+ case 2:
+ if (resizable) {
+ mode = EOM_THUMB_NAV_MODE_MULTIPLE_ROWS;
+
+ priv->layout = gtk_vpaned_new ();
+
+ if (position == 0) {
+ gtk_paned_pack1 (GTK_PANED (priv->layout), hpaned, TRUE, FALSE);
+ gtk_paned_pack2 (GTK_PANED (priv->layout), priv->nav, FALSE, TRUE);
+ } else {
+ gtk_paned_pack1 (GTK_PANED (priv->layout), priv->nav, FALSE, TRUE);
+ gtk_paned_pack2 (GTK_PANED (priv->layout), hpaned, TRUE, FALSE);
+ }
+ } else {
+ mode = EOM_THUMB_NAV_MODE_ONE_ROW;
+
+ priv->layout = gtk_vbox_new (FALSE, 2);
+
+ if (position == 0) {
+ gtk_box_pack_start (GTK_BOX (priv->layout), hpaned, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (priv->layout), priv->nav, FALSE, FALSE, 0);
+ } else {
+ gtk_box_pack_start (GTK_BOX (priv->layout), priv->nav, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (priv->layout), hpaned, TRUE, TRUE, 0);
+ }
+ }
+ break;
+
+ case 1:
+ case 3:
+ if (resizable) {
+ mode = EOM_THUMB_NAV_MODE_MULTIPLE_COLUMNS;
+
+ priv->layout = gtk_hpaned_new ();
+
+ if (position == 1) {
+ gtk_paned_pack1 (GTK_PANED (priv->layout), priv->nav, FALSE, TRUE);
+ gtk_paned_pack2 (GTK_PANED (priv->layout), hpaned, TRUE, FALSE);
+ } else {
+ gtk_paned_pack1 (GTK_PANED (priv->layout), hpaned, TRUE, FALSE);
+ gtk_paned_pack2 (GTK_PANED (priv->layout), priv->nav, FALSE, TRUE);
+ }
+ } else {
+ mode = EOM_THUMB_NAV_MODE_ONE_COLUMN;
+
+ priv->layout = gtk_hbox_new (FALSE, 2);
+
+ if (position == 1) {
+ gtk_box_pack_start (GTK_BOX (priv->layout), priv->nav, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (priv->layout), hpaned, TRUE, TRUE, 0);
+ } else {
+ gtk_box_pack_start (GTK_BOX (priv->layout), hpaned, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (priv->layout), priv->nav, FALSE, FALSE, 0);
+ }
+ }
+
+ break;
+ }
+
+ gtk_box_pack_end (GTK_BOX (priv->cbox), priv->layout, TRUE, TRUE, 0);
+
+ eom_thumb_nav_set_mode (EOM_THUMB_NAV (priv->nav), mode);
+
+ if (priv->mode != EOM_WINDOW_STATUS_UNKNOWN) {
+ update_action_groups_state (EOM_WINDOW (user_data));
+ }
+}
+
+static void
+eom_window_can_save_changed_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ EomWindow *window;
+ gboolean save_disabled = FALSE;
+ GtkAction *action_save, *action_save_as;
+
+ eom_debug (DEBUG_PREFERENCES);
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ window = EOM_WINDOW (user_data);
+ priv = EOM_WINDOW (user_data)->priv;
+
+ if (entry->value != NULL && entry->value->type == MATECONF_VALUE_BOOL) {
+ save_disabled = mateconf_value_get_bool (entry->value);
+ }
+
+ priv->save_disabled = save_disabled;
+
+ action_save =
+ gtk_action_group_get_action (priv->actions_image, "ImageSave");
+ action_save_as =
+ gtk_action_group_get_action (priv->actions_image, "ImageSaveAs");
+
+ if (priv->save_disabled) {
+ gtk_action_set_sensitive (action_save, FALSE);
+ gtk_action_set_sensitive (action_save_as, FALSE);
+ } else {
+ EomImage *image = eom_window_get_image (window);
+
+ if (EOM_IS_IMAGE (image)) {
+ gtk_action_set_sensitive (action_save,
+ eom_image_is_modified (image));
+
+ gtk_action_set_sensitive (action_save_as, TRUE);
+ }
+ }
+}
+
+static void
+eom_window_pd_nbmode_changed_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer user_data)
+{
+ EomWindow *window = EOM_WINDOW (user_data);
+
+ if (window->priv->properties_dlg != NULL) {
+ gboolean netbook_mode;
+ EomPropertiesDialog *dlg;
+
+ netbook_mode = mateconf_value_get_bool (entry->value);
+ dlg = EOM_PROPERTIES_DIALOG (window->priv->properties_dlg);
+
+ eom_properties_dialog_set_netbook_mode (dlg, netbook_mode);
+ }
+}
+
+#ifdef HAVE_LCMS
+static cmsHPROFILE *
+eom_window_get_display_profile (GdkScreen *screen)
+{
+ Display *dpy;
+ Atom icc_atom, type;
+ int format;
+ gulong nitems;
+ gulong bytes_after;
+ gulong length;
+ guchar *str;
+ int result;
+ cmsHPROFILE *profile;
+ char *atom_name;
+ int lcms_error_action;
+
+ dpy = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
+
+ if (gdk_screen_get_number (screen) > 0)
+ atom_name = g_strdup_printf ("_ICC_PROFILE_%d", gdk_screen_get_number (screen));
+ else
+ atom_name = g_strdup ("_ICC_PROFILE");
+
+ icc_atom = gdk_x11_get_xatom_by_name_for_display (gdk_screen_get_display (screen), atom_name);
+
+ g_free (atom_name);
+
+ result = XGetWindowProperty (dpy,
+ GDK_WINDOW_XID (gdk_screen_get_root_window (screen)),
+ icc_atom,
+ 0,
+ G_MAXLONG,
+ False,
+ XA_CARDINAL,
+ &type,
+ &format,
+ &nitems,
+ &bytes_after,
+ (guchar **)&str);
+
+ /* TODO: handle bytes_after != 0 */
+
+ if ((result == Success) && (type == XA_CARDINAL) && (nitems > 0)) {
+ switch (format)
+ {
+ case 8:
+ length = nitems;
+ break;
+ case 16:
+ length = sizeof(short) * nitems;
+ break;
+ case 32:
+ length = sizeof(long) * nitems;
+ break;
+ default:
+ eom_debug_message (DEBUG_LCMS, "Unable to read profile, not correcting");
+
+ XFree (str);
+ return NULL;
+ }
+
+ /* Make lcms errors non-fatal here, as it is possible
+ * to load invalid profiles with XICC.
+ * We don't want lcms to abort EOM in that case.
+ */
+ lcms_error_action = cmsErrorAction (LCMS_ERROR_IGNORE);
+
+ profile = cmsOpenProfileFromMem (str, length);
+
+ // Restore the previous error setting
+ cmsErrorAction (lcms_error_action);
+
+ if (G_UNLIKELY (profile == NULL)) {
+ eom_debug_message (DEBUG_LCMS,
+ "Invalid display profile, "
+ "not correcting");
+ }
+
+ XFree (str);
+ } else {
+ profile = NULL;
+ eom_debug_message (DEBUG_LCMS, "No profile, not correcting");
+ }
+
+ return profile;
+}
+#endif
+
+static void
+update_image_pos (EomWindow *window)
+{
+ EomWindowPrivate *priv;
+ gint pos, n_images;
+
+ priv = window->priv;
+
+ n_images = eom_list_store_length (EOM_LIST_STORE (priv->store));
+
+ if (n_images > 0) {
+ pos = eom_list_store_get_pos_by_image (EOM_LIST_STORE (priv->store),
+ priv->image);
+
+ /* Images: (image pos) / (n_total_images) */
+ eom_statusbar_set_image_number (EOM_STATUSBAR (priv->statusbar),
+ pos + 1,
+ n_images);
+ }
+}
+
+static void
+update_status_bar (EomWindow *window)
+{
+ EomWindowPrivate *priv;
+ char *str = NULL;
+
+ g_return_if_fail (EOM_IS_WINDOW (window));
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = window->priv;
+
+ if (priv->image != NULL &&
+ eom_image_has_data (priv->image, EOM_IMAGE_DATA_ALL)) {
+ int zoom, width, height;
+ goffset bytes = 0;
+
+ zoom = floor (100 * eom_scroll_view_get_zoom (EOM_SCROLL_VIEW (priv->view)) + 0.5);
+
+ eom_image_get_size (priv->image, &width, &height);
+
+ bytes = eom_image_get_bytes (priv->image);
+
+ if ((width > 0) && (height > 0)) {
+ char *size_string;
+
+ size_string = g_format_size_for_display (bytes);
+
+ /* Translators: This is the string displayed in the statusbar
+ * The tokens are from left to right:
+ * - image width
+ * - image height
+ * - image size in bytes
+ * - zoom in percent */
+ str = g_strdup_printf (ngettext("%i × %i pixel %s %i%%",
+ "%i × %i pixels %s %i%%", height),
+ width,
+ height,
+ size_string,
+ zoom);
+
+ g_free (size_string);
+ }
+
+ update_image_pos (window);
+ }
+
+ gtk_statusbar_pop (GTK_STATUSBAR (priv->statusbar),
+ priv->image_info_message_cid);
+
+ gtk_statusbar_push (GTK_STATUSBAR (priv->statusbar),
+ priv->image_info_message_cid, str ? str : "");
+
+ g_free (str);
+}
+
+static void
+eom_window_set_message_area (EomWindow *window,
+ GtkWidget *message_area)
+{
+ if (window->priv->message_area == message_area)
+ return;
+
+ if (window->priv->message_area != NULL)
+ gtk_widget_destroy (window->priv->message_area);
+
+ window->priv->message_area = message_area;
+
+ if (message_area == NULL) return;
+
+ gtk_box_pack_start (GTK_BOX (window->priv->cbox),
+ window->priv->message_area,
+ FALSE,
+ FALSE,
+ 0);
+
+ g_object_add_weak_pointer (G_OBJECT (window->priv->message_area),
+ (void *) &window->priv->message_area);
+}
+
+static void
+update_action_groups_state (EomWindow *window)
+{
+ EomWindowPrivate *priv;
+ GtkAction *action_collection;
+ GtkAction *action_sidebar;
+ GtkAction *action_fscreen;
+ GtkAction *action_sshow;
+ GtkAction *action_print;
+ gboolean print_disabled = FALSE;
+ gboolean page_setup_disabled = FALSE;
+ gboolean show_image_collection = FALSE;
+ gint n_images = 0;
+
+ g_return_if_fail (EOM_IS_WINDOW (window));
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = window->priv;
+
+ action_collection =
+ gtk_action_group_get_action (priv->actions_window,
+ "ViewImageCollection");
+
+ action_sidebar =
+ gtk_action_group_get_action (priv->actions_window,
+ "ViewSidebar");
+
+ action_fscreen =
+ gtk_action_group_get_action (priv->actions_image,
+ "ViewFullscreen");
+
+ action_sshow =
+ gtk_action_group_get_action (priv->actions_collection,
+ "ViewSlideshow");
+
+ action_print =
+ gtk_action_group_get_action (priv->actions_image,
+ "ImagePrint");
+
+ g_assert (action_collection != NULL);
+ g_assert (action_sidebar != NULL);
+ g_assert (action_fscreen != NULL);
+ g_assert (action_sshow != NULL);
+ g_assert (action_print != NULL);
+
+ if (priv->store != NULL) {
+ n_images = eom_list_store_length (EOM_LIST_STORE (priv->store));
+ }
+
+ if (n_images == 0) {
+ gtk_widget_hide (priv->layout);
+
+ gtk_action_group_set_sensitive (priv->actions_window, TRUE);
+ gtk_action_group_set_sensitive (priv->actions_image, FALSE);
+ gtk_action_group_set_sensitive (priv->actions_collection, FALSE);
+
+ gtk_action_set_sensitive (action_fscreen, FALSE);
+ gtk_action_set_sensitive (action_sshow, FALSE);
+
+ /* If there are no images on model, initialization
+ stops here. */
+ if (priv->status == EOM_WINDOW_STATUS_INIT) {
+ priv->status = EOM_WINDOW_STATUS_NORMAL;
+ }
+ } else {
+ if (priv->flags & EOM_STARTUP_DISABLE_COLLECTION) {
+ mateconf_client_set_bool (priv->client,
+ EOM_CONF_UI_IMAGE_COLLECTION,
+ FALSE,
+ NULL);
+
+ show_image_collection = FALSE;
+ } else {
+ show_image_collection =
+ mateconf_client_get_bool (priv->client,
+ EOM_CONF_UI_IMAGE_COLLECTION,
+ NULL);
+ }
+
+ show_image_collection = show_image_collection &&
+ n_images > 1 &&
+ priv->mode != EOM_WINDOW_MODE_SLIDESHOW;
+
+ gtk_widget_show (priv->layout);
+
+ if (show_image_collection)
+ gtk_widget_show (priv->nav);
+
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action_collection),
+ show_image_collection);
+
+ gtk_action_group_set_sensitive (priv->actions_window, TRUE);
+ gtk_action_group_set_sensitive (priv->actions_image, TRUE);
+
+ gtk_action_set_sensitive (action_fscreen, TRUE);
+
+ if (n_images == 1) {
+ gtk_action_group_set_sensitive (priv->actions_collection, FALSE);
+ gtk_action_set_sensitive (action_collection, FALSE);
+ gtk_action_set_sensitive (action_sshow, FALSE);
+ } else {
+ gtk_action_group_set_sensitive (priv->actions_collection, TRUE);
+ gtk_action_set_sensitive (action_sshow, TRUE);
+ }
+
+ if (show_image_collection)
+ gtk_widget_grab_focus (priv->thumbview);
+ else
+ gtk_widget_grab_focus (priv->view);
+ }
+
+ print_disabled = mateconf_client_get_bool (priv->client,
+ EOM_CONF_DESKTOP_CAN_PRINT,
+ NULL);
+
+ if (print_disabled) {
+ gtk_action_set_sensitive (action_print, FALSE);
+ }
+
+ page_setup_disabled = mateconf_client_get_bool (priv->client,
+ EOM_CONF_DESKTOP_CAN_SETUP_PAGE,
+ NULL);
+
+ if (eom_sidebar_is_empty (EOM_SIDEBAR (priv->sidebar))) {
+ gtk_action_set_sensitive (action_sidebar, FALSE);
+ gtk_widget_hide (priv->sidebar);
+ }
+}
+
+static void
+update_selection_ui_visibility (EomWindow *window)
+{
+ EomWindowPrivate *priv;
+ GtkAction *wallpaper_action;
+ gint n_selected;
+
+ priv = window->priv;
+
+ n_selected = eom_thumb_view_get_n_selected (EOM_THUMB_VIEW (priv->thumbview));
+
+ wallpaper_action =
+ gtk_action_group_get_action (priv->actions_image,
+ "ImageSetAsWallpaper");
+
+ if (n_selected == 1) {
+ gtk_action_set_sensitive (wallpaper_action, TRUE);
+ } else {
+ gtk_action_set_sensitive (wallpaper_action, FALSE);
+ }
+}
+
+static gboolean
+add_file_to_recent_files (GFile *file)
+{
+ gchar *text_uri;
+ GFileInfo *file_info;
+ GtkRecentData *recent_data;
+ static gchar *groups[2] = { EOM_RECENT_FILES_GROUP , NULL };
+
+ if (file == NULL) return FALSE;
+
+ /* The password gets stripped here because ~/.recently-used.xbel is
+ * readable by everyone (chmod 644). It also makes the workaround
+ * for the bug with gtk_recent_info_get_uri_display() easier
+ * (see the comment in eom_window_update_recent_files_menu()). */
+ text_uri = g_file_get_uri (file);
+
+ if (text_uri == NULL)
+ return FALSE;
+
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ 0, NULL, NULL);
+ if (file_info == NULL)
+ return FALSE;
+
+ recent_data = g_slice_new (GtkRecentData);
+ recent_data->display_name = NULL;
+ recent_data->description = NULL;
+ recent_data->mime_type = (gchar *) g_file_info_get_content_type (file_info);
+ recent_data->app_name = EOM_RECENT_FILES_APP_NAME;
+ recent_data->app_exec = g_strjoin(" ", g_get_prgname (), "%u", NULL);
+ recent_data->groups = groups;
+ recent_data->is_private = FALSE;
+
+ gtk_recent_manager_add_full (gtk_recent_manager_get_default (),
+ text_uri,
+ recent_data);
+
+ g_free (recent_data->app_exec);
+ g_free (text_uri);
+ g_object_unref (file_info);
+
+ g_slice_free (GtkRecentData, recent_data);
+
+ return FALSE;
+}
+
+static void
+image_thumb_changed_cb (EomImage *image, gpointer data)
+{
+ EomWindow *window;
+ EomWindowPrivate *priv;
+ GdkPixbuf *thumb;
+
+ g_return_if_fail (EOM_IS_WINDOW (data));
+
+ window = EOM_WINDOW (data);
+ priv = window->priv;
+
+ thumb = eom_image_get_thumbnail (image);
+
+ if (thumb != NULL) {
+ gtk_window_set_icon (GTK_WINDOW (window), thumb);
+
+ if (window->priv->properties_dlg != NULL) {
+ eom_properties_dialog_update (EOM_PROPERTIES_DIALOG (priv->properties_dlg),
+ image);
+ }
+
+ g_object_unref (thumb);
+ } else if (!gtk_widget_get_visible (window->priv->nav)) {
+ gint img_pos = eom_list_store_get_pos_by_image (window->priv->store, image);
+ GtkTreePath *path = gtk_tree_path_new_from_indices (img_pos,-1);
+ GtkTreeIter iter;
+
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (window->priv->store), &iter, path);
+ eom_list_store_thumbnail_set (window->priv->store, &iter);
+ gtk_tree_path_free (path);
+ }
+}
+
+static void
+file_changed_info_bar_response (GtkInfoBar *info_bar,
+ gint response,
+ EomWindow *window)
+{
+ if (response == GTK_RESPONSE_YES) {
+ eom_window_reload_image (window);
+ }
+
+ window->priv->needs_reload_confirmation = TRUE;
+
+ eom_window_set_message_area (window, NULL);
+}
+static void
+image_file_changed_cb (EomImage *img, EomWindow *window)
+{
+ GtkWidget *info_bar;
+ gchar *text, *markup;
+ GtkWidget *image;
+ GtkWidget *label;
+ GtkWidget *hbox;
+
+ if (window->priv->needs_reload_confirmation == FALSE)
+ return;
+
+ window->priv->needs_reload_confirmation = FALSE;
+
+ info_bar = gtk_info_bar_new_with_buttons (_("_Reload"),
+ GTK_RESPONSE_YES,
+ C_("MessageArea", "Hi_de"),
+ GTK_RESPONSE_NO, NULL);
+ gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar),
+ GTK_MESSAGE_QUESTION);
+ image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION,
+ GTK_ICON_SIZE_DIALOG);
+ label = gtk_label_new (NULL);
+
+ /* The newline character is currently necessary due to a problem
+ * with the automatic line break. */
+ text = g_strdup_printf (_("The image \"%s\" has been modified by an external application."
+ "\nWould you like to reload it?"), eom_image_get_caption (img));
+ markup = g_markup_printf_escaped ("<b>%s</b>", text);
+ gtk_label_set_markup (GTK_LABEL (label), markup);
+ g_free (text);
+ g_free (markup);
+
+ hbox = gtk_hbox_new (FALSE, 8);
+ gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ gtk_box_pack_start (GTK_BOX (gtk_info_bar_get_content_area (GTK_INFO_BAR (info_bar))), hbox, TRUE, TRUE, 0);
+ gtk_widget_show_all (hbox);
+ gtk_widget_show (info_bar);
+
+ eom_window_set_message_area (window, info_bar);
+ g_signal_connect (info_bar, "response",
+ G_CALLBACK (file_changed_info_bar_response), window);
+}
+
+static void
+eom_window_display_image (EomWindow *window, EomImage *image)
+{
+ EomWindowPrivate *priv;
+ GFile *file;
+
+ g_return_if_fail (EOM_IS_WINDOW (window));
+ g_return_if_fail (EOM_IS_IMAGE (image));
+
+ eom_debug (DEBUG_WINDOW);
+
+ g_assert (eom_image_has_data (image, EOM_IMAGE_DATA_ALL));
+
+ priv = window->priv;
+
+ if (image != NULL) {
+ g_signal_connect (image,
+ "thumbnail_changed",
+ G_CALLBACK (image_thumb_changed_cb),
+ window);
+ g_signal_connect (image, "file-changed",
+ G_CALLBACK (image_file_changed_cb),
+ window);
+
+ image_thumb_changed_cb (image, window);
+ }
+
+ priv->needs_reload_confirmation = TRUE;
+
+ eom_scroll_view_set_image (EOM_SCROLL_VIEW (priv->view), image);
+
+ gtk_window_set_title (GTK_WINDOW (window), eom_image_get_caption (image));
+
+ update_status_bar (window);
+
+ file = eom_image_get_file (image);
+ g_idle_add_full (G_PRIORITY_LOW,
+ (GSourceFunc) add_file_to_recent_files,
+ file,
+ (GDestroyNotify) g_object_unref);
+
+ eom_window_update_openwith_menu (window, image);
+}
+
+static void
+open_with_launch_application_cb (GtkAction *action, gpointer data) {
+ EomImage *image;
+ GAppInfo *app;
+ GFile *file;
+ GList *files = NULL;
+
+ image = EOM_IMAGE (data);
+ file = eom_image_get_file (image);
+
+ app = g_object_get_data (G_OBJECT (action), "app");
+ files = g_list_append (files, file);
+ g_app_info_launch (app,
+ files,
+ NULL, NULL);
+
+ g_object_unref (file);
+ g_list_free (files);
+}
+
+static void
+eom_window_update_openwith_menu (EomWindow *window, EomImage *image)
+{
+ GFile *file;
+ GFileInfo *file_info;
+ GList *iter;
+ gchar *label, *tip;
+ const gchar *mime_type;
+ GtkAction *action;
+ EomWindowPrivate *priv;
+ GList *apps;
+ guint action_id = 0;
+ GIcon *app_icon;
+ char *path;
+ GtkWidget *menuitem;
+
+ priv = window->priv;
+
+ file = eom_image_get_file (image);
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ 0, NULL, NULL);
+
+ if (file_info == NULL)
+ return;
+ else {
+ mime_type = g_file_info_get_content_type (file_info);
+ }
+
+ if (priv->open_with_menu_id != 0) {
+ gtk_ui_manager_remove_ui (priv->ui_mgr, priv->open_with_menu_id);
+ priv->open_with_menu_id = 0;
+ }
+
+ if (priv->actions_open_with != NULL) {
+ gtk_ui_manager_remove_action_group (priv->ui_mgr, priv->actions_open_with);
+ priv->actions_open_with = NULL;
+ }
+
+ if (mime_type == NULL) {
+ g_object_unref (file_info);
+ return;
+ }
+
+ apps = g_app_info_get_all_for_type (mime_type);
+
+ g_object_unref (file_info);
+
+ if (!apps)
+ return;
+
+ priv->actions_open_with = gtk_action_group_new ("OpenWithActions");
+ gtk_ui_manager_insert_action_group (priv->ui_mgr, priv->actions_open_with, -1);
+
+ priv->open_with_menu_id = gtk_ui_manager_new_merge_id (priv->ui_mgr);
+
+ for (iter = apps; iter; iter = iter->next) {
+ GAppInfo *app = iter->data;
+ gchar name[64];
+
+ /* Do not include eom itself */
+ if (g_ascii_strcasecmp (g_app_info_get_executable (app),
+ g_get_prgname ()) == 0) {
+ g_object_unref (app);
+ continue;
+ }
+
+ g_snprintf (name, sizeof (name), "OpenWith%u", action_id++);
+
+ label = g_strdup (g_app_info_get_name (app));
+ tip = g_strdup_printf (_("Use \"%s\" to open the selected image"), g_app_info_get_name (app));
+
+ action = gtk_action_new (name, label, tip, NULL);
+
+ app_icon = g_app_info_get_icon (app);
+ if (G_LIKELY (app_icon != NULL)) {
+ g_object_ref (app_icon);
+ gtk_action_set_gicon (action, app_icon);
+ g_object_unref (app_icon);
+ }
+
+ g_free (label);
+ g_free (tip);
+
+ g_object_set_data_full (G_OBJECT (action), "app", app,
+ (GDestroyNotify) g_object_unref);
+
+ g_signal_connect (action,
+ "activate",
+ G_CALLBACK (open_with_launch_application_cb),
+ image);
+
+ gtk_action_group_add_action (priv->actions_open_with, action);
+ g_object_unref (action);
+
+ gtk_ui_manager_add_ui (priv->ui_mgr,
+ priv->open_with_menu_id,
+ "/MainMenu/Image/ImageOpenWith/Applications Placeholder",
+ name,
+ name,
+ GTK_UI_MANAGER_MENUITEM,
+ FALSE);
+
+ gtk_ui_manager_add_ui (priv->ui_mgr,
+ priv->open_with_menu_id,
+ "/ThumbnailPopup/ImageOpenWith/Applications Placeholder",
+ name,
+ name,
+ GTK_UI_MANAGER_MENUITEM,
+ FALSE);
+ gtk_ui_manager_add_ui (priv->ui_mgr,
+ priv->open_with_menu_id,
+ "/ViewPopup/ImageOpenWith/Applications Placeholder",
+ name,
+ name,
+ GTK_UI_MANAGER_MENUITEM,
+ FALSE);
+
+ path = g_strdup_printf ("/MainMenu/Image/ImageOpenWith/Applications Placeholder/%s", name);
+
+ menuitem = gtk_ui_manager_get_widget (priv->ui_mgr, path);
+
+ /* Only force displaying the icon if it is an application icon */
+ gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), app_icon != NULL);
+
+ g_free (path);
+
+ path = g_strdup_printf ("/ThumbnailPopup/ImageOpenWith/Applications Placeholder/%s", name);
+
+ menuitem = gtk_ui_manager_get_widget (priv->ui_mgr, path);
+
+ /* Only force displaying the icon if it is an application icon */
+ gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), app_icon != NULL);
+
+ g_free (path);
+
+ path = g_strdup_printf ("/ViewPopup/ImageOpenWith/Applications Placeholder/%s", name);
+
+ menuitem = gtk_ui_manager_get_widget (priv->ui_mgr, path);
+
+ /* Only force displaying the icon if it is an application icon */
+ gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), app_icon != NULL);
+
+ g_free (path);
+ }
+
+ g_list_free (apps);
+}
+
+static void
+eom_window_clear_load_job (EomWindow *window)
+{
+ EomWindowPrivate *priv = window->priv;
+
+ if (priv->load_job != NULL) {
+ if (!priv->load_job->finished)
+ eom_job_queue_remove_job (priv->load_job);
+
+ g_signal_handlers_disconnect_by_func (priv->load_job,
+ eom_job_progress_cb,
+ window);
+
+ g_signal_handlers_disconnect_by_func (priv->load_job,
+ eom_job_load_cb,
+ window);
+
+ eom_image_cancel_load (EOM_JOB_LOAD (priv->load_job)->image);
+
+ g_object_unref (priv->load_job);
+ priv->load_job = NULL;
+
+ /* Hide statusbar */
+ eom_statusbar_set_progress (EOM_STATUSBAR (priv->statusbar), 0);
+ }
+}
+
+static void
+eom_job_progress_cb (EomJobLoad *job, float progress, gpointer user_data)
+{
+ EomWindow *window;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ window = EOM_WINDOW (user_data);
+
+ eom_statusbar_set_progress (EOM_STATUSBAR (window->priv->statusbar),
+ progress);
+}
+
+static void
+eom_job_save_progress_cb (EomJobSave *job, float progress, gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ EomWindow *window;
+
+ static EomImage *image = NULL;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ window = EOM_WINDOW (user_data);
+ priv = window->priv;
+
+ eom_statusbar_set_progress (EOM_STATUSBAR (priv->statusbar),
+ progress);
+
+ if (image != job->current_image) {
+ gchar *str_image, *status_message;
+ guint n_images;
+
+ image = job->current_image;
+
+ n_images = g_list_length (job->images);
+
+ str_image = eom_image_get_uri_for_display (image);
+
+ /* Translators: This string is displayed in the statusbar
+ * while saving images. The tokens are from left to right:
+ * - the original filename
+ * - the current image's position in the queue
+ * - the total number of images queued for saving */
+ status_message = g_strdup_printf (_("Saving image \"%s\" (%u/%u)"),
+ str_image,
+ job->current_pos + 1,
+ n_images);
+ g_free (str_image);
+
+ gtk_statusbar_pop (GTK_STATUSBAR (priv->statusbar),
+ priv->image_info_message_cid);
+
+ gtk_statusbar_push (GTK_STATUSBAR (priv->statusbar),
+ priv->image_info_message_cid,
+ status_message);
+
+ g_free (status_message);
+ }
+
+ if (progress == 1.0)
+ image = NULL;
+}
+
+static void
+eom_window_obtain_desired_size (EomImage *image,
+ gint width,
+ gint height,
+ EomWindow *window)
+{
+ GdkScreen *screen;
+ GdkRectangle monitor;
+ GtkAllocation allocation;
+ gint final_width, final_height;
+ gint screen_width, screen_height;
+ gint window_width, window_height;
+ gint img_width, img_height;
+ gint view_width, view_height;
+ gint deco_width, deco_height;
+
+ update_action_groups_state (window);
+
+ img_width = width;
+ img_height = height;
+
+#if GTK_CHECK_VERSION (2, 20, 0)
+ if (!gtk_widget_get_realized (window->priv->view)) {
+#else
+ if (!GTK_WIDGET_REALIZED (window->priv->view)) {
+#endif
+ gtk_widget_realize (window->priv->view);
+ }
+
+ gtk_widget_get_allocation (window->priv->view, &allocation);
+ view_width = allocation.width;
+ view_height = allocation.height;
+
+#if GTK_CHECK_VERSION (2, 20, 0)
+ if (!gtk_widget_get_realized (GTK_WIDGET (window))) {
+#else
+ if (!GTK_WIDGET_REALIZED (GTK_WIDGET (window))) {
+#endif
+ gtk_widget_realize (GTK_WIDGET (window));
+ }
+
+ gtk_widget_get_allocation (GTK_WIDGET (window), &allocation);
+ window_width = allocation.width;
+ window_height = allocation.height;
+
+ screen = gtk_window_get_screen (GTK_WINDOW (window));
+
+ gdk_screen_get_monitor_geometry (screen,
+ gdk_screen_get_monitor_at_window (screen,
+ gtk_widget_get_window (GTK_WIDGET (window))),
+ &monitor);
+
+ screen_width = monitor.width;
+ screen_height = monitor.height;
+
+ deco_width = window_width - view_width;
+ deco_height = window_height - view_height;
+
+ if (img_width > 0 && img_height > 0) {
+ if ((img_width + deco_width > screen_width) ||
+ (img_height + deco_height > screen_height))
+ {
+ double factor;
+
+ if (img_width > img_height) {
+ factor = (screen_width * 0.75 - deco_width) / (double) img_width;
+ } else {
+ factor = (screen_height * 0.75 - deco_height) / (double) img_height;
+ }
+
+ img_width = img_width * factor;
+ img_height = img_height * factor;
+ }
+ }
+
+ final_width = MAX (EOM_WINDOW_MIN_WIDTH, img_width + deco_width);
+ final_height = MAX (EOM_WINDOW_MIN_HEIGHT, img_height + deco_height);
+
+ eom_debug_message (DEBUG_WINDOW, "Setting window size: %d x %d", final_width, final_height);
+
+ gtk_window_set_default_size (GTK_WINDOW (window), final_width, final_height);
+
+ g_signal_emit (window, signals[SIGNAL_PREPARED], 0);
+}
+
+static void
+eom_window_error_message_area_response (GtkInfoBar *message_area,
+ gint response_id,
+ EomWindow *window)
+{
+ if (response_id != GTK_RESPONSE_OK) {
+ eom_window_set_message_area (window, NULL);
+
+ return;
+ }
+
+ /* Trigger loading for current image again */
+ eom_thumb_view_select_single (EOM_THUMB_VIEW (window->priv->thumbview),
+ EOM_THUMB_VIEW_SELECT_CURRENT);
+}
+
+static void
+eom_job_load_cb (EomJobLoad *job, gpointer data)
+{
+ EomWindow *window;
+ EomWindowPrivate *priv;
+ GtkAction *action_undo, *action_save;
+
+ g_return_if_fail (EOM_IS_WINDOW (data));
+
+ eom_debug (DEBUG_WINDOW);
+
+ window = EOM_WINDOW (data);
+ priv = window->priv;
+
+ eom_statusbar_set_progress (EOM_STATUSBAR (priv->statusbar), 0.0);
+
+ gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar),
+ priv->image_info_message_cid);
+
+ if (priv->image != NULL) {
+ g_signal_handlers_disconnect_by_func (priv->image,
+ image_thumb_changed_cb,
+ window);
+ g_signal_handlers_disconnect_by_func (priv->image,
+ image_file_changed_cb,
+ window);
+
+ g_object_unref (priv->image);
+ }
+
+ priv->image = g_object_ref (job->image);
+
+ if (EOM_JOB (job)->error == NULL) {
+#ifdef HAVE_LCMS
+ eom_image_apply_display_profile (job->image,
+ priv->display_profile);
+#endif
+
+ gtk_action_group_set_sensitive (priv->actions_image, TRUE);
+
+ eom_window_display_image (window, job->image);
+ } else {
+ GtkWidget *message_area;
+
+ message_area = eom_image_load_error_message_area_new (
+ eom_image_get_caption (job->image),
+ EOM_JOB (job)->error);
+
+ g_signal_connect (message_area,
+ "response",
+ G_CALLBACK (eom_window_error_message_area_response),
+ window);
+
+ gtk_window_set_icon (GTK_WINDOW (window), NULL);
+ gtk_window_set_title (GTK_WINDOW (window),
+ eom_image_get_caption (job->image));
+
+ eom_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);
+
+ eom_scroll_view_set_image (EOM_SCROLL_VIEW (priv->view), NULL);
+
+ if (window->priv->status == EOM_WINDOW_STATUS_INIT) {
+ update_action_groups_state (window);
+
+ g_signal_emit (window, signals[SIGNAL_PREPARED], 0);
+ }
+
+ gtk_action_group_set_sensitive (priv->actions_image, FALSE);
+ }
+
+ eom_window_clear_load_job (window);
+
+ if (window->priv->status == EOM_WINDOW_STATUS_INIT) {
+ window->priv->status = EOM_WINDOW_STATUS_NORMAL;
+
+ g_signal_handlers_disconnect_by_func
+ (job->image,
+ G_CALLBACK (eom_window_obtain_desired_size),
+ window);
+ }
+
+ action_save = gtk_action_group_get_action (priv->actions_image, "ImageSave");
+ action_undo = gtk_action_group_get_action (priv->actions_image, "EditUndo");
+
+ /* Set Save and Undo sensitive according to image state.
+ * Respect lockdown in case of Save.*/
+ gtk_action_set_sensitive (action_save, (!priv->save_disabled && eom_image_is_modified (job->image)));
+ gtk_action_set_sensitive (action_undo, eom_image_is_modified (job->image));
+
+ g_object_unref (job->image);
+}
+
+static void
+eom_window_clear_transform_job (EomWindow *window)
+{
+ EomWindowPrivate *priv = window->priv;
+
+ if (priv->transform_job != NULL) {
+ if (!priv->transform_job->finished)
+ eom_job_queue_remove_job (priv->transform_job);
+
+ g_signal_handlers_disconnect_by_func (priv->transform_job,
+ eom_job_transform_cb,
+ window);
+ g_object_unref (priv->transform_job);
+ priv->transform_job = NULL;
+ }
+}
+
+static void
+eom_job_transform_cb (EomJobTransform *job, gpointer data)
+{
+ EomWindow *window;
+ GtkAction *action_undo, *action_save;
+ EomImage *image;
+
+ g_return_if_fail (EOM_IS_WINDOW (data));
+
+ window = EOM_WINDOW (data);
+
+ eom_window_clear_transform_job (window);
+
+ action_undo =
+ gtk_action_group_get_action (window->priv->actions_image, "EditUndo");
+ action_save =
+ gtk_action_group_get_action (window->priv->actions_image, "ImageSave");
+
+ image = eom_window_get_image (window);
+
+ gtk_action_set_sensitive (action_undo, eom_image_is_modified (image));
+
+ if (!window->priv->save_disabled)
+ {
+ gtk_action_set_sensitive (action_save, eom_image_is_modified (image));
+ }
+}
+
+static void
+apply_transformation (EomWindow *window, EomTransform *trans)
+{
+ EomWindowPrivate *priv;
+ GList *images;
+
+ g_return_if_fail (EOM_IS_WINDOW (window));
+
+ priv = window->priv;
+
+ images = eom_thumb_view_get_selected_images (EOM_THUMB_VIEW (priv->thumbview));
+
+ eom_window_clear_transform_job (window);
+
+ priv->transform_job = eom_job_transform_new (images, trans);
+
+ g_signal_connect (priv->transform_job,
+ "finished",
+ G_CALLBACK (eom_job_transform_cb),
+ window);
+
+ g_signal_connect (priv->transform_job,
+ "progress",
+ G_CALLBACK (eom_job_progress_cb),
+ window);
+
+ eom_job_queue_add_job (priv->transform_job);
+}
+
+static void
+handle_image_selection_changed_cb (EomThumbView *thumbview, EomWindow *window)
+{
+ EomWindowPrivate *priv;
+ EomImage *image;
+ gchar *status_message;
+ gchar *str_image;
+
+ priv = window->priv;
+
+ if (eom_thumb_view_get_n_selected (EOM_THUMB_VIEW (priv->thumbview)) == 0)
+ return;
+
+ update_selection_ui_visibility (window);
+
+ image = eom_thumb_view_get_first_selected_image (EOM_THUMB_VIEW (priv->thumbview));
+
+ g_assert (EOM_IS_IMAGE (image));
+
+ eom_window_clear_load_job (window);
+
+ eom_window_set_message_area (window, NULL);
+
+ gtk_statusbar_pop (GTK_STATUSBAR (priv->statusbar),
+ priv->image_info_message_cid);
+
+ if (image == priv->image) {
+ update_status_bar (window);
+ return;
+ }
+
+ if (eom_image_has_data (image, EOM_IMAGE_DATA_ALL)) {
+ eom_window_display_image (window, image);
+ return;
+ }
+
+ if (priv->status == EOM_WINDOW_STATUS_INIT) {
+ g_signal_connect (image,
+ "size-prepared",
+ G_CALLBACK (eom_window_obtain_desired_size),
+ window);
+ }
+
+ priv->load_job = eom_job_load_new (image, EOM_IMAGE_DATA_ALL);
+
+ g_signal_connect (priv->load_job,
+ "finished",
+ G_CALLBACK (eom_job_load_cb),
+ window);
+
+ g_signal_connect (priv->load_job,
+ "progress",
+ G_CALLBACK (eom_job_progress_cb),
+ window);
+
+ eom_job_queue_add_job (priv->load_job);
+
+ str_image = eom_image_get_uri_for_display (image);
+
+ status_message = g_strdup_printf (_("Opening image \"%s\""),
+ str_image);
+
+ g_free (str_image);
+
+ gtk_statusbar_push (GTK_STATUSBAR (priv->statusbar),
+ priv->image_info_message_cid, status_message);
+
+ g_free (status_message);
+}
+
+static void
+view_zoom_changed_cb (GtkWidget *widget, double zoom, gpointer user_data)
+{
+ EomWindow *window;
+ GtkAction *action_zoom_in;
+ GtkAction *action_zoom_out;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ window = EOM_WINDOW (user_data);
+
+ update_status_bar (window);
+
+ action_zoom_in =
+ gtk_action_group_get_action (window->priv->actions_image,
+ "ViewZoomIn");
+
+ action_zoom_out =
+ gtk_action_group_get_action (window->priv->actions_image,
+ "ViewZoomOut");
+
+ gtk_action_set_sensitive (action_zoom_in,
+ !eom_scroll_view_get_zoom_is_max (EOM_SCROLL_VIEW (window->priv->view)));
+ gtk_action_set_sensitive (action_zoom_out,
+ !eom_scroll_view_get_zoom_is_min (EOM_SCROLL_VIEW (window->priv->view)));
+}
+
+static void
+eom_window_open_recent_cb (GtkAction *action, EomWindow *window)
+{
+ GtkRecentInfo *info;
+ const gchar *uri;
+ GSList *list = NULL;
+
+ info = g_object_get_data (G_OBJECT (action), "gtk-recent-info");
+ g_return_if_fail (info != NULL);
+
+ uri = gtk_recent_info_get_uri (info);
+ list = g_slist_prepend (list, g_strdup (uri));
+
+ eom_application_open_uri_list (EOM_APP,
+ list,
+ GDK_CURRENT_TIME,
+ 0,
+ NULL);
+
+ g_slist_foreach (list, (GFunc) g_free, NULL);
+ g_slist_free (list);
+}
+
+static void
+file_open_dialog_response_cb (GtkWidget *chooser,
+ gint response_id,
+ EomWindow *ev_window)
+{
+ if (response_id == GTK_RESPONSE_OK) {
+ GSList *uris;
+
+ uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (chooser));
+
+ eom_application_open_uri_list (EOM_APP,
+ uris,
+ GDK_CURRENT_TIME,
+ 0,
+ NULL);
+
+ g_slist_foreach (uris, (GFunc) g_free, NULL);
+ g_slist_free (uris);
+ }
+
+ gtk_widget_destroy (chooser);
+}
+
+static void
+eom_window_update_fullscreen_action (EomWindow *window)
+{
+ GtkAction *action;
+
+ action = gtk_action_group_get_action (window->priv->actions_image,
+ "ViewFullscreen");
+
+ g_signal_handlers_block_by_func
+ (action, G_CALLBACK (eom_window_cmd_fullscreen), window);
+
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
+ window->priv->mode == EOM_WINDOW_MODE_FULLSCREEN);
+
+ g_signal_handlers_unblock_by_func
+ (action, G_CALLBACK (eom_window_cmd_fullscreen), window);
+}
+
+static void
+eom_window_update_slideshow_action (EomWindow *window)
+{
+ GtkAction *action;
+
+ action = gtk_action_group_get_action (window->priv->actions_collection,
+ "ViewSlideshow");
+
+ g_signal_handlers_block_by_func
+ (action, G_CALLBACK (eom_window_cmd_slideshow), window);
+
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
+ window->priv->mode == EOM_WINDOW_MODE_SLIDESHOW);
+
+ g_signal_handlers_unblock_by_func
+ (action, G_CALLBACK (eom_window_cmd_slideshow), window);
+}
+
+static void
+eom_window_update_pause_slideshow_action (EomWindow *window)
+{
+ GtkAction *action;
+
+ action = gtk_action_group_get_action (window->priv->actions_image,
+ "PauseSlideshow");
+
+ g_signal_handlers_block_by_func
+ (action, G_CALLBACK (eom_window_cmd_pause_slideshow), window);
+
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
+ window->priv->mode != EOM_WINDOW_MODE_SLIDESHOW);
+
+ g_signal_handlers_unblock_by_func
+ (action, G_CALLBACK (eom_window_cmd_pause_slideshow), window);
+}
+
+static void
+eom_window_update_fullscreen_popup (EomWindow *window)
+{
+ GtkWidget *popup = window->priv->fullscreen_popup;
+ GdkRectangle screen_rect;
+ GdkScreen *screen;
+
+ g_return_if_fail (popup != NULL);
+
+ if (gtk_widget_get_window (GTK_WIDGET (window)) == NULL) return;
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (window));
+
+ gdk_screen_get_monitor_geometry (screen,
+ gdk_screen_get_monitor_at_window
+ (screen,
+ gtk_widget_get_window (GTK_WIDGET (window))),
+ &screen_rect);
+
+ gtk_widget_set_size_request (popup,
+ screen_rect.width,
+ -1);
+
+ gtk_window_move (GTK_WINDOW (popup), screen_rect.x, screen_rect.y);
+}
+
+static void
+screen_size_changed_cb (GdkScreen *screen, EomWindow *window)
+{
+ eom_window_update_fullscreen_popup (window);
+}
+
+static void
+fullscreen_popup_size_request_cb (GtkWidget *popup,
+ GtkRequisition *req,
+ EomWindow *window)
+{
+ eom_window_update_fullscreen_popup (window);
+}
+
+static gboolean
+fullscreen_timeout_cb (gpointer data)
+{
+ EomWindow *window = EOM_WINDOW (data);
+
+ gtk_widget_hide_all (window->priv->fullscreen_popup);
+
+ eom_scroll_view_hide_cursor (EOM_SCROLL_VIEW (window->priv->view));
+
+ fullscreen_clear_timeout (window);
+
+ return FALSE;
+}
+
+static gboolean
+slideshow_is_loop_end (EomWindow *window)
+{
+ EomWindowPrivate *priv = window->priv;
+ EomImage *image = NULL;
+ gint pos;
+
+ image = eom_thumb_view_get_first_selected_image (EOM_THUMB_VIEW (priv->thumbview));
+
+ pos = eom_list_store_get_pos_by_image (priv->store, image);
+
+ return (pos == (eom_list_store_length (priv->store) - 1));
+}
+
+static gboolean
+slideshow_switch_cb (gpointer data)
+{
+ EomWindow *window = EOM_WINDOW (data);
+ EomWindowPrivate *priv = window->priv;
+
+ eom_debug (DEBUG_WINDOW);
+
+ if (!priv->slideshow_loop && slideshow_is_loop_end (window)) {
+ eom_window_stop_fullscreen (window, TRUE);
+ return FALSE;
+ }
+
+ eom_thumb_view_select_single (EOM_THUMB_VIEW (priv->thumbview),
+ EOM_THUMB_VIEW_SELECT_RIGHT);
+
+ return TRUE;
+}
+
+static void
+fullscreen_clear_timeout (EomWindow *window)
+{
+ eom_debug (DEBUG_WINDOW);
+
+ if (window->priv->fullscreen_timeout_source != NULL) {
+ g_source_unref (window->priv->fullscreen_timeout_source);
+ g_source_destroy (window->priv->fullscreen_timeout_source);
+ }
+
+ window->priv->fullscreen_timeout_source = NULL;
+}
+
+static void
+fullscreen_set_timeout (EomWindow *window)
+{
+ GSource *source;
+
+ eom_debug (DEBUG_WINDOW);
+
+ fullscreen_clear_timeout (window);
+
+ source = g_timeout_source_new (EOM_WINDOW_FULLSCREEN_TIMEOUT);
+ g_source_set_callback (source, fullscreen_timeout_cb, window, NULL);
+
+ g_source_attach (source, NULL);
+
+ window->priv->fullscreen_timeout_source = source;
+
+ eom_scroll_view_show_cursor (EOM_SCROLL_VIEW (window->priv->view));
+}
+
+static void
+slideshow_clear_timeout (EomWindow *window)
+{
+ eom_debug (DEBUG_WINDOW);
+
+ if (window->priv->slideshow_switch_source != NULL) {
+ g_source_unref (window->priv->slideshow_switch_source);
+ g_source_destroy (window->priv->slideshow_switch_source);
+ }
+
+ window->priv->slideshow_switch_source = NULL;
+}
+
+static void
+slideshow_set_timeout (EomWindow *window)
+{
+ GSource *source;
+
+ eom_debug (DEBUG_WINDOW);
+
+ slideshow_clear_timeout (window);
+
+ if (window->priv->slideshow_switch_timeout <= 0)
+ return;
+
+ source = g_timeout_source_new (window->priv->slideshow_switch_timeout * 1000);
+ g_source_set_callback (source, slideshow_switch_cb, window, NULL);
+
+ g_source_attach (source, NULL);
+
+ window->priv->slideshow_switch_source = source;
+}
+
+static void
+show_fullscreen_popup (EomWindow *window)
+{
+ eom_debug (DEBUG_WINDOW);
+
+ if (!gtk_widget_get_visible (window->priv->fullscreen_popup)) {
+ gtk_widget_show_all (GTK_WIDGET (window->priv->fullscreen_popup));
+ }
+
+ fullscreen_set_timeout (window);
+}
+
+static gboolean
+fullscreen_motion_notify_cb (GtkWidget *widget,
+ GdkEventMotion *event,
+ gpointer user_data)
+{
+ EomWindow *window = EOM_WINDOW (user_data);
+
+ eom_debug (DEBUG_WINDOW);
+
+ if (event->y < EOM_WINDOW_FULLSCREEN_POPUP_THRESHOLD) {
+ show_fullscreen_popup (window);
+ } else {
+ fullscreen_set_timeout (window);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+fullscreen_leave_notify_cb (GtkWidget *widget,
+ GdkEventCrossing *event,
+ gpointer user_data)
+{
+ EomWindow *window = EOM_WINDOW (user_data);
+
+ eom_debug (DEBUG_WINDOW);
+
+ fullscreen_clear_timeout (window);
+
+ return FALSE;
+}
+
+static void
+exit_fullscreen_button_clicked_cb (GtkWidget *button, EomWindow *window)
+{
+ GtkAction *action;
+
+ eom_debug (DEBUG_WINDOW);
+
+ if (window->priv->mode == EOM_WINDOW_MODE_SLIDESHOW) {
+ action = gtk_action_group_get_action (window->priv->actions_collection,
+ "ViewSlideshow");
+ } else {
+ action = gtk_action_group_get_action (window->priv->actions_image,
+ "ViewFullscreen");
+ }
+ g_return_if_fail (action != NULL);
+
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
+}
+
+static GtkWidget *
+eom_window_get_exit_fullscreen_button (EomWindow *window)
+{
+ GtkWidget *button;
+
+ button = gtk_button_new_from_stock (GTK_STOCK_LEAVE_FULLSCREEN);
+
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (exit_fullscreen_button_clicked_cb),
+ window);
+
+ return button;
+}
+
+static GtkWidget *
+eom_window_create_fullscreen_popup (EomWindow *window)
+{
+ GtkWidget *popup;
+ GtkWidget *hbox;
+ GtkWidget *button;
+ GtkWidget *toolbar;
+ GdkScreen *screen;
+
+ eom_debug (DEBUG_WINDOW);
+
+ popup = gtk_window_new (GTK_WINDOW_POPUP);
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (popup), hbox);
+
+ toolbar = gtk_ui_manager_get_widget (window->priv->ui_mgr,
+ "/FullscreenToolbar");
+ g_assert (GTK_IS_WIDGET (toolbar));
+ gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
+ gtk_box_pack_start (GTK_BOX (hbox), toolbar, TRUE, TRUE, 0);
+
+ button = eom_window_get_exit_fullscreen_button (window);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+ gtk_window_set_resizable (GTK_WINDOW (popup), FALSE);
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (window));
+
+ g_signal_connect_object (screen, "size-changed",
+ G_CALLBACK (screen_size_changed_cb),
+ window, 0);
+
+ g_signal_connect_object (popup, "size_request",
+ G_CALLBACK (fullscreen_popup_size_request_cb),
+ window, 0);
+
+ g_signal_connect (popup,
+ "enter-notify-event",
+ G_CALLBACK (fullscreen_leave_notify_cb),
+ window);
+
+ gtk_window_set_screen (GTK_WINDOW (popup), screen);
+
+ return popup;
+}
+
+static void
+update_ui_visibility (EomWindow *window)
+{
+ EomWindowPrivate *priv;
+
+ GtkAction *action;
+ GtkWidget *menubar;
+ GError *error = NULL;
+
+ gboolean fullscreen_mode, visible;
+
+ g_return_if_fail (EOM_IS_WINDOW (window));
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = window->priv;
+
+ fullscreen_mode = priv->mode == EOM_WINDOW_MODE_FULLSCREEN ||
+ priv->mode == EOM_WINDOW_MODE_SLIDESHOW;
+
+ menubar = gtk_ui_manager_get_widget (priv->ui_mgr, "/MainMenu");
+ g_assert (GTK_IS_WIDGET (menubar));
+
+ visible = mateconf_client_get_bool (priv->client, EOM_CONF_UI_TOOLBAR, &error);
+ visible = visible && !fullscreen_mode;
+ if (error) {
+ g_error_free (error);
+ error = NULL;
+ visible = !fullscreen_mode;
+ }
+ action = gtk_ui_manager_get_action (priv->ui_mgr, "/MainMenu/View/ToolbarToggle");
+ g_assert (action != NULL);
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
+ g_object_set (G_OBJECT (priv->toolbar), "visible", visible, NULL);
+
+ visible = mateconf_client_get_bool (priv->client, EOM_CONF_UI_STATUSBAR, &error);
+ visible = visible && !fullscreen_mode;
+ if (error) {
+ g_error_free (error);
+ error = NULL;
+ visible = !fullscreen_mode;
+ }
+ action = gtk_ui_manager_get_action (priv->ui_mgr, "/MainMenu/View/StatusbarToggle");
+ g_assert (action != NULL);
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
+ g_object_set (G_OBJECT (priv->statusbar), "visible", visible, NULL);
+
+ if (priv->status != EOM_WINDOW_STATUS_INIT) {
+ visible = mateconf_client_get_bool (priv->client, EOM_CONF_UI_IMAGE_COLLECTION, NULL);
+ visible = visible && priv->mode != EOM_WINDOW_MODE_SLIDESHOW;
+ action = gtk_ui_manager_get_action (priv->ui_mgr, "/MainMenu/View/ImageCollectionToggle");
+ g_assert (action != NULL);
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
+ if (visible) {
+ gtk_widget_show (priv->nav);
+ } else {
+ gtk_widget_hide (priv->nav);
+ }
+ }
+
+ visible = mateconf_client_get_bool (priv->client, EOM_CONF_UI_SIDEBAR, NULL);
+ visible = visible && !fullscreen_mode;
+ action = gtk_ui_manager_get_action (priv->ui_mgr, "/MainMenu/View/SidebarToggle");
+ g_assert (action != NULL);
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
+ if (visible) {
+ gtk_widget_show (priv->sidebar);
+ } else {
+ gtk_widget_hide (priv->sidebar);
+ }
+
+ if (priv->fullscreen_popup != NULL) {
+ gtk_widget_hide_all (priv->fullscreen_popup);
+ }
+}
+
+static void
+eom_window_run_fullscreen (EomWindow *window, gboolean slideshow)
+{
+ EomWindowPrivate *priv;
+ GtkWidget *menubar;
+ gboolean upscale;
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = window->priv;
+
+ if (slideshow) {
+ priv->mode = EOM_WINDOW_MODE_SLIDESHOW;
+ } else {
+ /* Stop the timer if we come from slideshowing */
+ if (priv->mode == EOM_WINDOW_MODE_SLIDESHOW)
+ slideshow_clear_timeout (window);
+
+ priv->mode = EOM_WINDOW_MODE_FULLSCREEN;
+ }
+
+ if (window->priv->fullscreen_popup == NULL)
+ priv->fullscreen_popup
+ = eom_window_create_fullscreen_popup (window);
+
+ update_ui_visibility (window);
+
+ menubar = gtk_ui_manager_get_widget (priv->ui_mgr, "/MainMenu");
+ g_assert (GTK_IS_WIDGET (menubar));
+ gtk_widget_hide (menubar);
+
+ g_signal_connect (priv->view,
+ "motion-notify-event",
+ G_CALLBACK (fullscreen_motion_notify_cb),
+ window);
+
+ g_signal_connect (priv->view,
+ "leave-notify-event",
+ G_CALLBACK (fullscreen_leave_notify_cb),
+ window);
+
+ g_signal_connect (priv->thumbview,
+ "motion-notify-event",
+ G_CALLBACK (fullscreen_motion_notify_cb),
+ window);
+
+ g_signal_connect (priv->thumbview,
+ "leave-notify-event",
+ G_CALLBACK (fullscreen_leave_notify_cb),
+ window);
+
+ fullscreen_set_timeout (window);
+
+ if (slideshow) {
+ priv->slideshow_loop =
+ mateconf_client_get_bool (priv->client,
+ EOM_CONF_FULLSCREEN_LOOP,
+ NULL);
+
+ priv->slideshow_switch_timeout =
+ mateconf_client_get_int (priv->client,
+ EOM_CONF_FULLSCREEN_SECONDS,
+ NULL);
+
+ slideshow_set_timeout (window);
+ }
+
+ upscale = mateconf_client_get_bool (priv->client,
+ EOM_CONF_FULLSCREEN_UPSCALE,
+ NULL);
+
+ eom_scroll_view_set_zoom_upscale (EOM_SCROLL_VIEW (priv->view),
+ upscale);
+
+ gtk_widget_grab_focus (priv->view);
+
+ eom_scroll_view_override_bg_color (EOM_SCROLL_VIEW (window->priv->view),
+ &(gtk_widget_get_style (GTK_WIDGET (window))->black));
+
+ {
+ GtkStyle *style;
+
+ style = gtk_style_copy (gtk_widget_get_style (gtk_widget_get_parent (priv->view)));
+
+ style->xthickness = 0;
+ style->ythickness = 0;
+
+ gtk_widget_set_style (gtk_widget_get_parent (priv->view),
+ style);
+
+ g_object_unref (style);
+ }
+
+ gtk_window_fullscreen (GTK_WINDOW (window));
+ eom_window_update_fullscreen_popup (window);
+
+#ifdef HAVE_DBUS
+ eom_application_screensaver_disable (EOM_APP);
+#endif
+
+ /* Update both actions as we could've already been in one those modes */
+ eom_window_update_slideshow_action (window);
+ eom_window_update_fullscreen_action (window);
+ eom_window_update_pause_slideshow_action (window);
+}
+
+static void
+eom_window_stop_fullscreen (EomWindow *window, gboolean slideshow)
+{
+ EomWindowPrivate *priv;
+ GtkWidget *menubar;
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = window->priv;
+
+ if (priv->mode != EOM_WINDOW_MODE_SLIDESHOW &&
+ priv->mode != EOM_WINDOW_MODE_FULLSCREEN) return;
+
+ priv->mode = EOM_WINDOW_MODE_NORMAL;
+
+ fullscreen_clear_timeout (window);
+
+ if (slideshow) {
+ slideshow_clear_timeout (window);
+ }
+
+ g_signal_handlers_disconnect_by_func (priv->view,
+ (gpointer) fullscreen_motion_notify_cb,
+ window);
+
+ g_signal_handlers_disconnect_by_func (priv->view,
+ (gpointer) fullscreen_leave_notify_cb,
+ window);
+
+ g_signal_handlers_disconnect_by_func (priv->thumbview,
+ (gpointer) fullscreen_motion_notify_cb,
+ window);
+
+ g_signal_handlers_disconnect_by_func (priv->thumbview,
+ (gpointer) fullscreen_leave_notify_cb,
+ window);
+
+ update_ui_visibility (window);
+
+ menubar = gtk_ui_manager_get_widget (priv->ui_mgr, "/MainMenu");
+ g_assert (GTK_IS_WIDGET (menubar));
+ gtk_widget_show (menubar);
+
+ eom_scroll_view_set_zoom_upscale (EOM_SCROLL_VIEW (priv->view), FALSE);
+
+ eom_scroll_view_override_bg_color (EOM_SCROLL_VIEW (window->priv->view),
+ NULL);
+ gtk_widget_set_style (gtk_widget_get_parent (window->priv->view), NULL);
+ gtk_window_unfullscreen (GTK_WINDOW (window));
+
+ if (slideshow) {
+ eom_window_update_slideshow_action (window);
+ } else {
+ eom_window_update_fullscreen_action (window);
+ }
+
+ eom_scroll_view_show_cursor (EOM_SCROLL_VIEW (priv->view));
+
+#ifdef HAVE_DBUS
+ eom_application_screensaver_enable (EOM_APP);
+#endif
+}
+
+static void
+eom_window_print (EomWindow *window)
+{
+ GtkWidget *dialog;
+ GError *error = NULL;
+ GtkPrintOperation *print;
+ GtkPrintOperationResult res;
+ GtkPageSetup *page_setup;
+ GtkPrintSettings *print_settings;
+
+ eom_debug (DEBUG_PRINTING);
+
+ print_settings = eom_print_get_print_settings ();
+ page_setup = eom_print_get_page_setup ();
+
+ /* Make sure the window stays valid while printing */
+ g_object_ref (window);
+
+ print = eom_print_operation_new (window->priv->image,
+ print_settings,
+ page_setup);
+
+ res = gtk_print_operation_run (print,
+ GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+ GTK_WINDOW (window), &error);
+
+ if (res == GTK_PRINT_OPERATION_RESULT_ERROR) {
+ dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("Error printing file:\n%s"),
+ error->message);
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_widget_show (dialog);
+ g_error_free (error);
+ } else if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
+ eom_print_set_print_settings (gtk_print_operation_get_print_settings (print));
+ eom_print_set_page_setup (gtk_print_operation_get_default_page_setup (print));
+ }
+
+ g_object_unref (page_setup);
+ g_object_unref (print_settings);
+ g_object_unref (window);
+}
+
+static void
+eom_window_cmd_file_open (GtkAction *action, gpointer user_data)
+{
+ EomWindow *window;
+ EomWindowPrivate *priv;
+ EomImage *current;
+ GtkWidget *dlg;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ window = EOM_WINDOW (user_data);
+
+ priv = window->priv;
+
+ dlg = eom_file_chooser_new (GTK_FILE_CHOOSER_ACTION_OPEN);
+
+ current = eom_thumb_view_get_first_selected_image (EOM_THUMB_VIEW (priv->thumbview));
+
+ if (current != NULL) {
+ gchar *dir_uri, *file_uri;
+
+ file_uri = eom_image_get_uri_for_display (current);
+ dir_uri = g_path_get_dirname (file_uri);
+
+ gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dlg),
+ dir_uri);
+ g_free (file_uri);
+ g_free (dir_uri);
+ g_object_unref (current);
+ } else {
+ /* If desired by the user,
+ fallback to the XDG_PICTURES_DIR (if available) */
+ const gchar *pics_dir;
+ gboolean use_fallback;
+
+ use_fallback = mateconf_client_get_bool (priv->client,
+ EOM_CONF_UI_FILECHOOSER_XDG_FALLBACK,
+ NULL);
+ pics_dir = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
+ if (use_fallback && pics_dir) {
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dlg),
+ pics_dir);
+ }
+ }
+
+ g_signal_connect (dlg, "response",
+ G_CALLBACK (file_open_dialog_response_cb),
+ window);
+
+ gtk_widget_show_all (dlg);
+}
+
+static void
+eom_job_close_save_cb (EomJobSave *job, gpointer user_data)
+{
+ EomWindow *window = EOM_WINDOW (user_data);
+
+ g_signal_handlers_disconnect_by_func (job,
+ eom_job_close_save_cb,
+ window);
+
+ gtk_widget_destroy (GTK_WIDGET (window));
+}
+
+static void
+close_confirmation_dialog_response_handler (EomCloseConfirmationDialog *dlg,
+ gint response_id,
+ EomWindow *window)
+{
+ GList *selected_images;
+ EomWindowPrivate *priv;
+
+ priv = window->priv;
+
+ switch (response_id)
+ {
+ case GTK_RESPONSE_YES:
+ /* save selected images */
+ selected_images = eom_close_confirmation_dialog_get_selected_images (dlg);
+ eom_close_confirmation_dialog_set_sensitive (dlg, FALSE);
+ if (eom_window_save_images (window, selected_images)) {
+ g_signal_connect (priv->save_job,
+ "finished",
+ G_CALLBACK (eom_job_close_save_cb),
+ window);
+
+ eom_job_queue_add_job (priv->save_job);
+ }
+
+ break;
+
+ case GTK_RESPONSE_NO:
+ /* dont save */
+ gtk_widget_destroy (GTK_WIDGET (window));
+ break;
+
+ default:
+ /* Cancel */
+ gtk_widget_destroy (GTK_WIDGET (dlg));
+ break;
+ }
+}
+
+static gboolean
+eom_window_unsaved_images_confirm (EomWindow *window)
+{
+ EomWindowPrivate *priv;
+ GtkWidget *dialog;
+ GList *list;
+ EomImage *image;
+ GtkTreeIter iter;
+
+ priv = window->priv;
+
+ if (window->priv->save_disabled) {
+ return FALSE;
+ }
+
+ list = NULL;
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->store), &iter)) {
+ do {
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
+ EOM_LIST_STORE_EOM_IMAGE, &image,
+ -1);
+ if (!image)
+ continue;
+
+ if (eom_image_is_modified (image)) {
+ list = g_list_append (list, image);
+ }
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->store), &iter));
+ }
+
+ if (list) {
+ dialog = eom_close_confirmation_dialog_new (GTK_WINDOW (window),
+ list);
+
+ g_signal_connect (dialog,
+ "response",
+ G_CALLBACK (close_confirmation_dialog_response_handler),
+ window);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+
+ gtk_widget_show (dialog);
+ return TRUE;
+
+ }
+ return FALSE;
+}
+
+static void
+eom_window_cmd_close_window (GtkAction *action, gpointer user_data)
+{
+ EomWindow *window;
+ EomWindowPrivate *priv;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ window = EOM_WINDOW (user_data);
+ priv = window->priv;
+
+ if (priv->save_job != NULL) {
+ eom_window_finish_saving (window);
+ }
+
+ if (!eom_window_unsaved_images_confirm (window)) {
+ gtk_widget_destroy (GTK_WIDGET (user_data));
+ }
+}
+
+static void
+eom_window_cmd_preferences (GtkAction *action, gpointer user_data)
+{
+ EomWindow *window;
+ GObject *pref_dlg;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ window = EOM_WINDOW (user_data);
+
+ pref_dlg = eom_preferences_dialog_get_instance (GTK_WINDOW (window),
+ window->priv->client);
+
+ eom_dialog_show (EOM_DIALOG (pref_dlg));
+}
+
+#define EOM_TB_EDITOR_DLG_RESET_RESPONSE 128
+
+static void
+eom_window_cmd_edit_toolbar_cb (GtkDialog *dialog, gint response, gpointer data)
+{
+ EomWindow *window = EOM_WINDOW (data);
+
+ if (response == EOM_TB_EDITOR_DLG_RESET_RESPONSE) {
+ EggToolbarsModel *model;
+ EggToolbarEditor *editor;
+
+ editor = g_object_get_data (G_OBJECT (dialog),
+ "EggToolbarEditor");
+
+ g_return_if_fail (editor != NULL);
+
+ egg_editable_toolbar_set_edit_mode
+ (EGG_EDITABLE_TOOLBAR (window->priv->toolbar), FALSE);
+
+ eom_application_reset_toolbars_model (EOM_APP);
+ model = eom_application_get_toolbars_model (EOM_APP);
+ egg_editable_toolbar_set_model
+ (EGG_EDITABLE_TOOLBAR (window->priv->toolbar), model);
+ egg_toolbar_editor_set_model (editor, model);
+
+ /* Toolbar would be uneditable now otherwise */
+ egg_editable_toolbar_set_edit_mode
+ (EGG_EDITABLE_TOOLBAR (window->priv->toolbar), TRUE);
+ } else if (response == GTK_RESPONSE_HELP) {
+ eom_util_show_help ("eom-toolbareditor", NULL);
+ } else {
+ egg_editable_toolbar_set_edit_mode
+ (EGG_EDITABLE_TOOLBAR (window->priv->toolbar), FALSE);
+
+ eom_application_save_toolbars_model (EOM_APP);
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ }
+}
+
+static void
+eom_window_cmd_edit_toolbar (GtkAction *action, gpointer *user_data)
+{
+ EomWindow *window;
+ GtkWidget *dialog;
+ GtkWidget *editor;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ window = EOM_WINDOW (user_data);
+
+ dialog = gtk_dialog_new_with_buttons (_("Toolbar Editor"),
+ GTK_WINDOW (window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ _("_Reset to Default"),
+ EOM_TB_EDITOR_DLG_RESET_RESPONSE,
+ GTK_STOCK_CLOSE,
+ GTK_RESPONSE_CLOSE,
+ GTK_STOCK_HELP,
+ GTK_RESPONSE_HELP,
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_CLOSE);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+
+ gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 2);
+
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 400);
+
+ editor = egg_toolbar_editor_new (window->priv->ui_mgr,
+ eom_application_get_toolbars_model (EOM_APP));
+
+ gtk_container_set_border_width (GTK_CONTAINER (editor), 5);
+
+ gtk_box_set_spacing (GTK_BOX (EGG_TOOLBAR_EDITOR (editor)), 5);
+
+ gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), editor);
+
+ egg_editable_toolbar_set_edit_mode
+ (EGG_EDITABLE_TOOLBAR (window->priv->toolbar), TRUE);
+
+ g_object_set_data (G_OBJECT (dialog), "EggToolbarEditor", editor);
+
+ g_signal_connect (dialog,
+ "response",
+ G_CALLBACK (eom_window_cmd_edit_toolbar_cb),
+ window);
+
+ gtk_widget_show_all (dialog);
+}
+
+static void
+eom_window_cmd_help (GtkAction *action, gpointer user_data)
+{
+ EomWindow *window;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ window = EOM_WINDOW (user_data);
+
+ eom_util_show_help (NULL, GTK_WINDOW (window));
+}
+
+static void
+eom_window_cmd_about (GtkAction *action, gpointer user_data)
+{
+ EomWindow *window;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ static const char *authors[] = {
+ "Claudio Saavedra <[email protected]> (maintainer)",
+ "Felix Riemann <[email protected]> (maintainer)",
+ "",
+ "Lucas Rocha <[email protected]>",
+ "Tim Gerla <[email protected]>",
+ "Philip Van Hoof <[email protected]>",
+ "Paolo Borelli <[email protected]>",
+ "Jens Finke <[email protected]>",
+ "Martin Baulig <[email protected]>",
+ "Arik Devens <[email protected]>",
+ "Michael Meeks <[email protected]>",
+ "Federico Mena-Quintero <[email protected]>",
+ "Lutz M\xc3\xbcller <[email protected]>",
+ NULL
+ };
+
+ static const char *documenters[] = {
+ "Eliot Landrum <[email protected]>",
+ "Federico Mena-Quintero <[email protected]>",
+ "Sun MATE Documentation Team <[email protected]>",
+ NULL
+ };
+
+ const char *translators;
+
+ translators = _("translator-credits");
+
+ const char *license[] = {
+ N_("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 "
+ "the Free Software Foundation; either version 2 of the License, or "
+ "(at your option) any later version.\n"),
+ N_("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 "
+ "GNU General Public License for more details.\n"),
+ N_("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.")
+ };
+
+ char *license_trans;
+
+ license_trans = g_strconcat (_(license[0]), "\n", _(license[1]), "\n",
+ _(license[2]), "\n", NULL);
+
+ window = EOM_WINDOW (user_data);
+
+ gtk_show_about_dialog (GTK_WINDOW (window),
+ "program-name", _("Eye of MATE"),
+ "version", VERSION,
+ "copyright", "Copyright \xc2\xa9 2000-2010 Free Software Foundation, Inc.",
+ "comments",_("The MATE image viewer."),
+ "authors", authors,
+ "documenters", documenters,
+ "translator-credits", translators,
+ "website", "http://projects.gnome.org/eom/",
+ "logo-icon-name", "eom",
+ "wrap-license", TRUE,
+ "license", license_trans,
+ NULL);
+
+ g_free (license_trans);
+}
+
+static void
+eom_window_cmd_show_hide_bar (GtkAction *action, gpointer user_data)
+{
+ EomWindow *window;
+ EomWindowPrivate *priv;
+ gboolean visible;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ window = EOM_WINDOW (user_data);
+ priv = window->priv;
+
+ if (priv->mode != EOM_WINDOW_MODE_NORMAL &&
+ priv->mode != EOM_WINDOW_MODE_FULLSCREEN) return;
+
+ visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+
+ if (g_ascii_strcasecmp (gtk_action_get_name (action), "ViewToolbar") == 0) {
+ g_object_set (G_OBJECT (priv->toolbar), "visible", visible, NULL);
+
+ if (priv->mode == EOM_WINDOW_MODE_NORMAL)
+ mateconf_client_set_bool (priv->client, EOM_CONF_UI_TOOLBAR, visible, NULL);
+
+ } else if (g_ascii_strcasecmp (gtk_action_get_name (action), "ViewStatusbar") == 0) {
+ g_object_set (G_OBJECT (priv->statusbar), "visible", visible, NULL);
+
+ if (priv->mode == EOM_WINDOW_MODE_NORMAL)
+ mateconf_client_set_bool (priv->client, EOM_CONF_UI_STATUSBAR, visible, NULL);
+
+ } else if (g_ascii_strcasecmp (gtk_action_get_name (action), "ViewImageCollection") == 0) {
+ if (visible) {
+ /* Make sure the focus widget is realized to
+ * avoid warnings on keypress events */
+#if GTK_CHECK_VERSION (2, 20, 0)
+ if (!gtk_widget_get_realized (window->priv->thumbview))
+#else
+ if (!GTK_WIDGET_REALIZED (window->priv->thumbview))
+#endif
+ gtk_widget_realize (window->priv->thumbview);
+
+ gtk_widget_show (priv->nav);
+ gtk_widget_grab_focus (priv->thumbview);
+ } else {
+ /* Make sure the focus widget is realized to
+ * avoid warnings on keypress events.
+ * Don't do it during init phase or the view
+ * will get a bogus allocation. */
+#if GTK_CHECK_VERSION (2, 20, 0)
+ if (!gtk_widget_get_realized (priv->view)
+#else
+ if (!GTK_WIDGET_REALIZED (priv->view)
+#endif
+ && priv->status == EOM_WINDOW_STATUS_NORMAL)
+ gtk_widget_realize (priv->view);
+
+ gtk_widget_hide (priv->nav);
+
+#if GTK_CHECK_VERSION (2, 20, 0)
+ if (gtk_widget_get_realized (priv->view))
+#else
+ if (GTK_WIDGET_REALIZED (priv->view))
+#endif
+ gtk_widget_grab_focus (priv->view);
+ }
+ mateconf_client_set_bool (priv->client, EOM_CONF_UI_IMAGE_COLLECTION, visible, NULL);
+
+ } else if (g_ascii_strcasecmp (gtk_action_get_name (action), "ViewSidebar") == 0) {
+ if (visible) {
+ gtk_widget_show (priv->sidebar);
+ } else {
+ gtk_widget_hide (priv->sidebar);
+ }
+ mateconf_client_set_bool (priv->client, EOM_CONF_UI_SIDEBAR, visible, NULL);
+ }
+}
+
+static void
+wallpaper_info_bar_response (GtkInfoBar *bar, gint response, EomWindow *window)
+{
+ if (response == GTK_RESPONSE_YES) {
+ GdkScreen *screen;
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (window));
+ gdk_spawn_command_line_on_screen (screen,
+ "mate-appearance-properties"
+ " --show-page=background",
+ NULL);
+ }
+
+ /* Close message area on every response */
+ eom_window_set_message_area (window, NULL);
+}
+
+static void
+eom_window_set_wallpaper (EomWindow *window, const gchar *filename, const gchar *visible_filename)
+{
+ EomWindowPrivate *priv = EOM_WINDOW_GET_PRIVATE (window);
+ GtkWidget *info_bar;
+ GtkWidget *image;
+ GtkWidget *label;
+ GtkWidget *hbox;
+ gchar *markup;
+ gchar *text;
+ gchar *basename;
+
+
+ mateconf_client_set_string (priv->client,
+ EOM_CONF_DESKTOP_WALLPAPER,
+ filename,
+ NULL);
+
+ /* I18N: When setting mnemonics for these strings, watch out to not
+ clash with mnemonics from eom's menubar */
+ info_bar = gtk_info_bar_new_with_buttons (_("_Open Background Preferences"),
+ GTK_RESPONSE_YES,
+ C_("MessageArea","Hi_de"),
+ GTK_RESPONSE_NO, NULL);
+ gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar),
+ GTK_MESSAGE_QUESTION);
+
+ image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION,
+ GTK_ICON_SIZE_DIALOG);
+ label = gtk_label_new (NULL);
+
+ if (!visible_filename)
+ basename = g_path_get_basename (filename);
+
+ /* The newline character is currently necessary due to a problem
+ * with the automatic line break. */
+ text = g_strdup_printf (_("The image \"%s\" has been set as Desktop Background."
+ "\nWould you like to modify its appearance?"),
+ visible_filename ? visible_filename : basename);
+ markup = g_markup_printf_escaped ("<b>%s</b>", text);
+ gtk_label_set_markup (GTK_LABEL (label), markup);
+ g_free (markup);
+ g_free (text);
+ if (!visible_filename)
+ g_free (basename);
+
+ hbox = gtk_hbox_new (FALSE, 8);
+ gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ gtk_box_pack_start (GTK_BOX (gtk_info_bar_get_content_area (GTK_INFO_BAR (info_bar))), hbox, TRUE, TRUE, 0);
+ gtk_widget_show_all (hbox);
+ gtk_widget_show (info_bar);
+
+
+ eom_window_set_message_area (window, info_bar);
+ gtk_info_bar_set_default_response (GTK_INFO_BAR (info_bar),
+ GTK_RESPONSE_YES);
+ g_signal_connect (info_bar, "response",
+ G_CALLBACK (wallpaper_info_bar_response), window);
+}
+
+static void
+eom_job_save_cb (EomJobSave *job, gpointer user_data)
+{
+ EomWindow *window = EOM_WINDOW (user_data);
+ GtkAction *action_save;
+
+ g_signal_handlers_disconnect_by_func (job,
+ eom_job_save_cb,
+ window);
+
+ g_signal_handlers_disconnect_by_func (job,
+ eom_job_save_progress_cb,
+ window);
+
+ g_object_unref (window->priv->save_job);
+ window->priv->save_job = NULL;
+
+ update_status_bar (window);
+ action_save = gtk_action_group_get_action (window->priv->actions_image,
+ "ImageSave");
+ gtk_action_set_sensitive (action_save, FALSE);
+}
+
+static void
+eom_job_copy_cb (EomJobCopy *job, gpointer user_data)
+{
+ EomWindow *window = EOM_WINDOW (user_data);
+ gchar *filepath, *basename, *filename, *extension;
+ GtkAction *action;
+ GFile *source_file, *dest_file;
+
+ /* Create source GFile */
+ basename = g_file_get_basename (job->images->data);
+ filepath = g_build_filename (job->dest, basename, NULL);
+ source_file = g_file_new_for_path (filepath);
+ g_free (filepath);
+
+ /* Create destination GFile */
+ extension = eom_util_filename_get_extension (basename);
+ filename = g_strdup_printf ("%s.%s", EOM_WALLPAPER_FILENAME, extension);
+ filepath = g_build_filename (job->dest, filename, NULL);
+ dest_file = g_file_new_for_path (filepath);
+ g_free (filename);
+ g_free (extension);
+
+ /* Move the file */
+ g_file_move (source_file, dest_file, G_FILE_COPY_OVERWRITE,
+ NULL, NULL, NULL, NULL);
+
+ /* Set the wallpaper */
+ eom_window_set_wallpaper (window, filepath, basename);
+ g_free (basename);
+ g_free (filepath);
+
+ gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar),
+ window->priv->copy_file_cid);
+ action = gtk_action_group_get_action (window->priv->actions_image,
+ "ImageSetAsWallpaper");
+ gtk_action_set_sensitive (action, TRUE);
+
+ window->priv->copy_job = NULL;
+
+ g_object_unref (source_file);
+ g_object_unref (dest_file);
+ g_object_unref (G_OBJECT (job->images->data));
+ g_list_free (job->images);
+ g_object_unref (job);
+}
+
+static gboolean
+eom_window_save_images (EomWindow *window, GList *images)
+{
+ EomWindowPrivate *priv;
+
+ priv = window->priv;
+
+ if (window->priv->save_job != NULL)
+ return FALSE;
+
+ priv->save_job = eom_job_save_new (images);
+
+ g_signal_connect (priv->save_job,
+ "finished",
+ G_CALLBACK (eom_job_save_cb),
+ window);
+
+ g_signal_connect (priv->save_job,
+ "progress",
+ G_CALLBACK (eom_job_save_progress_cb),
+ window);
+
+ return TRUE;
+}
+
+static void
+eom_window_cmd_save (GtkAction *action, gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ EomWindow *window;
+ GList *images;
+
+ window = EOM_WINDOW (user_data);
+ priv = window->priv;
+
+ if (window->priv->save_job != NULL)
+ return;
+
+ images = eom_thumb_view_get_selected_images (EOM_THUMB_VIEW (priv->thumbview));
+
+ if (eom_window_save_images (window, images)) {
+ eom_job_queue_add_job (priv->save_job);
+ }
+}
+
+static GFile*
+eom_window_retrieve_save_as_file (EomWindow *window, EomImage *image)
+{
+ GtkWidget *dialog;
+ GFile *save_file = NULL;
+ GFile *last_dest_folder;
+ gint response;
+
+ g_assert (image != NULL);
+
+ dialog = eom_file_chooser_new (GTK_FILE_CHOOSER_ACTION_SAVE);
+
+ last_dest_folder = window->priv->last_save_as_folder;
+
+ if (last_dest_folder && g_file_query_exists (last_dest_folder, NULL)) {
+ gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog), last_dest_folder, NULL);
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog),
+ eom_image_get_caption (image));
+ } else {
+ GFile *image_file;
+
+ image_file = eom_image_get_file (image);
+ /* Setting the file will also navigate to its parent folder */
+ gtk_file_chooser_set_file (GTK_FILE_CHOOSER (dialog),
+ image_file, NULL);
+ g_object_unref (image_file);
+ }
+
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_hide (dialog);
+
+ if (response == GTK_RESPONSE_OK) {
+ save_file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ if (window->priv->last_save_as_folder)
+ g_object_unref (window->priv->last_save_as_folder);
+ window->priv->last_save_as_folder = g_file_get_parent (save_file);
+ }
+ gtk_widget_destroy (dialog);
+
+ return save_file;
+}
+
+static void
+eom_window_cmd_save_as (GtkAction *action, gpointer user_data)
+{
+ EomWindowPrivate *priv;
+ EomWindow *window;
+ GList *images;
+ guint n_images;
+
+ window = EOM_WINDOW (user_data);
+ priv = window->priv;
+
+ if (window->priv->save_job != NULL)
+ return;
+
+ images = eom_thumb_view_get_selected_images (EOM_THUMB_VIEW (priv->thumbview));
+ n_images = g_list_length (images);
+
+ if (n_images == 1) {
+ GFile *file;
+
+ file = eom_window_retrieve_save_as_file (window, images->data);
+
+ if (!file) {
+ g_list_free (images);
+ return;
+ }
+
+ priv->save_job = eom_job_save_as_new (images, NULL, file);
+
+ g_object_unref (file);
+ } else if (n_images > 1) {
+ GFile *base_file;
+ GtkWidget *dialog;
+ gchar *basedir;
+ EomURIConverter *converter;
+
+ basedir = g_get_current_dir ();
+ base_file = g_file_new_for_path (basedir);
+ g_free (basedir);
+
+ dialog = eom_save_as_dialog_new (GTK_WINDOW (window),
+ images,
+ base_file);
+
+ gtk_widget_show_all (dialog);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) {
+ g_object_unref (base_file);
+ g_list_free (images);
+ gtk_widget_destroy (dialog);
+
+ return;
+ }
+
+ converter = eom_save_as_dialog_get_converter (dialog);
+
+ g_assert (converter != NULL);
+
+ priv->save_job = eom_job_save_as_new (images, converter, NULL);
+
+ gtk_widget_destroy (dialog);
+
+ g_object_unref (converter);
+ g_object_unref (base_file);
+ } else {
+ /* n_images = 0 -- No Image selected */
+ return;
+ }
+
+ g_signal_connect (priv->save_job,
+ "finished",
+ G_CALLBACK (eom_job_save_cb),
+ window);
+
+ g_signal_connect (priv->save_job,
+ "progress",
+ G_CALLBACK (eom_job_save_progress_cb),
+ window);
+
+ eom_job_queue_add_job (priv->save_job);
+}
+
+static void
+eom_window_cmd_print (GtkAction *action, gpointer user_data)
+{
+ EomWindow *window = EOM_WINDOW (user_data);
+
+ eom_window_print (window);
+}
+
+static void
+eom_window_cmd_properties (GtkAction *action, gpointer user_data)
+{
+ EomWindow *window = EOM_WINDOW (user_data);
+ EomWindowPrivate *priv;
+ GtkAction *next_image_action, *previous_image_action;
+
+ priv = window->priv;
+
+ next_image_action =
+ gtk_action_group_get_action (priv->actions_collection,
+ "GoNext");
+
+ previous_image_action =
+ gtk_action_group_get_action (priv->actions_collection,
+ "GoPrevious");
+
+ if (window->priv->properties_dlg == NULL) {
+ gboolean netbook_mode;
+
+ window->priv->properties_dlg =
+ eom_properties_dialog_new (GTK_WINDOW (window),
+ EOM_THUMB_VIEW (priv->thumbview),
+ next_image_action,
+ previous_image_action);
+
+ eom_properties_dialog_update (EOM_PROPERTIES_DIALOG (priv->properties_dlg),
+ priv->image);
+ netbook_mode =
+ mateconf_client_get_bool (priv->client,
+ EOM_CONF_UI_PROPSDIALOG_NETBOOK_MODE,
+ NULL);
+ eom_properties_dialog_set_netbook_mode (EOM_PROPERTIES_DIALOG (priv->properties_dlg),
+ netbook_mode);
+ }
+
+ eom_dialog_show (EOM_DIALOG (window->priv->properties_dlg));
+}
+
+static void
+eom_window_cmd_undo (GtkAction *action, gpointer user_data)
+{
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ apply_transformation (EOM_WINDOW (user_data), NULL);
+}
+
+static void
+eom_window_cmd_flip_horizontal (GtkAction *action, gpointer user_data)
+{
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ apply_transformation (EOM_WINDOW (user_data),
+ eom_transform_flip_new (EOM_TRANSFORM_FLIP_HORIZONTAL));
+}
+
+static void
+eom_window_cmd_flip_vertical (GtkAction *action, gpointer user_data)
+{
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ apply_transformation (EOM_WINDOW (user_data),
+ eom_transform_flip_new (EOM_TRANSFORM_FLIP_VERTICAL));
+}
+
+static void
+eom_window_cmd_rotate_90 (GtkAction *action, gpointer user_data)
+{
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ apply_transformation (EOM_WINDOW (user_data),
+ eom_transform_rotate_new (90));
+}
+
+static void
+eom_window_cmd_rotate_270 (GtkAction *action, gpointer user_data)
+{
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ apply_transformation (EOM_WINDOW (user_data),
+ eom_transform_rotate_new (270));
+}
+
+static void
+eom_window_cmd_wallpaper (GtkAction *action, gpointer user_data)
+{
+ EomWindow *window;
+ EomWindowPrivate *priv;
+ EomImage *image;
+ GFile *file;
+ char *filename = NULL;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ window = EOM_WINDOW (user_data);
+ priv = window->priv;
+
+ /* If currently copying an image to set it as wallpaper, return. */
+ if (priv->copy_job != NULL)
+ return;
+
+ image = eom_thumb_view_get_first_selected_image (EOM_THUMB_VIEW (priv->thumbview));
+
+ g_return_if_fail (EOM_IS_IMAGE (image));
+
+ file = eom_image_get_file (image);
+
+ filename = g_file_get_path (file);
+
+ /* Currently only local files can be set as wallpaper */
+ if (filename == NULL || !eom_util_file_is_persistent (file))
+ {
+ GList *files = NULL;
+ GtkAction *action;
+
+ action = gtk_action_group_get_action (window->priv->actions_image,
+ "ImageSetAsWallpaper");
+ gtk_action_set_sensitive (action, FALSE);
+
+ priv->copy_file_cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (priv->statusbar),
+ "copy_file_cid");
+ gtk_statusbar_push (GTK_STATUSBAR (priv->statusbar),
+ priv->copy_file_cid,
+ _("Saving image locally…"));
+
+ files = g_list_append (files, eom_image_get_file (image));
+ priv->copy_job = eom_job_copy_new (files, g_get_user_data_dir ());
+ g_signal_connect (priv->copy_job,
+ "finished",
+ G_CALLBACK (eom_job_copy_cb),
+ window);
+ g_signal_connect (priv->copy_job,
+ "progress",
+ G_CALLBACK (eom_job_progress_cb),
+ window);
+ eom_job_queue_add_job (priv->copy_job);
+
+ g_object_unref (file);
+ g_free (filename);
+ return;
+ }
+
+ g_object_unref (file);
+
+ eom_window_set_wallpaper (window, filename, NULL);
+
+ g_free (filename);
+}
+
+static gboolean
+eom_window_all_images_trasheable (GList *images)
+{
+ GFile *file;
+ GFileInfo *file_info;
+ GList *iter;
+ EomImage *image;
+ gboolean can_trash = TRUE;
+
+ for (iter = images; iter != NULL; iter = g_list_next (iter)) {
+ image = (EomImage *) iter->data;
+ file = eom_image_get_file (image);
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH,
+ 0, NULL, NULL);
+ can_trash = g_file_info_get_attribute_boolean (file_info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH);
+
+ g_object_unref (file_info);
+ g_object_unref (file);
+
+ if (can_trash == FALSE)
+ break;
+ }
+
+ return can_trash;
+}
+
+static int
+show_move_to_trash_confirm_dialog (EomWindow *window, GList *images, gboolean can_trash)
+{
+ GtkWidget *dlg;
+ char *prompt;
+ int response;
+ int n_images;
+ EomImage *image;
+ static gboolean dontaskagain = FALSE;
+ gboolean neverask = FALSE;
+ GtkWidget* dontask_cbutton = NULL;
+
+ /* Check if the user never wants to be bugged. Ignore the error as
+ * it returns FALSE for safety anyway */
+ neverask = mateconf_client_get_bool (window->priv->client,
+ EOM_CONF_UI_DISABLE_TRASH_CONFIRMATION,
+ NULL);
+
+ /* Assume agreement, if the user doesn't want to be
+ * 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) {
+ image = EOM_IMAGE (images->data);
+ if (can_trash) {
+ prompt = g_strdup_printf (_("Are you sure you want to move\n\"%s\" to the trash?"),
+ eom_image_get_caption (image));
+ } else {
+ prompt = g_strdup_printf (_("A trash for \"%s\" couldn't be found. Do you want to remove "
+ "this image permanently?"), eom_image_get_caption (image));
+ }
+ } else {
+ if (can_trash) {
+ prompt = g_strdup_printf (ngettext("Are you sure you want to move\n"
+ "the selected image to the trash?",
+ "Are you sure you want to move\n"
+ "the %d selected images to the trash?", n_images), n_images);
+ } else {
+ prompt = g_strdup (_("Some of the selected images can't be moved to the trash "
+ "and will be removed permanently. Are you sure you want "
+ "to proceed?"));
+ }
+ }
+
+ dlg = gtk_message_dialog_new_with_markup (GTK_WINDOW (window),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ "<span weight=\"bold\" size=\"larger\">%s</span>",
+ prompt);
+ g_free (prompt);
+
+ gtk_dialog_add_button (GTK_DIALOG (dlg), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+
+ if (can_trash) {
+ gtk_dialog_add_button (GTK_DIALOG (dlg), _("Move to _Trash"), GTK_RESPONSE_OK);
+
+ dontask_cbutton = gtk_check_button_new_with_mnemonic (_("_Do not ask again during this session"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dontask_cbutton), FALSE);
+
+ gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), dontask_cbutton, TRUE, TRUE, 0);
+ } else {
+ if (n_images == 1) {
+ gtk_dialog_add_button (GTK_DIALOG (dlg), GTK_STOCK_DELETE, GTK_RESPONSE_OK);
+ } else {
+ gtk_dialog_add_button (GTK_DIALOG (dlg), GTK_STOCK_YES, GTK_RESPONSE_OK);
+ }
+ }
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dlg), GTK_RESPONSE_OK);
+ gtk_window_set_title (GTK_WINDOW (dlg), "");
+ gtk_widget_show_all (dlg);
+
+ response = gtk_dialog_run (GTK_DIALOG (dlg));
+
+ /* Only update the property if the user has accepted */
+ if (can_trash && response == GTK_RESPONSE_OK)
+ dontaskagain = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dontask_cbutton));
+
+ /* The checkbutton is destroyed together with the dialog */
+ gtk_widget_destroy (dlg);
+
+ return response;
+}
+
+static gboolean
+move_to_trash_real (EomImage *image, GError **error)
+{
+ GFile *file;
+ GFileInfo *file_info;
+ gboolean can_trash, result;
+
+ g_return_val_if_fail (EOM_IS_IMAGE (image), FALSE);
+
+ file = eom_image_get_file (image);
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH,
+ 0, NULL, NULL);
+ if (file_info == NULL) {
+ g_set_error (error,
+ EOM_WINDOW_ERROR,
+ EOM_WINDOW_ERROR_TRASH_NOT_FOUND,
+ _("Couldn't access trash."));
+ return FALSE;
+ }
+
+ can_trash = g_file_info_get_attribute_boolean (file_info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH);
+ g_object_unref (file_info);
+ if (can_trash)
+ {
+ result = g_file_trash (file, NULL, NULL);
+ if (result == FALSE) {
+ g_set_error (error,
+ EOM_WINDOW_ERROR,
+ EOM_WINDOW_ERROR_TRASH_NOT_FOUND,
+ _("Couldn't access trash."));
+ }
+ } else {
+ result = g_file_delete (file, NULL, NULL);
+ if (result == FALSE) {
+ g_set_error (error,
+ EOM_WINDOW_ERROR,
+ EOM_WINDOW_ERROR_IO,
+ _("Couldn't delete file"));
+ }
+ }
+
+ g_object_unref (file);
+
+ return result;
+}
+
+static void
+eom_window_cmd_move_to_trash (GtkAction *action, gpointer user_data)
+{
+ GList *images;
+ GList *it;
+ EomWindowPrivate *priv;
+ EomListStore *list;
+ int pos;
+ EomImage *img;
+ EomWindow *window;
+ int response;
+ int n_images;
+ gboolean success;
+ gboolean can_trash;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ window = EOM_WINDOW (user_data);
+ priv = window->priv;
+ list = priv->store;
+
+ n_images = eom_thumb_view_get_n_selected (EOM_THUMB_VIEW (priv->thumbview));
+
+ if (n_images < 1) return;
+
+ /* save position of selected image after the deletion */
+ images = eom_thumb_view_get_selected_images (EOM_THUMB_VIEW (priv->thumbview));
+
+ g_assert (images != NULL);
+
+ /* HACK: eom_list_store_get_n_selected return list in reverse order */
+ images = g_list_reverse (images);
+
+ can_trash = eom_window_all_images_trasheable (images);
+
+ if (g_ascii_strcasecmp (gtk_action_get_name (action), "Delete") == 0 ||
+ can_trash == FALSE) {
+ response = show_move_to_trash_confirm_dialog (window, images, can_trash);
+
+ if (response != GTK_RESPONSE_OK) return;
+ }
+
+ pos = eom_list_store_get_pos_by_image (list, EOM_IMAGE (images->data));
+
+ /* FIXME: make a nice progress dialog */
+ /* Do the work actually. First try to delete the image from the disk. If this
+ * is successfull, remove it from the screen. Otherwise show error dialog.
+ */
+ for (it = images; it != NULL; it = it->next) {
+ GError *error = NULL;
+ EomImage *image;
+
+ image = EOM_IMAGE (it->data);
+
+ success = move_to_trash_real (image, &error);
+
+ if (success) {
+ eom_list_store_remove_image (list, image);
+ } else {
+ char *header;
+ GtkWidget *dlg;
+
+ header = g_strdup_printf (_("Error on deleting image %s"),
+ eom_image_get_caption (image));
+
+ dlg = gtk_message_dialog_new (GTK_WINDOW (window),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "%s", header);
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dlg),
+ "%s", error->message);
+
+ gtk_dialog_run (GTK_DIALOG (dlg));
+
+ gtk_widget_destroy (dlg);
+
+ g_free (header);
+ }
+ }
+
+ /* free list */
+ g_list_foreach (images, (GFunc) g_object_unref, NULL);
+ g_list_free (images);
+
+ /* select image at previously saved position */
+ pos = MIN (pos, eom_list_store_length (list) - 1);
+
+ if (pos >= 0) {
+ img = eom_list_store_get_image_by_pos (list, pos);
+
+ eom_thumb_view_set_current_image (EOM_THUMB_VIEW (priv->thumbview),
+ img,
+ TRUE);
+
+ if (img != NULL) {
+ g_object_unref (img);
+ }
+ }
+}
+
+static void
+eom_window_cmd_fullscreen (GtkAction *action, gpointer user_data)
+{
+ EomWindow *window;
+ gboolean fullscreen;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_WINDOW);
+
+ window = EOM_WINDOW (user_data);
+
+ fullscreen = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+
+ if (fullscreen) {
+ eom_window_run_fullscreen (window, FALSE);
+ } else {
+ eom_window_stop_fullscreen (window, FALSE);
+ }
+}
+
+static void
+eom_window_cmd_slideshow (GtkAction *action, gpointer user_data)
+{
+ EomWindow *window;
+ gboolean slideshow;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_WINDOW);
+
+ window = EOM_WINDOW (user_data);
+
+ slideshow = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+
+ if (slideshow) {
+ eom_window_run_fullscreen (window, TRUE);
+ } else {
+ eom_window_stop_fullscreen (window, TRUE);
+ }
+}
+
+static void
+eom_window_cmd_pause_slideshow (GtkAction *action, gpointer user_data)
+{
+ EomWindow *window;
+ gboolean slideshow;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_WINDOW);
+
+ window = EOM_WINDOW (user_data);
+
+ slideshow = window->priv->mode == EOM_WINDOW_MODE_SLIDESHOW;
+
+ if (!slideshow && window->priv->mode != EOM_WINDOW_MODE_FULLSCREEN)
+ return;
+
+ eom_window_run_fullscreen (window, !slideshow);
+}
+
+static void
+eom_window_cmd_zoom_in (GtkAction *action, gpointer user_data)
+{
+ EomWindowPrivate *priv;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ if (priv->view) {
+ eom_scroll_view_zoom_in (EOM_SCROLL_VIEW (priv->view), FALSE);
+ }
+}
+
+static void
+eom_window_cmd_zoom_out (GtkAction *action, gpointer user_data)
+{
+ EomWindowPrivate *priv;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ if (priv->view) {
+ eom_scroll_view_zoom_out (EOM_SCROLL_VIEW (priv->view), FALSE);
+ }
+}
+
+static void
+eom_window_cmd_zoom_normal (GtkAction *action, gpointer user_data)
+{
+ EomWindowPrivate *priv;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ if (priv->view) {
+ eom_scroll_view_set_zoom (EOM_SCROLL_VIEW (priv->view), 1.0);
+ }
+}
+
+static void
+eom_window_cmd_zoom_fit (GtkAction *action, gpointer user_data)
+{
+ EomWindowPrivate *priv;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ if (priv->view) {
+ eom_scroll_view_zoom_fit (EOM_SCROLL_VIEW (priv->view));
+ }
+}
+
+static void
+eom_window_cmd_go_prev (GtkAction *action, gpointer user_data)
+{
+ EomWindowPrivate *priv;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ eom_thumb_view_select_single (EOM_THUMB_VIEW (priv->thumbview),
+ EOM_THUMB_VIEW_SELECT_LEFT);
+}
+
+static void
+eom_window_cmd_go_next (GtkAction *action, gpointer user_data)
+{
+ EomWindowPrivate *priv;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ eom_thumb_view_select_single (EOM_THUMB_VIEW (priv->thumbview),
+ EOM_THUMB_VIEW_SELECT_RIGHT);
+}
+
+static void
+eom_window_cmd_go_first (GtkAction *action, gpointer user_data)
+{
+ EomWindowPrivate *priv;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ eom_thumb_view_select_single (EOM_THUMB_VIEW (priv->thumbview),
+ EOM_THUMB_VIEW_SELECT_FIRST);
+}
+
+static void
+eom_window_cmd_go_last (GtkAction *action, gpointer user_data)
+{
+ EomWindowPrivate *priv;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ eom_thumb_view_select_single (EOM_THUMB_VIEW (priv->thumbview),
+ EOM_THUMB_VIEW_SELECT_LAST);
+}
+
+static void
+eom_window_cmd_go_random (GtkAction *action, gpointer user_data)
+{
+ EomWindowPrivate *priv;
+
+ g_return_if_fail (EOM_IS_WINDOW (user_data));
+
+ eom_debug (DEBUG_WINDOW);
+
+ priv = EOM_WINDOW (user_data)->priv;
+
+ eom_thumb_view_select_single (EOM_THUMB_VIEW (priv->thumbview),
+ EOM_THUMB_VIEW_SELECT_RANDOM);
+}
+
+static const GtkActionEntry action_entries_window[] = {
+ { "Image", NULL, N_("_Image") },
+ { "Edit", NULL, N_("_Edit") },
+ { "View", NULL, N_("_View") },
+ { "Go", NULL, N_("_Go") },
+ { "Tools", NULL, N_("_Tools") },
+ { "Help", NULL, N_("_Help") },
+
+ { "ImageOpen", GTK_STOCK_OPEN, N_("_Open…"), "<control>O",
+ N_("Open a file"),
+ G_CALLBACK (eom_window_cmd_file_open) },
+ { "ImageClose", GTK_STOCK_CLOSE, N_("_Close"), "<control>W",
+ N_("Close window"),
+ G_CALLBACK (eom_window_cmd_close_window) },
+ { "EditToolbar", NULL, N_("T_oolbar"), NULL,
+ N_("Edit the application toolbar"),
+ G_CALLBACK (eom_window_cmd_edit_toolbar) },
+ { "EditPreferences", GTK_STOCK_PREFERENCES, N_("Prefere_nces"), NULL,
+ N_("Preferences for Eye of MATE"),
+ G_CALLBACK (eom_window_cmd_preferences) },
+ { "HelpManual", GTK_STOCK_HELP, N_("_Contents"), "F1",
+ N_("Help on this application"),
+ G_CALLBACK (eom_window_cmd_help) },
+ { "HelpAbout", GTK_STOCK_ABOUT, N_("_About"), NULL,
+ N_("About this application"),
+ G_CALLBACK (eom_window_cmd_about) }
+};
+
+static const GtkToggleActionEntry toggle_entries_window[] = {
+ { "ViewToolbar", NULL, N_("_Toolbar"), NULL,
+ N_("Changes the visibility of the toolbar in the current window"),
+ G_CALLBACK (eom_window_cmd_show_hide_bar), TRUE },
+ { "ViewStatusbar", NULL, N_("_Statusbar"), NULL,
+ N_("Changes the visibility of the statusbar in the current window"),
+ G_CALLBACK (eom_window_cmd_show_hide_bar), TRUE },
+ { "ViewImageCollection", "eom-image-collection", N_("_Image Collection"), "F9",
+ N_("Changes the visibility of the image collection pane in the current window"),
+ G_CALLBACK (eom_window_cmd_show_hide_bar), TRUE },
+ { "ViewSidebar", NULL, N_("Side _Pane"), "<control>F9",
+ N_("Changes the visibility of the side pane in the current window"),
+ G_CALLBACK (eom_window_cmd_show_hide_bar), TRUE },
+};
+
+static const GtkActionEntry action_entries_image[] = {
+ { "ImageSave", GTK_STOCK_SAVE, N_("_Save"), "<control>s",
+ N_("Save changes in currently selected images"),
+ G_CALLBACK (eom_window_cmd_save) },
+ { "ImageOpenWith", NULL, N_("Open _with"), NULL,
+ N_("Open the selected image with a different application"),
+ NULL},
+ { "ImageSaveAs", GTK_STOCK_SAVE_AS, N_("Save _As…"), "<control><shift>s",
+ N_("Save the selected images with a different name"),
+ G_CALLBACK (eom_window_cmd_save_as) },
+ { "ImagePrint", GTK_STOCK_PRINT, N_("_Print…"), "<control>p",
+ N_("Print the selected image"),
+ G_CALLBACK (eom_window_cmd_print) },
+ { "ImageProperties", GTK_STOCK_PROPERTIES, N_("Prope_rties"), "<alt>Return",
+ N_("Show the properties and metadata of the selected image"),
+ G_CALLBACK (eom_window_cmd_properties) },
+ { "EditUndo", GTK_STOCK_UNDO, N_("_Undo"), "<control>z",
+ N_("Undo the last change in the image"),
+ G_CALLBACK (eom_window_cmd_undo) },
+ { "EditFlipHorizontal", "object-flip-horizontal", N_("Flip _Horizontal"), NULL,
+ N_("Mirror the image horizontally"),
+ G_CALLBACK (eom_window_cmd_flip_horizontal) },
+ { "EditFlipVertical", "object-flip-vertical", N_("Flip _Vertical"), NULL,
+ N_("Mirror the image vertically"),
+ G_CALLBACK (eom_window_cmd_flip_vertical) },
+ { "EditRotate90", "object-rotate-right", N_("_Rotate Clockwise"), "<control>r",
+ N_("Rotate the image 90 degrees to the right"),
+ G_CALLBACK (eom_window_cmd_rotate_90) },
+ { "EditRotate270", "object-rotate-left", N_("Rotate Counterc_lockwise"), "<ctrl><shift>r",
+ N_("Rotate the image 90 degrees to the left"),
+ G_CALLBACK (eom_window_cmd_rotate_270) },
+ { "ImageSetAsWallpaper", NULL, N_("Set as _Desktop Background"),
+ "<control>F8", N_("Set the selected image as the desktop background"),
+ G_CALLBACK (eom_window_cmd_wallpaper) },
+ { "EditMoveToTrash", "user-trash", N_("Move to _Trash"), NULL,
+ N_("Move the selected image to the trash folder"),
+ G_CALLBACK (eom_window_cmd_move_to_trash) },
+ { "ViewZoomIn", GTK_STOCK_ZOOM_IN, N_("_Zoom In"), "<control>plus",
+ N_("Enlarge the image"),
+ G_CALLBACK (eom_window_cmd_zoom_in) },
+ { "ViewZoomOut", GTK_STOCK_ZOOM_OUT, N_("Zoom _Out"), "<control>minus",
+ N_("Shrink the image"),
+ G_CALLBACK (eom_window_cmd_zoom_out) },
+ { "ViewZoomNormal", GTK_STOCK_ZOOM_100, N_("_Normal Size"), "<control>0",
+ N_("Show the image at its normal size"),
+ G_CALLBACK (eom_window_cmd_zoom_normal) },
+ { "ViewZoomFit", GTK_STOCK_ZOOM_FIT, N_("Best _Fit"), "F",
+ N_("Fit the image to the window"),
+ G_CALLBACK (eom_window_cmd_zoom_fit) },
+ { "ControlEqual", GTK_STOCK_ZOOM_IN, N_("_Zoom In"), "<control>equal",
+ N_("Enlarge the image"),
+ G_CALLBACK (eom_window_cmd_zoom_in) },
+ { "ControlKpAdd", GTK_STOCK_ZOOM_IN, N_("_Zoom In"), "<control>KP_Add",
+ N_("Shrink the image"),
+ G_CALLBACK (eom_window_cmd_zoom_in) },
+ { "ControlKpSub", GTK_STOCK_ZOOM_OUT, N_("Zoom _Out"), "<control>KP_Subtract",
+ N_("Shrink the image"),
+ G_CALLBACK (eom_window_cmd_zoom_out) },
+ { "Delete", NULL, N_("Move to _Trash"), "Delete",
+ NULL,
+ G_CALLBACK (eom_window_cmd_move_to_trash) },
+};
+
+static const GtkToggleActionEntry toggle_entries_image[] = {
+ { "ViewFullscreen", GTK_STOCK_FULLSCREEN, N_("_Fullscreen"), "F11",
+ N_("Show the current image in fullscreen mode"),
+ G_CALLBACK (eom_window_cmd_fullscreen), FALSE },
+ { "PauseSlideshow", "media-playback-pause", N_("Pause Slideshow"),
+ NULL, N_("Pause or resume the slideshow"),
+ G_CALLBACK (eom_window_cmd_pause_slideshow), FALSE },
+};
+
+static const GtkActionEntry action_entries_collection[] = {
+ { "GoPrevious", GTK_STOCK_GO_BACK, N_("_Previous Image"), "<Alt>Left",
+ N_("Go to the previous image of the collection"),
+ G_CALLBACK (eom_window_cmd_go_prev) },
+ { "GoNext", GTK_STOCK_GO_FORWARD, N_("_Next Image"), "<Alt>Right",
+ N_("Go to the next image of the collection"),
+ G_CALLBACK (eom_window_cmd_go_next) },
+ { "GoFirst", GTK_STOCK_GOTO_FIRST, N_("_First Image"), "<Alt>Home",
+ N_("Go to the first image of the collection"),
+ G_CALLBACK (eom_window_cmd_go_first) },
+ { "GoLast", GTK_STOCK_GOTO_LAST, N_("_Last Image"), "<Alt>End",
+ N_("Go to the last image of the collection"),
+ G_CALLBACK (eom_window_cmd_go_last) },
+ { "GoRandom", NULL, N_("_Random Image"), "<control>M",
+ N_("Go to a random image of the collection"),
+ G_CALLBACK (eom_window_cmd_go_random) },
+ { "BackSpace", NULL, N_("_Previous Image"), "BackSpace",
+ NULL,
+ G_CALLBACK (eom_window_cmd_go_prev) },
+ { "Home", NULL, N_("_First Image"), "Home",
+ NULL,
+ G_CALLBACK (eom_window_cmd_go_first) },
+ { "End", NULL, N_("_Last Image"), "End",
+ NULL,
+ G_CALLBACK (eom_window_cmd_go_last) },
+};
+
+static const GtkToggleActionEntry toggle_entries_collection[] = {
+ { "ViewSlideshow", "slideshow-play", N_("_Slideshow"), "F5",
+ N_("Start a slideshow view of the images"),
+ G_CALLBACK (eom_window_cmd_slideshow), FALSE },
+};
+
+static void
+menu_item_select_cb (GtkMenuItem *proxy, EomWindow *window)
+{
+ GtkAction *action;
+ char *message;
+
+ action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (proxy));
+
+ g_return_if_fail (action != NULL);
+
+ g_object_get (G_OBJECT (action), "tooltip", &message, NULL);
+
+ if (message) {
+ gtk_statusbar_push (GTK_STATUSBAR (window->priv->statusbar),
+ window->priv->tip_message_cid, message);
+ g_free (message);
+ }
+}
+
+static void
+menu_item_deselect_cb (GtkMenuItem *proxy, EomWindow *window)
+{
+ gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar),
+ window->priv->tip_message_cid);
+}
+
+static void
+connect_proxy_cb (GtkUIManager *manager,
+ GtkAction *action,
+ GtkWidget *proxy,
+ EomWindow *window)
+{
+ if (GTK_IS_MENU_ITEM (proxy)) {
+ g_signal_connect (proxy, "select",
+ G_CALLBACK (menu_item_select_cb), window);
+ g_signal_connect (proxy, "deselect",
+ G_CALLBACK (menu_item_deselect_cb), window);
+ }
+}
+
+static void
+disconnect_proxy_cb (GtkUIManager *manager,
+ GtkAction *action,
+ GtkWidget *proxy,
+ EomWindow *window)
+{
+ if (GTK_IS_MENU_ITEM (proxy)) {
+ g_signal_handlers_disconnect_by_func
+ (proxy, G_CALLBACK (menu_item_select_cb), window);
+ g_signal_handlers_disconnect_by_func
+ (proxy, G_CALLBACK (menu_item_deselect_cb), window);
+ }
+}
+
+static void
+set_action_properties (GtkActionGroup *window_group,
+ GtkActionGroup *image_group,
+ GtkActionGroup *collection_group)
+{
+ GtkAction *action;
+
+ action = gtk_action_group_get_action (collection_group, "GoPrevious");
+ g_object_set (action, "short_label", _("Previous"), NULL);
+ g_object_set (action, "is-important", TRUE, NULL);
+
+ action = gtk_action_group_get_action (collection_group, "GoNext");
+ g_object_set (action, "short_label", _("Next"), NULL);
+ g_object_set (action, "is-important", TRUE, NULL);
+
+ action = gtk_action_group_get_action (image_group, "EditRotate90");
+ g_object_set (action, "short_label", _("Right"), NULL);
+
+ action = gtk_action_group_get_action (image_group, "EditRotate270");
+ g_object_set (action, "short_label", _("Left"), NULL);
+
+ action = gtk_action_group_get_action (image_group, "ViewZoomIn");
+ g_object_set (action, "short_label", _("In"), NULL);
+
+ action = gtk_action_group_get_action (image_group, "ViewZoomOut");
+ g_object_set (action, "short_label", _("Out"), NULL);
+
+ action = gtk_action_group_get_action (image_group, "ViewZoomNormal");
+ g_object_set (action, "short_label", _("Normal"), NULL);
+
+ action = gtk_action_group_get_action (image_group, "ViewZoomFit");
+ g_object_set (action, "short_label", _("Fit"), NULL);
+
+ action = gtk_action_group_get_action (window_group, "ViewImageCollection");
+ g_object_set (action, "short_label", _("Collection"), NULL);
+
+ action = gtk_action_group_get_action (image_group, "EditMoveToTrash");
+ g_object_set (action, "short_label", C_("action (to trash)", "Trash"), NULL);
+}
+
+static gint
+sort_recents_mru (GtkRecentInfo *a, GtkRecentInfo *b)
+{
+ gboolean has_eom_a, has_eom_b;
+
+ /* We need to check this first as gtk_recent_info_get_application_info
+ * will treat it as a non-fatal error when the GtkRecentInfo doesn't
+ * have the application registered. */
+ has_eom_a = gtk_recent_info_has_application (a,
+ EOM_RECENT_FILES_APP_NAME);
+ has_eom_b = gtk_recent_info_has_application (b,
+ EOM_RECENT_FILES_APP_NAME);
+ if (has_eom_a && has_eom_b) {
+ time_t time_a, time_b;
+
+ /* These should not fail as we already checked that
+ * the application is registered with the info objects */
+ gtk_recent_info_get_application_info (a,
+ EOM_RECENT_FILES_APP_NAME,
+ NULL,
+ NULL,
+ &time_a);
+ gtk_recent_info_get_application_info (b,
+ EOM_RECENT_FILES_APP_NAME,
+ NULL,
+ NULL,
+ &time_b);
+
+ return (time_b - time_a);
+ } else if (has_eom_a) {
+ return -1;
+ } else if (has_eom_b) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
+eom_window_update_recent_files_menu (EomWindow *window)
+{
+ EomWindowPrivate *priv;
+ GList *actions = NULL, *li = NULL, *items = NULL;
+ guint count_recent = 0;
+
+ priv = window->priv;
+
+ if (priv->recent_menu_id != 0)
+ gtk_ui_manager_remove_ui (priv->ui_mgr, priv->recent_menu_id);
+
+ actions = gtk_action_group_list_actions (priv->actions_recent);
+
+ for (li = actions; li != NULL; li = li->next) {
+ g_signal_handlers_disconnect_by_func (GTK_ACTION (li->data),
+ G_CALLBACK(eom_window_open_recent_cb),
+ window);
+
+ gtk_action_group_remove_action (priv->actions_recent,
+ GTK_ACTION (li->data));
+ }
+
+ g_list_free (actions);
+
+ priv->recent_menu_id = gtk_ui_manager_new_merge_id (priv->ui_mgr);
+ items = gtk_recent_manager_get_items (gtk_recent_manager_get_default());
+ items = g_list_sort (items, (GCompareFunc) sort_recents_mru);
+
+ for (li = items; li != NULL && count_recent < EOM_RECENT_FILES_LIMIT; li = li->next) {
+ gchar *action_name;
+ gchar *label;
+ gchar *tip;
+ gchar **display_name;
+ gchar *label_filename;
+ GtkAction *action;
+ GtkRecentInfo *info = li->data;
+
+ /* Sorting moves non-EOM files to the end of the list.
+ * So no file of interest will follow if this test fails */
+ if (!gtk_recent_info_has_application (info, EOM_RECENT_FILES_APP_NAME))
+ break;
+
+ count_recent++;
+
+ action_name = g_strdup_printf ("recent-info-%d", count_recent);
+ display_name = g_strsplit (gtk_recent_info_get_display_name (info), "_", -1);
+ label_filename = g_strjoinv ("__", display_name);
+ label = g_strdup_printf ("%s_%d. %s",
+ (is_rtl ? "\xE2\x80\x8F" : ""), count_recent, label_filename);
+ g_free (label_filename);
+ g_strfreev (display_name);
+
+ tip = gtk_recent_info_get_uri_display (info);
+
+ /* This is a workaround for a bug (#351945) regarding
+ * gtk_recent_info_get_uri_display() and remote URIs.
+ * mate_vfs_format_uri_for_display is sufficient here
+ * since the password gets stripped when adding the
+ * file to the recently used list. */
+ if (tip == NULL)
+ tip = g_uri_unescape_string (gtk_recent_info_get_uri (info), NULL);
+
+ action = gtk_action_new (action_name, label, tip, NULL);
+ gtk_action_set_always_show_image (action, TRUE);
+
+ g_object_set_data_full (G_OBJECT (action), "gtk-recent-info",
+ gtk_recent_info_ref (info),
+ (GDestroyNotify) gtk_recent_info_unref);
+
+ g_object_set (G_OBJECT (action), "icon-name", "image-x-generic", NULL);
+
+ g_signal_connect (action, "activate",
+ G_CALLBACK (eom_window_open_recent_cb),
+ window);
+
+ gtk_action_group_add_action (priv->actions_recent, action);
+
+ g_object_unref (action);
+
+ gtk_ui_manager_add_ui (priv->ui_mgr, priv->recent_menu_id,
+ "/MainMenu/Image/RecentDocuments",
+ action_name, action_name,
+ GTK_UI_MANAGER_AUTO, FALSE);
+
+ g_free (action_name);
+ g_free (label);
+ g_free (tip);
+ }
+
+ g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
+ g_list_free (items);
+}
+
+static void
+eom_window_recent_manager_changed_cb (GtkRecentManager *manager, EomWindow *window)
+{
+ eom_window_update_recent_files_menu (window);
+}
+
+static void
+eom_window_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x, gint y,
+ GtkSelectionData *selection_data,
+ guint info, guint time)
+{
+ GSList *file_list;
+ EomWindow *window;
+ GdkAtom target;
+
+ target = gtk_selection_data_get_target (selection_data);
+
+ if (!gtk_targets_include_uri (&target, 1))
+ return;
+
+ if (context->suggested_action == GDK_ACTION_COPY) {
+ window = EOM_WINDOW (widget);
+
+ file_list = eom_util_parse_uri_string_list_to_file_list ((const gchar *) gtk_selection_data_get_data (selection_data));
+
+ eom_window_open_file_list (window, file_list);
+ }
+}
+
+static void
+eom_window_set_drag_dest (EomWindow *window)
+{
+ gtk_drag_dest_set (GTK_WIDGET (window),
+ GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+ NULL, 0,
+ GDK_ACTION_COPY | GDK_ACTION_ASK);
+ gtk_drag_dest_add_uri_targets (GTK_WIDGET (window));
+}
+
+static void
+eom_window_sidebar_visibility_changed (GtkWidget *widget, EomWindow *window)
+{
+ GtkAction *action;
+ gboolean visible;
+
+ visible = gtk_widget_get_visible (window->priv->sidebar);
+
+ mateconf_client_set_bool (window->priv->client,
+ EOM_CONF_UI_SIDEBAR,
+ visible,
+ NULL);
+
+ action = gtk_action_group_get_action (window->priv->actions_window,
+ "ViewSidebar");
+
+ if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) != visible)
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
+
+ /* Focus the image */
+ if (!visible && window->priv->image != NULL)
+ gtk_widget_grab_focus (window->priv->view);
+}
+
+static void
+eom_window_sidebar_page_added (EomSidebar *sidebar,
+ GtkWidget *main_widget,
+ EomWindow *window)
+{
+ if (eom_sidebar_get_n_pages (sidebar) == 1) {
+ GtkAction *action;
+ gboolean show;
+
+ action = gtk_action_group_get_action (window->priv->actions_window,
+ "ViewSidebar");
+
+ gtk_action_set_sensitive (action, TRUE);
+
+ show = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+
+ if (show)
+ gtk_widget_show (GTK_WIDGET (sidebar));
+ }
+}
+static void
+eom_window_sidebar_page_removed (EomSidebar *sidebar,
+ GtkWidget *main_widget,
+ EomWindow *window)
+{
+ if (eom_sidebar_is_empty (sidebar)) {
+ GtkAction *action;
+
+ gtk_widget_hide (GTK_WIDGET (sidebar));
+
+ action = gtk_action_group_get_action (window->priv->actions_window,
+ "ViewSidebar");
+
+ gtk_action_set_sensitive (action, FALSE);
+ }
+}
+
+static void
+eom_window_finish_saving (EomWindow *window)
+{
+ EomWindowPrivate *priv = window->priv;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (window), FALSE);
+
+ do {
+ gtk_main_iteration ();
+ } while (priv->save_job != NULL);
+}
+
+static void
+eom_window_construct_ui (EomWindow *window)
+{
+ EomWindowPrivate *priv;
+
+ GError *error = NULL;
+
+ GtkWidget *menubar;
+ GtkWidget *thumb_popup;
+ GtkWidget *view_popup;
+ GtkWidget *hpaned;
+ GtkWidget *menuitem;
+
+ MateConfEntry *entry;
+
+ g_return_if_fail (EOM_IS_WINDOW (window));
+
+ priv = window->priv;
+
+ priv->box = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), priv->box);
+ gtk_widget_show (priv->box);
+
+ priv->ui_mgr = gtk_ui_manager_new ();
+
+ priv->actions_window = gtk_action_group_new ("MenuActionsWindow");
+
+ gtk_action_group_set_translation_domain (priv->actions_window,
+ GETTEXT_PACKAGE);
+
+ gtk_action_group_add_actions (priv->actions_window,
+ action_entries_window,
+ G_N_ELEMENTS (action_entries_window),
+ window);
+
+ gtk_action_group_add_toggle_actions (priv->actions_window,
+ toggle_entries_window,
+ G_N_ELEMENTS (toggle_entries_window),
+ window);
+
+ gtk_ui_manager_insert_action_group (priv->ui_mgr, priv->actions_window, 0);
+
+ priv->actions_image = gtk_action_group_new ("MenuActionsImage");
+ gtk_action_group_set_translation_domain (priv->actions_image,
+ GETTEXT_PACKAGE);
+
+ gtk_action_group_add_actions (priv->actions_image,
+ action_entries_image,
+ G_N_ELEMENTS (action_entries_image),
+ window);
+
+ gtk_action_group_add_toggle_actions (priv->actions_image,
+ toggle_entries_image,
+ G_N_ELEMENTS (toggle_entries_image),
+ window);
+
+ gtk_ui_manager_insert_action_group (priv->ui_mgr, priv->actions_image, 0);
+
+ priv->actions_collection = gtk_action_group_new ("MenuActionsCollection");
+ gtk_action_group_set_translation_domain (priv->actions_collection,
+ GETTEXT_PACKAGE);
+
+ gtk_action_group_add_actions (priv->actions_collection,
+ action_entries_collection,
+ G_N_ELEMENTS (action_entries_collection),
+ window);
+
+ gtk_action_group_add_toggle_actions (priv->actions_collection,
+ toggle_entries_collection,
+ G_N_ELEMENTS (toggle_entries_collection),
+ window);
+
+ set_action_properties (priv->actions_window,
+ priv->actions_image,
+ priv->actions_collection);
+
+ gtk_ui_manager_insert_action_group (priv->ui_mgr, priv->actions_collection, 0);
+
+ if (!gtk_ui_manager_add_ui_from_file (priv->ui_mgr,
+ EOM_DATA_DIR"/eom-ui.xml",
+ &error)) {
+ g_warning ("building menus failed: %s", error->message);
+ g_error_free (error);
+ }
+
+ g_signal_connect (priv->ui_mgr, "connect_proxy",
+ G_CALLBACK (connect_proxy_cb), window);
+ g_signal_connect (priv->ui_mgr, "disconnect_proxy",
+ G_CALLBACK (disconnect_proxy_cb), window);
+
+ menubar = gtk_ui_manager_get_widget (priv->ui_mgr, "/MainMenu");
+ g_assert (GTK_IS_WIDGET (menubar));
+ gtk_box_pack_start (GTK_BOX (priv->box), menubar, FALSE, FALSE, 0);
+ gtk_widget_show (menubar);
+
+ menuitem = gtk_ui_manager_get_widget (priv->ui_mgr,
+ "/MainMenu/Edit/EditFlipHorizontal");
+ gtk_image_menu_item_set_always_show_image (
+ GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
+
+ menuitem = gtk_ui_manager_get_widget (priv->ui_mgr,
+ "/MainMenu/Edit/EditFlipVertical");
+ gtk_image_menu_item_set_always_show_image (
+ GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
+
+ menuitem = gtk_ui_manager_get_widget (priv->ui_mgr,
+ "/MainMenu/Edit/EditRotate90");
+ gtk_image_menu_item_set_always_show_image (
+ GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
+
+ menuitem = gtk_ui_manager_get_widget (priv->ui_mgr,
+ "/MainMenu/Edit/EditRotate270");
+ gtk_image_menu_item_set_always_show_image (
+ GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
+
+ priv->toolbar = GTK_WIDGET
+ (g_object_new (EGG_TYPE_EDITABLE_TOOLBAR,
+ "ui-manager", priv->ui_mgr,
+ "model", eom_application_get_toolbars_model (EOM_APP),
+ NULL));
+
+ egg_editable_toolbar_show (EGG_EDITABLE_TOOLBAR (priv->toolbar),
+ "Toolbar");
+
+ gtk_box_pack_start (GTK_BOX (priv->box),
+ priv->toolbar,
+ FALSE,
+ FALSE,
+ 0);
+
+ gtk_widget_show (priv->toolbar);
+
+ gtk_window_add_accel_group (GTK_WINDOW (window),
+ gtk_ui_manager_get_accel_group (priv->ui_mgr));
+
+ priv->actions_recent = gtk_action_group_new ("RecentFilesActions");
+ gtk_action_group_set_translation_domain (priv->actions_recent,
+ GETTEXT_PACKAGE);
+
+ g_signal_connect (gtk_recent_manager_get_default (), "changed",
+ G_CALLBACK (eom_window_recent_manager_changed_cb),
+ window);
+
+ eom_window_update_recent_files_menu (window);
+
+ gtk_ui_manager_insert_action_group (priv->ui_mgr, priv->actions_recent, 0);
+
+ priv->cbox = gtk_vbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (priv->box), priv->cbox, TRUE, TRUE, 0);
+ gtk_widget_show (priv->cbox);
+
+ priv->statusbar = eom_statusbar_new ();
+ gtk_box_pack_end (GTK_BOX (priv->box),
+ GTK_WIDGET (priv->statusbar),
+ FALSE, FALSE, 0);
+ gtk_widget_show (priv->statusbar);
+
+ priv->image_info_message_cid =
+ gtk_statusbar_get_context_id (GTK_STATUSBAR (priv->statusbar),
+ "image_info_message");
+ priv->tip_message_cid =
+ gtk_statusbar_get_context_id (GTK_STATUSBAR (priv->statusbar),
+ "tip_message");
+
+ priv->layout = gtk_vbox_new (FALSE, 2);
+
+ hpaned = gtk_hpaned_new ();
+
+ priv->sidebar = eom_sidebar_new ();
+ /* The sidebar shouldn't be shown automatically on show_all(),
+ but only when the user actually wants it. */
+ gtk_widget_set_no_show_all (priv->sidebar, TRUE);
+
+ gtk_widget_set_size_request (priv->sidebar, 210, -1);
+
+ g_signal_connect_after (priv->sidebar,
+ "show",
+ G_CALLBACK (eom_window_sidebar_visibility_changed),
+ window);
+
+ g_signal_connect_after (priv->sidebar,
+ "hide",
+ G_CALLBACK (eom_window_sidebar_visibility_changed),
+ window);
+
+ g_signal_connect_after (priv->sidebar,
+ "page-added",
+ G_CALLBACK (eom_window_sidebar_page_added),
+ window);
+
+ g_signal_connect_after (priv->sidebar,
+ "page-removed",
+ G_CALLBACK (eom_window_sidebar_page_removed),
+ window);
+
+ priv->view = eom_scroll_view_new ();
+ gtk_widget_set_size_request (GTK_WIDGET (priv->view), 100, 100);
+ g_signal_connect (G_OBJECT (priv->view),
+ "zoom_changed",
+ G_CALLBACK (view_zoom_changed_cb),
+ window);
+
+ view_popup = gtk_ui_manager_get_widget (priv->ui_mgr, "/ViewPopup");
+ eom_scroll_view_set_popup (EOM_SCROLL_VIEW (priv->view),
+ GTK_MENU (view_popup));
+
+ gtk_paned_pack1 (GTK_PANED (hpaned),
+ priv->sidebar,
+ FALSE,
+ FALSE);
+
+ gtk_paned_pack2 (GTK_PANED (hpaned),
+ priv->view,
+ TRUE,
+ FALSE);
+
+ gtk_widget_show_all (hpaned);
+
+ gtk_box_pack_start (GTK_BOX (priv->layout), hpaned, TRUE, TRUE, 0);
+
+ priv->thumbview = eom_thumb_view_new ();
+
+ /* giving shape to the view */
+ gtk_icon_view_set_margin (GTK_ICON_VIEW (priv->thumbview), 4);
+ gtk_icon_view_set_row_spacing (GTK_ICON_VIEW (priv->thumbview), 0);
+
+ g_signal_connect (G_OBJECT (priv->thumbview), "selection_changed",
+ G_CALLBACK (handle_image_selection_changed_cb), window);
+
+ priv->nav = eom_thumb_nav_new (priv->thumbview,
+ EOM_THUMB_NAV_MODE_ONE_ROW,
+ mateconf_client_get_bool (priv->client,
+ EOM_CONF_UI_SCROLL_BUTTONS,
+ NULL));
+
+ thumb_popup = gtk_ui_manager_get_widget (priv->ui_mgr, "/ThumbnailPopup");
+ eom_thumb_view_set_thumbnail_popup (EOM_THUMB_VIEW (priv->thumbview),
+ GTK_MENU (thumb_popup));
+
+ gtk_box_pack_start (GTK_BOX (priv->layout), priv->nav, FALSE, FALSE, 0);
+
+ gtk_box_pack_end (GTK_BOX (priv->cbox), priv->layout, TRUE, TRUE, 0);
+
+
+ entry = mateconf_client_get_entry (priv->client,
+ EOM_CONF_VIEW_EXTRAPOLATE,
+ NULL, TRUE, NULL);
+ if (entry != NULL) {
+ eom_window_interp_in_type_changed_cb (priv->client, 0, entry, window);
+ mateconf_entry_unref (entry);
+ entry = NULL;
+ }
+
+ entry = mateconf_client_get_entry (priv->client,
+ EOM_CONF_VIEW_INTERPOLATE,
+ NULL, TRUE, NULL);
+ if (entry != NULL) {
+ eom_window_interp_out_type_changed_cb (priv->client, 0, entry, window);
+ mateconf_entry_unref (entry);
+ entry = NULL;
+ }
+
+ entry = mateconf_client_get_entry (priv->client,
+ EOM_CONF_VIEW_SCROLL_WHEEL_ZOOM,
+ NULL, TRUE, NULL);
+ if (entry != NULL) {
+ eom_window_scroll_wheel_zoom_changed_cb (priv->client, 0, entry, window);
+ mateconf_entry_unref (entry);
+ entry = NULL;
+ }
+
+ entry = mateconf_client_get_entry (priv->client,
+ EOM_CONF_VIEW_ZOOM_MULTIPLIER,
+ NULL, TRUE, NULL);
+ if (entry != NULL) {
+ eom_window_zoom_multiplier_changed_cb (priv->client, 0, entry, window);
+ mateconf_entry_unref (entry);
+ entry = NULL;
+ }
+
+ entry = mateconf_client_get_entry (priv->client,
+ EOM_CONF_VIEW_BACKGROUND_COLOR,
+ NULL, TRUE, NULL);
+ if (entry != NULL) {
+ eom_window_bg_color_changed_cb (priv->client, 0, entry, window);
+ mateconf_entry_unref (entry);
+ entry = NULL;
+ }
+
+ entry = mateconf_client_get_entry (priv->client,
+ EOM_CONF_VIEW_USE_BG_COLOR,
+ NULL, TRUE, NULL);
+ if (entry != NULL) {
+ eom_window_use_bg_color_changed_cb (priv->client, 0, entry, window);
+ mateconf_entry_unref (entry);
+ entry = NULL;
+ }
+
+ entry = mateconf_client_get_entry (priv->client,
+ EOM_CONF_VIEW_TRANSPARENCY,
+ NULL, TRUE, NULL);
+ if (entry != NULL) {
+ eom_window_transparency_changed_cb (priv->client, 0, entry, window);
+ mateconf_entry_unref (entry);
+ entry = NULL;
+ }
+
+ entry = mateconf_client_get_entry (priv->client,
+ EOM_CONF_VIEW_TRANS_COLOR,
+ NULL, TRUE, NULL);
+ if (entry != NULL) {
+ eom_window_trans_color_changed_cb (priv->client, 0, entry, window);
+ mateconf_entry_unref (entry);
+ entry = NULL;
+ }
+
+ entry = mateconf_client_get_entry (priv->client,
+ EOM_CONF_UI_IMAGE_COLLECTION_POSITION,
+ NULL, TRUE, NULL);
+ if (entry != NULL) {
+ eom_window_collection_mode_changed_cb (priv->client, 0, entry, window);
+ mateconf_entry_unref (entry);
+ entry = NULL;
+ }
+
+ entry = mateconf_client_get_entry (priv->client,
+ EOM_CONF_DESKTOP_CAN_SAVE,
+ NULL, TRUE, NULL);
+ if (entry != NULL) {
+ eom_window_can_save_changed_cb (priv->client, 0, entry, window);
+ mateconf_entry_unref (entry);
+ entry = NULL;
+ }
+
+ if ((priv->flags & EOM_STARTUP_FULLSCREEN) ||
+ (priv->flags & EOM_STARTUP_SLIDE_SHOW)) {
+ eom_window_run_fullscreen (window, (priv->flags & EOM_STARTUP_SLIDE_SHOW));
+ } else {
+ priv->mode = EOM_WINDOW_MODE_NORMAL;
+ update_ui_visibility (window);
+ }
+
+ eom_window_set_drag_dest (window);
+}
+
+static void
+eom_window_init (EomWindow *window)
+{
+ GdkGeometry hints;
+ GdkScreen *screen;
+ EomWindowPrivate *priv;
+
+ eom_debug (DEBUG_WINDOW);
+
+ hints.min_width = EOM_WINDOW_MIN_WIDTH;
+ hints.min_height = EOM_WINDOW_MIN_HEIGHT;
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (window));
+
+ priv = window->priv = EOM_WINDOW_GET_PRIVATE (window);
+
+ priv->client = mateconf_client_get_default ();
+
+ mateconf_client_add_dir (window->priv->client, EOM_CONF_DIR,
+ MATECONF_CLIENT_PRELOAD_RECURSIVE, NULL);
+
+ priv->client_notifications[EOM_WINDOW_NOTIFY_EXTRAPOLATE] =
+ mateconf_client_notify_add (window->priv->client,
+ EOM_CONF_VIEW_EXTRAPOLATE,
+ eom_window_interp_in_type_changed_cb,
+ window, NULL, NULL);
+
+ priv->client_notifications[EOM_WINDOW_NOTIFY_INTERPOLATE] =
+ mateconf_client_notify_add (window->priv->client,
+ EOM_CONF_VIEW_INTERPOLATE,
+ eom_window_interp_out_type_changed_cb,
+ window, NULL, NULL);
+
+ priv->client_notifications[EOM_WINDOW_NOTIFY_SCROLLWHEEL_ZOOM] =
+ mateconf_client_notify_add (window->priv->client,
+ EOM_CONF_VIEW_SCROLL_WHEEL_ZOOM,
+ eom_window_scroll_wheel_zoom_changed_cb,
+ window, NULL, NULL);
+
+ priv->client_notifications[EOM_WINDOW_NOTIFY_ZOOM_MULTIPLIER] =
+ mateconf_client_notify_add (window->priv->client,
+ EOM_CONF_VIEW_ZOOM_MULTIPLIER,
+ eom_window_zoom_multiplier_changed_cb,
+ window, NULL, NULL);
+
+ priv->client_notifications[EOM_WINDOW_NOTIFY_BACKGROUND_COLOR] =
+ mateconf_client_notify_add (window->priv->client,
+ EOM_CONF_VIEW_BACKGROUND_COLOR,
+ eom_window_bg_color_changed_cb,
+ window, NULL, NULL);
+
+ priv->client_notifications[EOM_WINDOW_NOTIFY_USE_BG_COLOR] =
+ mateconf_client_notify_add (window->priv->client,
+ EOM_CONF_VIEW_USE_BG_COLOR,
+ eom_window_use_bg_color_changed_cb,
+ window, NULL, NULL);
+
+ priv->client_notifications[EOM_WINDOW_NOTIFY_TRANSPARENCY] =
+ mateconf_client_notify_add (window->priv->client,
+ EOM_CONF_VIEW_TRANSPARENCY,
+ eom_window_transparency_changed_cb,
+ window, NULL, NULL);
+
+ priv->client_notifications[EOM_WINDOW_NOTIFY_TRANS_COLOR] =
+ mateconf_client_notify_add (window->priv->client,
+ EOM_CONF_VIEW_TRANS_COLOR,
+ eom_window_trans_color_changed_cb,
+ window, NULL, NULL);
+
+ priv->client_notifications[EOM_WINDOW_NOTIFY_SCROLL_BUTTONS] =
+ mateconf_client_notify_add (window->priv->client,
+ EOM_CONF_UI_SCROLL_BUTTONS,
+ eom_window_scroll_buttons_changed_cb,
+ window, NULL, NULL);
+
+ priv->client_notifications[EOM_WINDOW_NOTIFY_COLLECTION_POS] =
+ mateconf_client_notify_add (window->priv->client,
+ EOM_CONF_UI_IMAGE_COLLECTION_POSITION,
+ eom_window_collection_mode_changed_cb,
+ window, NULL, NULL);
+
+ priv->client_notifications[EOM_WINDOW_NOTIFY_COLLECTION_RESIZABLE] =
+ mateconf_client_notify_add (window->priv->client,
+ EOM_CONF_UI_IMAGE_COLLECTION_RESIZABLE,
+ eom_window_collection_mode_changed_cb,
+ window, NULL, NULL);
+
+ priv->client_notifications[EOM_WINDOW_NOTIFY_CAN_SAVE] =
+ mateconf_client_notify_add (window->priv->client,
+ EOM_CONF_DESKTOP_CAN_SAVE,
+ eom_window_can_save_changed_cb,
+ window, NULL, NULL);
+
+ priv->client_notifications[EOM_WINDOW_NOTIFY_PROPSDIALOG_NETBOOK_MODE] =
+ mateconf_client_notify_add (window->priv->client,
+ EOM_CONF_UI_PROPSDIALOG_NETBOOK_MODE,
+ eom_window_pd_nbmode_changed_cb,
+ window, NULL, NULL);
+
+ window->priv->store = NULL;
+ window->priv->image = NULL;
+
+ window->priv->fullscreen_popup = NULL;
+ window->priv->fullscreen_timeout_source = NULL;
+ window->priv->slideshow_loop = FALSE;
+ window->priv->slideshow_switch_timeout = 0;
+ window->priv->slideshow_switch_source = NULL;
+
+ gtk_window_set_geometry_hints (GTK_WINDOW (window),
+ GTK_WIDGET (window),
+ &hints,
+ GDK_HINT_MIN_SIZE);
+
+ gtk_window_set_default_size (GTK_WINDOW (window),
+ EOM_WINDOW_DEFAULT_WIDTH,
+ EOM_WINDOW_DEFAULT_HEIGHT);
+
+ gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
+
+ window->priv->mode = EOM_WINDOW_MODE_UNKNOWN;
+ window->priv->status = EOM_WINDOW_STATUS_UNKNOWN;
+
+#ifdef HAVE_LCMS
+ window->priv->display_profile =
+ eom_window_get_display_profile (screen);
+#endif
+
+ window->priv->recent_menu_id = 0;
+
+ window->priv->collection_position = 0;
+ window->priv->collection_resizable = FALSE;
+
+ window->priv->save_disabled = FALSE;
+}
+
+static void
+eom_window_dispose (GObject *object)
+{
+ EomWindow *window;
+ EomWindowPrivate *priv;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (EOM_IS_WINDOW (object));
+
+ eom_debug (DEBUG_WINDOW);
+
+ window = EOM_WINDOW (object);
+ priv = window->priv;
+
+ eom_plugin_engine_garbage_collect ();
+
+ if (priv->store != NULL) {
+ g_signal_handlers_disconnect_by_func (priv->store,
+ eom_window_list_store_image_added,
+ window);
+ g_signal_handlers_disconnect_by_func (priv->store,
+ eom_window_list_store_image_removed,
+ window);
+ g_object_unref (priv->store);
+ priv->store = NULL;
+ }
+
+ if (priv->image != NULL) {
+ g_signal_handlers_disconnect_by_func (priv->image,
+ image_thumb_changed_cb,
+ window);
+ g_signal_handlers_disconnect_by_func (priv->image,
+ image_file_changed_cb,
+ window);
+ g_object_unref (priv->image);
+ priv->image = NULL;
+ }
+
+ if (priv->actions_window != NULL) {
+ g_object_unref (priv->actions_window);
+ priv->actions_window = NULL;
+ }
+
+ if (priv->actions_image != NULL) {
+ g_object_unref (priv->actions_image);
+ priv->actions_image = NULL;
+ }
+
+ if (priv->actions_collection != NULL) {
+ g_object_unref (priv->actions_collection);
+ priv->actions_collection = NULL;
+ }
+
+ if (priv->actions_recent != NULL) {
+ g_object_unref (priv->actions_recent);
+ priv->actions_recent = NULL;
+ }
+
+ if (priv->actions_open_with != NULL) {
+ g_object_unref (priv->actions_open_with);
+ priv->actions_open_with = NULL;
+ }
+
+ fullscreen_clear_timeout (window);
+
+ if (window->priv->fullscreen_popup != NULL) {
+ gtk_widget_destroy (priv->fullscreen_popup);
+ priv->fullscreen_popup = NULL;
+ }
+
+ slideshow_clear_timeout (window);
+
+ g_signal_handlers_disconnect_by_func (gtk_recent_manager_get_default (),
+ G_CALLBACK (eom_window_recent_manager_changed_cb),
+ window);
+
+ priv->recent_menu_id = 0;
+
+ eom_window_clear_load_job (window);
+
+ eom_window_clear_transform_job (window);
+
+ if (priv->client) {
+ int i;
+
+ for (i = 0; i < EOM_WINDOW_NOTIFY_LENGTH; ++i) {
+ mateconf_client_notify_remove (priv->client,
+ priv->client_notifications[i]);
+ }
+ mateconf_client_remove_dir (priv->client, EOM_CONF_DIR, NULL);
+ g_object_unref (priv->client);
+ priv->client = NULL;
+ }
+
+ if (priv->file_list != NULL) {
+ g_slist_foreach (priv->file_list, (GFunc) g_object_unref, NULL);
+ g_slist_free (priv->file_list);
+ priv->file_list = NULL;
+ }
+
+#ifdef HAVE_LCMS
+ if (priv->display_profile != NULL) {
+ cmsCloseProfile (priv->display_profile);
+ priv->display_profile = NULL;
+ }
+#endif
+
+ if (priv->last_save_as_folder != NULL) {
+ g_object_unref (priv->last_save_as_folder);
+ priv->last_save_as_folder = NULL;
+ }
+
+ eom_plugin_engine_garbage_collect ();
+
+ G_OBJECT_CLASS (eom_window_parent_class)->dispose (object);
+}
+
+static void
+eom_window_finalize (GObject *object)
+{
+ GList *windows = eom_application_get_windows (EOM_APP);
+
+ g_return_if_fail (EOM_IS_WINDOW (object));
+
+ eom_debug (DEBUG_WINDOW);
+
+ if (windows == NULL) {
+ eom_application_shutdown (EOM_APP);
+ } else {
+ g_list_free (windows);
+ }
+
+ G_OBJECT_CLASS (eom_window_parent_class)->finalize (object);
+}
+
+static gint
+eom_window_delete (GtkWidget *widget, GdkEventAny *event)
+{
+ EomWindow *window;
+ EomWindowPrivate *priv;
+
+ g_return_val_if_fail (EOM_IS_WINDOW (widget), FALSE);
+
+ window = EOM_WINDOW (widget);
+ priv = window->priv;
+
+ if (priv->save_job != NULL) {
+ eom_window_finish_saving (window);
+ }
+
+ if (eom_window_unsaved_images_confirm (window)) {
+ return TRUE;
+ }
+
+ gtk_widget_destroy (widget);
+
+ return TRUE;
+}
+
+static gint
+eom_window_key_press (GtkWidget *widget, GdkEventKey *event)
+{
+ GtkContainer *tbcontainer = GTK_CONTAINER ((EOM_WINDOW (widget)->priv->toolbar));
+ gint result = FALSE;
+ gboolean handle_selection = FALSE;
+
+ switch (event->keyval) {
+ case GDK_space:
+ if (event->state & GDK_CONTROL_MASK) {
+ handle_selection = TRUE;
+ break;
+ }
+ case GDK_Return:
+ if (gtk_container_get_focus_child (tbcontainer) == NULL) {
+ /* Image properties dialog case */
+ if (event->state & GDK_MOD1_MASK) {
+ result = FALSE;
+ break;
+ }
+
+ if (event->state & GDK_SHIFT_MASK) {
+ eom_window_cmd_go_prev (NULL, EOM_WINDOW (widget));
+ } else {
+ eom_window_cmd_go_next (NULL, EOM_WINDOW (widget));
+ }
+ result = TRUE;
+ }
+ break;
+ case GDK_p:
+ case GDK_P:
+ if (EOM_WINDOW (widget)->priv->mode == EOM_WINDOW_MODE_FULLSCREEN || EOM_WINDOW (widget)->priv->mode == EOM_WINDOW_MODE_SLIDESHOW) {
+ gboolean slideshow;
+
+ slideshow = EOM_WINDOW (widget)->priv->mode == EOM_WINDOW_MODE_SLIDESHOW;
+ eom_window_run_fullscreen (EOM_WINDOW (widget), !slideshow);
+ }
+ break;
+ case GDK_Q:
+ case GDK_q:
+ case GDK_Escape:
+ if (EOM_WINDOW (widget)->priv->mode == EOM_WINDOW_MODE_FULLSCREEN) {
+ eom_window_stop_fullscreen (EOM_WINDOW (widget), FALSE);
+ } else if (EOM_WINDOW (widget)->priv->mode == EOM_WINDOW_MODE_SLIDESHOW) {
+ eom_window_stop_fullscreen (EOM_WINDOW (widget), TRUE);
+ } else {
+ eom_window_cmd_close_window (NULL, EOM_WINDOW (widget));
+ return TRUE;
+ }
+ break;
+ case GDK_Left:
+ if (event->state & GDK_MOD1_MASK) {
+ /* Alt+Left moves to previous image */
+ if (is_rtl) { /* move to next in RTL mode */
+ eom_window_cmd_go_next (NULL, EOM_WINDOW (widget));
+ } else {
+ eom_window_cmd_go_prev (NULL, EOM_WINDOW (widget));
+ }
+ result = TRUE;
+ break;
+ } /* else fall-trough is intended */
+ case GDK_Up:
+ if (eom_scroll_view_scrollbars_visible (EOM_SCROLL_VIEW (EOM_WINDOW (widget)->priv->view))) {
+ /* break to let scrollview handle the key */
+ break;
+ }
+ if (gtk_container_get_focus_child (tbcontainer) != NULL)
+ break;
+ if (!gtk_widget_get_visible (EOM_WINDOW (widget)->priv->nav)) {
+ if (is_rtl && event->keyval == GDK_Left) {
+ /* handle RTL fall-through,
+ * need to behave like GDK_Down then */
+ eom_window_cmd_go_next (NULL,
+ EOM_WINDOW (widget));
+ } else {
+ eom_window_cmd_go_prev (NULL,
+ EOM_WINDOW (widget));
+ }
+ result = TRUE;
+ break;
+ }
+ case GDK_Right:
+ if (event->state & GDK_MOD1_MASK) {
+ /* Alt+Right moves to next image */
+ if (is_rtl) { /* move to previous in RTL mode */
+ eom_window_cmd_go_prev (NULL, EOM_WINDOW (widget));
+ } else {
+ eom_window_cmd_go_next (NULL, EOM_WINDOW (widget));
+ }
+ result = TRUE;
+ break;
+ } /* else fall-trough is intended */
+ case GDK_Down:
+ if (eom_scroll_view_scrollbars_visible (EOM_SCROLL_VIEW (EOM_WINDOW (widget)->priv->view))) {
+ /* break to let scrollview handle the key */
+ break;
+ }
+ if (gtk_container_get_focus_child (tbcontainer) != NULL)
+ break;
+ if (!gtk_widget_get_visible (EOM_WINDOW (widget)->priv->nav)) {
+ if (is_rtl && event->keyval == GDK_Right) {
+ /* handle RTL fall-through,
+ * need to behave like GDK_Up then */
+ eom_window_cmd_go_prev (NULL,
+ EOM_WINDOW (widget));
+ } else {
+ eom_window_cmd_go_next (NULL,
+ EOM_WINDOW (widget));
+ }
+ result = TRUE;
+ break;
+ }
+ case GDK_Page_Up:
+ if (!eom_scroll_view_scrollbars_visible (EOM_SCROLL_VIEW (EOM_WINDOW (widget)->priv->view))) {
+ if (!gtk_widget_get_visible (EOM_WINDOW (widget)->priv->nav)) {
+ /* If the iconview is not visible skip to the
+ * previous image manually as it won't handle
+ * the keypress then. */
+ eom_window_cmd_go_prev (NULL,
+ EOM_WINDOW (widget));
+ result = TRUE;
+ } else
+ handle_selection = TRUE;
+ }
+ break;
+ case GDK_Page_Down:
+ if (!eom_scroll_view_scrollbars_visible (EOM_SCROLL_VIEW (EOM_WINDOW (widget)->priv->view))) {
+ if (!gtk_widget_get_visible (EOM_WINDOW (widget)->priv->nav)) {
+ /* If the iconview is not visible skip to the
+ * next image manually as it won't handle
+ * the keypress then. */
+ eom_window_cmd_go_next (NULL,
+ EOM_WINDOW (widget));
+ result = TRUE;
+ } else
+ handle_selection = TRUE;
+ }
+ break;
+ }
+
+ /* Update slideshow timeout */
+ if (result && (EOM_WINDOW (widget)->priv->mode == EOM_WINDOW_MODE_SLIDESHOW)) {
+ slideshow_set_timeout (EOM_WINDOW (widget));
+ }
+
+ if (handle_selection == TRUE && result == FALSE) {
+ gtk_widget_grab_focus (GTK_WIDGET (EOM_WINDOW (widget)->priv->thumbview));
+
+ result = gtk_widget_event (GTK_WIDGET (EOM_WINDOW (widget)->priv->thumbview),
+ (GdkEvent *) event);
+ }
+
+ /* If the focus is not in the toolbar and we still haven't handled the
+ event, give the scrollview a chance to do it. */
+ if (!gtk_container_get_focus_child (tbcontainer) && result == FALSE &&
+#if GTK_CHECK_VERSION (2, 20, 0)
+ gtk_widget_get_realized (GTK_WIDGET (EOM_WINDOW (widget)->priv->view))) {
+#else
+ GTK_WIDGET_REALIZED(GTK_WIDGET (EOM_WINDOW (widget)->priv->view))) {
+#endif
+ result = gtk_widget_event (GTK_WIDGET (EOM_WINDOW (widget)->priv->view),
+ (GdkEvent *) event);
+ }
+
+ if (result == FALSE && GTK_WIDGET_CLASS (eom_window_parent_class)->key_press_event) {
+ result = (* GTK_WIDGET_CLASS (eom_window_parent_class)->key_press_event) (widget, event);
+ }
+
+ return result;
+}
+
+static gint
+eom_window_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+ EomWindow *window = EOM_WINDOW (widget);
+ gint result = FALSE;
+
+ if (event->type == GDK_BUTTON_PRESS) {
+ switch (event->button) {
+ case 6:
+ eom_thumb_view_select_single (EOM_THUMB_VIEW (window->priv->thumbview),
+ EOM_THUMB_VIEW_SELECT_LEFT);
+ result = TRUE;
+ break;
+ case 7:
+ eom_thumb_view_select_single (EOM_THUMB_VIEW (window->priv->thumbview),
+ EOM_THUMB_VIEW_SELECT_RIGHT);
+ result = TRUE;
+ break;
+ }
+ }
+
+ if (result == FALSE && GTK_WIDGET_CLASS (eom_window_parent_class)->button_press_event) {
+ result = (* GTK_WIDGET_CLASS (eom_window_parent_class)->button_press_event) (widget, event);
+ }
+
+ return result;
+}
+
+static gboolean
+eom_window_configure_event (GtkWidget *widget, GdkEventConfigure *event)
+{
+ EomWindow *window;
+
+ g_return_val_if_fail (EOM_IS_WINDOW (widget), TRUE);
+
+ window = EOM_WINDOW (widget);
+
+ GTK_WIDGET_CLASS (eom_window_parent_class)->configure_event (widget, event);
+
+ return FALSE;
+}
+
+static gboolean
+eom_window_window_state_event (GtkWidget *widget,
+ GdkEventWindowState *event)
+{
+ EomWindow *window;
+
+ g_return_val_if_fail (EOM_IS_WINDOW (widget), TRUE);
+
+ window = EOM_WINDOW (widget);
+
+ if (event->changed_mask &
+ (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) {
+ gboolean show;
+
+ show = !(event->new_window_state &
+ (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN));
+
+ eom_statusbar_set_has_resize_grip (EOM_STATUSBAR (window->priv->statusbar),
+ show);
+ }
+
+ return FALSE;
+}
+
+static void
+eom_window_unrealize (GtkWidget *widget)
+{
+ EomWindow *window;
+
+ g_return_if_fail (EOM_IS_WINDOW (widget));
+
+ window = EOM_WINDOW (widget);
+
+ GTK_WIDGET_CLASS (eom_window_parent_class)->unrealize (widget);
+}
+
+
+static gboolean
+eom_window_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
+{
+ EomWindow *window = EOM_WINDOW (widget);
+ EomWindowPrivate *priv = window->priv;
+ gboolean fullscreen;
+
+ eom_debug (DEBUG_WINDOW);
+
+ fullscreen = priv->mode == EOM_WINDOW_MODE_FULLSCREEN ||
+ priv->mode == EOM_WINDOW_MODE_SLIDESHOW;
+
+ if (fullscreen) {
+ gtk_widget_hide_all (priv->fullscreen_popup);
+ }
+
+ return GTK_WIDGET_CLASS (eom_window_parent_class)->focus_out_event (widget, event);
+}
+
+static void
+eom_window_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EomWindow *window;
+ EomWindowPrivate *priv;
+
+ g_return_if_fail (EOM_IS_WINDOW (object));
+
+ window = EOM_WINDOW (object);
+ priv = window->priv;
+
+ switch (property_id) {
+ case PROP_STARTUP_FLAGS:
+ priv->flags = g_value_get_flags (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+eom_window_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EomWindow *window;
+ EomWindowPrivate *priv;
+
+ g_return_if_fail (EOM_IS_WINDOW (object));
+
+ window = EOM_WINDOW (object);
+ priv = window->priv;
+
+ switch (property_id) {
+ case PROP_STARTUP_FLAGS:
+ g_value_set_flags (value, priv->flags);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static GObject *
+eom_window_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+
+ object = G_OBJECT_CLASS (eom_window_parent_class)->constructor
+ (type, n_construct_properties, construct_params);
+
+ eom_window_construct_ui (EOM_WINDOW (object));
+
+ eom_plugin_engine_update_plugins_ui (EOM_WINDOW (object), TRUE);
+
+ return object;
+}
+
+static void
+eom_window_class_init (EomWindowClass *class)
+{
+ GObjectClass *g_object_class = (GObjectClass *) class;
+ GtkWidgetClass *widget_class = (GtkWidgetClass *) class;
+
+ g_object_class->constructor = eom_window_constructor;
+ g_object_class->dispose = eom_window_dispose;
+ g_object_class->finalize = eom_window_finalize;
+ g_object_class->set_property = eom_window_set_property;
+ g_object_class->get_property = eom_window_get_property;
+
+ widget_class->delete_event = eom_window_delete;
+ widget_class->key_press_event = eom_window_key_press;
+ widget_class->button_press_event = eom_window_button_press;
+ widget_class->drag_data_received = eom_window_drag_data_received;
+ widget_class->configure_event = eom_window_configure_event;
+ widget_class->window_state_event = eom_window_window_state_event;
+ widget_class->unrealize = eom_window_unrealize;
+ widget_class->focus_out_event = eom_window_focus_out_event;
+
+/**
+ * EomWindow:startup-flags:
+ *
+ * A bitwise OR of #EomStartupFlags elements, indicating how the window
+ * should behave upon creation.
+ */
+ g_object_class_install_property (g_object_class,
+ PROP_STARTUP_FLAGS,
+ g_param_spec_flags ("startup-flags",
+ NULL,
+ NULL,
+ EOM_TYPE_STARTUP_FLAGS,
+ 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+/**
+ * EomWindow::prepared:
+ * @window: the object which received the signal.
+ *
+ * The #EomWindow::prepared signal is emitted when the @window is ready
+ * to be shown.
+ */
+ signals [SIGNAL_PREPARED] =
+ g_signal_new ("prepared",
+ EOM_TYPE_WINDOW,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EomWindowClass, prepared),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_type_class_add_private (g_object_class, sizeof (EomWindowPrivate));
+}
+
+/**
+ * eom_window_new:
+ * @flags: the initialization parameters for the new window.
+ *
+ *
+ * Creates a new and empty #EomWindow. Use @flags to indicate
+ * if the window should be initialized fullscreen, in slideshow mode,
+ * and/or without the thumbnails collection visible. See #EomStartupFlags.
+ *
+ * Returns: a newly created #EomWindow.
+ **/
+GtkWidget*
+eom_window_new (EomStartupFlags flags)
+{
+ EomWindow *window;
+
+ eom_debug (DEBUG_WINDOW);
+
+ window = EOM_WINDOW (g_object_new (EOM_TYPE_WINDOW,
+ "type", GTK_WINDOW_TOPLEVEL,
+ "startup-flags", flags,
+ NULL));
+
+ return GTK_WIDGET (window);
+}
+
+static void
+eom_window_list_store_image_added (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ EomWindow *window = EOM_WINDOW (user_data);
+
+ update_image_pos (window);
+ update_action_groups_state (window);
+}
+
+static void
+eom_window_list_store_image_removed (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ gpointer user_data)
+{
+ EomWindow *window = EOM_WINDOW (user_data);
+
+ update_image_pos (window);
+ update_action_groups_state (window);
+}
+
+static void
+eom_job_model_cb (EomJobModel *job, gpointer data)
+{
+ EomWindow *window;
+ EomWindowPrivate *priv;
+ gint n_images;
+
+ eom_debug (DEBUG_WINDOW);
+
+#ifdef HAVE_EXIF
+ int i;
+ EomImage *image;
+#endif
+
+ g_return_if_fail (EOM_IS_WINDOW (data));
+
+ window = EOM_WINDOW (data);
+ priv = window->priv;
+
+ if (priv->store != NULL) {
+ g_object_unref (priv->store);
+ priv->store = NULL;
+ }
+
+ priv->store = g_object_ref (job->store);
+
+ n_images = eom_list_store_length (EOM_LIST_STORE (priv->store));
+
+#ifdef HAVE_EXIF
+ if (mateconf_client_get_bool (priv->client, EOM_CONF_VIEW_AUTOROTATE, NULL)) {
+ for (i = 0; i < n_images; i++) {
+ image = eom_list_store_get_image_by_pos (priv->store, i);
+ eom_image_autorotate (image);
+ g_object_unref (image);
+ }
+ }
+#endif
+
+ eom_thumb_view_set_model (EOM_THUMB_VIEW (priv->thumbview), priv->store);
+
+ g_signal_connect (G_OBJECT (priv->store),
+ "row-inserted",
+ G_CALLBACK (eom_window_list_store_image_added),
+ window);
+
+ g_signal_connect (G_OBJECT (priv->store),
+ "row-deleted",
+ G_CALLBACK (eom_window_list_store_image_removed),
+ window);
+
+ if (n_images == 0) {
+ gint n_files;
+
+ priv->status = EOM_WINDOW_STATUS_NORMAL;
+ update_action_groups_state (window);
+
+ n_files = g_slist_length (priv->file_list);
+
+ if (n_files > 0) {
+ GtkWidget *message_area;
+ GFile *file = NULL;
+
+ if (n_files == 1) {
+ file = (GFile *) priv->file_list->data;
+ }
+
+ message_area = eom_no_images_error_message_area_new (file);
+
+ eom_window_set_message_area (window, message_area);
+
+ gtk_widget_show (message_area);
+ }
+
+ g_signal_emit (window, signals[SIGNAL_PREPARED], 0);
+ }
+}
+
+/**
+ * eom_window_open_file_list:
+ * @window: An #EomWindow.
+ * @file_list: A %NULL-terminated list of #GFile's.
+ *
+ * Opens a list of files, adding them to the collection in @window.
+ * Files will be checked to be readable and later filtered according
+ * with eom_list_store_add_files().
+ **/
+void
+eom_window_open_file_list (EomWindow *window, GSList *file_list)
+{
+ EomJob *job;
+
+ eom_debug (DEBUG_WINDOW);
+
+ window->priv->status = EOM_WINDOW_STATUS_INIT;
+
+ g_slist_foreach (file_list, (GFunc) g_object_ref, NULL);
+ window->priv->file_list = file_list;
+
+ job = eom_job_model_new (file_list);
+
+ g_signal_connect (job,
+ "finished",
+ G_CALLBACK (eom_job_model_cb),
+ window);
+
+ eom_job_queue_add_job (job);
+ g_object_unref (job);
+}
+
+/**
+ * eom_window_get_ui_manager:
+ * @window: An #EomWindow.
+ *
+ * Gets the #GtkUIManager that describes the UI of @window.
+ *
+ * Returns: A #GtkUIManager.
+ **/
+GtkUIManager *
+eom_window_get_ui_manager (EomWindow *window)
+{
+ g_return_val_if_fail (EOM_IS_WINDOW (window), NULL);
+
+ return window->priv->ui_mgr;
+}
+
+/**
+ * eom_window_get_mode:
+ * @window: An #EomWindow.
+ *
+ * Gets the mode of @window. See #EomWindowMode for details.
+ *
+ * Returns: An #EomWindowMode.
+ **/
+EomWindowMode
+eom_window_get_mode (EomWindow *window)
+{
+ g_return_val_if_fail (EOM_IS_WINDOW (window), EOM_WINDOW_MODE_UNKNOWN);
+
+ return window->priv->mode;
+}
+
+/**
+ * eom_window_set_mode:
+ * @window: an #EomWindow.
+ * @mode: an #EomWindowMode value.
+ *
+ * Changes the mode of @window to normal, fullscreen, or slideshow.
+ * See #EomWindowMode for details.
+ **/
+void
+eom_window_set_mode (EomWindow *window, EomWindowMode mode)
+{
+ g_return_if_fail (EOM_IS_WINDOW (window));
+
+ if (window->priv->mode == mode)
+ return;
+
+ switch (mode) {
+ case EOM_WINDOW_MODE_NORMAL:
+ eom_window_stop_fullscreen (window,
+ window->priv->mode == EOM_WINDOW_MODE_SLIDESHOW);
+ break;
+ case EOM_WINDOW_MODE_FULLSCREEN:
+ eom_window_run_fullscreen (window, FALSE);
+ break;
+ case EOM_WINDOW_MODE_SLIDESHOW:
+ eom_window_run_fullscreen (window, TRUE);
+ break;
+ case EOM_WINDOW_MODE_UNKNOWN:
+ break;
+ }
+}
+
+/**
+ * eom_window_get_store:
+ * @window: An #EomWindow.
+ *
+ * Gets the #EomListStore that contains the images in the collection
+ * of @window.
+ *
+ * Returns: an #EomListStore.
+ **/
+EomListStore *
+eom_window_get_store (EomWindow *window)
+{
+ g_return_val_if_fail (EOM_IS_WINDOW (window), NULL);
+
+ return EOM_LIST_STORE (window->priv->store);
+}
+
+/**
+ * eom_window_get_view:
+ * @window: An #EomWindow.
+ *
+ * Gets the #EomScrollView in the window.
+ *
+ * Returns: the #EomScrollView.
+ **/
+GtkWidget *
+eom_window_get_view (EomWindow *window)
+{
+ g_return_val_if_fail (EOM_IS_WINDOW (window), NULL);
+
+ return window->priv->view;
+}
+
+/**
+ * eom_window_get_sidebar:
+ * @window: An #EomWindow.
+ *
+ * Gets the sidebar widget of @window.
+ *
+ * Returns: the #EomSidebar.
+ **/
+GtkWidget *
+eom_window_get_sidebar (EomWindow *window)
+{
+ g_return_val_if_fail (EOM_IS_WINDOW (window), NULL);
+
+ return window->priv->sidebar;
+}
+
+/**
+ * eom_window_get_thumb_view:
+ * @window: an #EomWindow.
+ *
+ * Gets the thumbnails view in @window.
+ *
+ * Returns: an #EomThumbView.
+ **/
+GtkWidget *
+eom_window_get_thumb_view (EomWindow *window)
+{
+ g_return_val_if_fail (EOM_IS_WINDOW (window), NULL);
+
+ return window->priv->thumbview;
+}
+
+/**
+ * eom_window_get_thumb_nav:
+ * @window: an #EomWindow.
+ *
+ * Gets the thumbnails navigation pane in @window.
+ *
+ * Returns: an #EomThumbNav.
+ **/
+GtkWidget *
+eom_window_get_thumb_nav (EomWindow *window)
+{
+ g_return_val_if_fail (EOM_IS_WINDOW (window), NULL);
+
+ return window->priv->nav;
+}
+
+/**
+ * eom_window_get_statusbar:
+ * @window: an #EomWindow.
+ *
+ * Gets the statusbar in @window.
+ *
+ * Returns: a #EomStatusBar.
+ **/
+GtkWidget *
+eom_window_get_statusbar (EomWindow *window)
+{
+ g_return_val_if_fail (EOM_IS_WINDOW (window), NULL);
+
+ return window->priv->statusbar;
+}
+
+/**
+ * eom_window_get_image:
+ * @window: an #EomWindow.
+ *
+ * Gets the image currently displayed in @window or %NULL if
+ * no image is being displayed.
+ *
+ * Returns: an #EomImage.
+ **/
+EomImage *
+eom_window_get_image (EomWindow *window)
+{
+ g_return_val_if_fail (EOM_IS_WINDOW (window), NULL);
+
+ return window->priv->image;
+}
+
+/**
+ * eom_window_is_empty:
+ * @window: an #EomWindow.
+ *
+ * Tells whether @window is currently empty or not.
+ *
+ * Returns: %TRUE if @window has no images, %FALSE otherwise.
+ **/
+gboolean
+eom_window_is_empty (EomWindow *window)
+{
+ EomWindowPrivate *priv;
+ gboolean empty = TRUE;
+
+ eom_debug (DEBUG_WINDOW);
+
+ g_return_val_if_fail (EOM_IS_WINDOW (window), FALSE);
+
+ priv = window->priv;
+
+ if (priv->store != NULL) {
+ empty = (eom_list_store_length (EOM_LIST_STORE (priv->store)) == 0);
+ }
+
+ return empty;
+}
+
+void
+eom_window_reload_image (EomWindow *window)
+{
+ GtkWidget *view;
+
+ g_return_if_fail (EOM_IS_WINDOW (window));
+
+ if (window->priv->image == NULL)
+ return;
+
+ g_object_unref (window->priv->image);
+ window->priv->image = NULL;
+
+ view = eom_window_get_view (window);
+ eom_scroll_view_set_image (EOM_SCROLL_VIEW (view), NULL);
+
+ eom_thumb_view_select_single (EOM_THUMB_VIEW (window->priv->thumbview),
+ EOM_THUMB_VIEW_SELECT_CURRENT);
+}