* configure.in: Add test for lcms (little cms).
* Makefile.am: Add color-man.[ch]:
* color-man.[ch]: New files for color management support.
* globals.c, gqview.h, main.c, rcfile.c, typedefs.h: Add color profile
variables and option saving.
* image.[ch]: Add color profile functions.
* layout.c, layout_image.[ch]: Add color profile icon, popup menu, and
fix sort menu to use radio buttons.
* menu.c: Use radio buttons for sort menu when appropriate.
* preferences.c: Add color profile options to preferences.
* ui_menu.[ch]: Add menu_item_add_radio() for radio item menus.
* ui_misc.c: Fix gtk_table_attach() arg for vertical expansion.
* view_file_icon.c, view_file_list.c: Check for active state in sort
menu callbacks.
* README: Add info about lcms, and how to disable.
+Fri Nov 24 21:37:01 2006 John Ellis <johne@verizon.net>
+
+ * configure.in: Add test for lcms (little cms).
+ * Makefile.am: Add color-man.[ch]:
+ * color-man.[ch]: New files for color management support.
+ * globals.c, gqview.h, main.c, rcfile.c, typedefs.h: Add color profile
+ variables and option saving.
+ * image.[ch]: Add color profile functions.
+ * layout.c, layout_image.[ch]: Add color profile icon, popup menu, and
+ fix sort menu to use radio buttons.
+ * menu.c: Use radio buttons for sort menu when appropriate.
+ * preferences.c: Add color profile options to preferences.
+ * ui_menu.[ch]: Add menu_item_add_radio() for radio item menus.
+ * ui_misc.c: Fix gtk_table_attach() arg for vertical expansion.
+ * view_file_icon.c, view_file_list.c: Check for active state in sort
+ menu callbacks.
+ * README: Add info about lcms, and how to disable.
+
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
* ui_fileops.[ch]: Add path_list_lstat() to obtain a path listing that
======== Requirements
- GTK+ 2.4.x: ftp://ftp.gtk.org/pub/gtk
+ Required libraries:
+ GTK+ 2.4.x: ftp://ftp.gtk.org/pub/gtk
+
+ Optional libraries:
+ lcms, for color management support: http://www.littlecms.com
+ (disable with configure option: '--without-lcms')
======== Notes and changes for this release [section:release_notes]
Version in perenthesis indicates first appearance of feature or change.
+ (2.1.5) Add support for color profiles when lcms is installed. To
+ disable color profiles and use of lcms, run configure
+ with '--without-lcms'.
+
(2.1.1) Add support for viewing jpeg images and EXIF embedded within
raw files for Canon (.crw, .cr2) Fujifilm (.raf), and Nikon (.nef).
Note that not all cameras that support a raw format will necessarily
> cache-load.c:
> should honor enable_thumbnails setting
+ > color profiles:
+ > support profiles embedded in images
+ > add support in img-view.c
+
---
>raw + exif formats:
> [Control]+V now shows image in new window
> [Shift]+P print shortcut added to collection and img-view windows.
(fixme, forgot to add it to find dialog).
+ > add color profile page
> add blurb about moving images between collections with shift+drag
d> update icon used for window to the (not so) new icon
+ > fix gtk_table_attach use to not use FALSE for fill vertical arg.
+
> xv and xpaint are hardly used or even installed by any distro anymore - time
to remove these (and find alternates?) seems silly to only have gimp.
dnl checks for functions
AC_CHECK_FUNCS(strverscmp)
+dnl check for little cms (lcms, this test pulled from gimp)
+AC_ARG_WITH(lcms, [ --without-lcms build without lcms support])
+
+have_lcms=no
+if test "x$with_lcms" != "xno"; then
+ AC_CHECK_LIB(lcms, cmsCreate_sRGBProfile, [
+ AC_CHECK_HEADER(lcms.h,
+ have_lcms=yes, [
+ AC_CHECK_HEADER(lcms/lcms.h,
+ have_lcms=yes
+ AC_DEFINE(HAVE_LCMS_LCMS_H, 1,
+ [Define to 1 if the lcms header must be included as lcms/lcms.h]))
+ ])
+ ])
+ if test "$have_lcms" = "yes"; then
+ LCMS_LIBS="-llcms"
+ AC_DEFINE(HAVE_LCMS, 1, [define to enable use of color profiles with lcms])
+ else
+ have_lcms="no (lcms not found or unusable)"
+ fi
+else
+ have_lcms="no (lcms support disabled)"
+fi
+
+AC_SUBST(LCMS_LIBS)
+AM_CONDITIONAL(HAVE_LCMS, test "$have_lcms" = "yes")
+
ALL_LINGUAS="ar be bg ca cs da de eo es et eu fi fr hu id it ja ko nl no pl pt_BR ro ru sk sl sv th tr uk vi zh_CN.GB2312 zh_TW"
GETTEXT_PACKAGE=$PACKAGE
AC_SUBST(GETTEXT_PACKAGE)
collect-io.h \
collect-table.c \
collect-table.h \
+ color-man.c \
+ color-man.h \
dnd.c \
dnd.h \
dupe.c \
view_file_icon.c \
view_file_icon.h
-gqview_LDADD = $(GTK_LIBS) $(INTLLIBS)
+gqview_LDADD = $(GTK_LIBS) $(INTLLIBS) $(LCMS_LIBS)
EXTRA_DIST = \
$(extra_SLIK)
--- /dev/null
+/*
+ * GQview
+ * (C) 2006 John Ellis
+ *
+ * Author: John Ellis
+ *
+ * This software is released under the GNU General Public License (GNU GPL).
+ * Please read the included file COPYING for more information.
+ * This software comes with no warranty of any kind, use at your own risk!
+ */
+
+
+#include "gqview.h"
+#include "color-man.h"
+
+#include "image.h"
+#include "ui_fileops.h"
+
+
+#ifdef HAVE_LCMS
+/*** color support enabled ***/
+
+#ifdef HAVE_LCMS_LCMS_H
+ #include <lcms/lcms.h>
+#else
+ #include <lcms.h>
+#endif
+
+
+typedef struct _ColorManCache ColorManCache;
+struct _ColorManCache {
+ cmsHPROFILE profile_in;
+ cmsHPROFILE profile_out;
+ cmsHTRANSFORM transform;
+
+ ColorManProfileType profile_in_type;
+ gchar *profile_in_file;
+
+ ColorManProfileType profile_out_type;
+ gchar *profile_out_file;
+
+ gint has_alpha;
+
+ gint refcount;
+};
+
+/* pixels to transform per idle call */
+#define COLOR_MAN_CHUNK_SIZE 81900
+
+
+static void color_man_lib_init(void)
+{
+ static gint init_done = FALSE;
+
+ if (init_done) return;
+ init_done = TRUE;
+
+ cmsErrorAction(LCMS_ERROR_IGNORE);
+}
+
+
+/*
+ *-------------------------------------------------------------------
+ * color transform cache
+ *-------------------------------------------------------------------
+ */
+
+static GList *cm_cache_list = NULL;
+
+
+static void color_man_cache_ref(ColorManCache *cc)
+{
+ if (!cc) return;
+
+ cc->refcount++;
+}
+
+static void color_man_cache_unref(ColorManCache *cc)
+{
+ if (!cc) return;
+
+ cc->refcount--;
+ if (cc->refcount < 1)
+ {
+ if (cc->transform) cmsDeleteTransform(cc->transform);
+ if (cc->profile_in) cmsCloseProfile(cc->profile_in);
+ if (cc->profile_out) cmsCloseProfile(cc->profile_out);
+
+ g_free(cc->profile_in_file);
+ g_free(cc->profile_out_file);
+
+ g_free(cc);
+ }
+}
+
+static cmsHPROFILE color_man_cache_load_profile(ColorManProfileType type, const gchar *file)
+{
+ cmsHPROFILE profile = NULL;
+
+ switch (type)
+ {
+ case COLOR_PROFILE_FILE:
+ if (file)
+ {
+ gchar *pathl;
+
+ pathl = path_from_utf8(file);
+ profile = cmsOpenProfileFromFile(pathl, "r");
+ g_free(pathl);
+ }
+ break;
+ case COLOR_PROFILE_SRGB:
+ profile = cmsCreate_sRGBProfile();
+ break;
+ case COLOR_PROFILE_NONE:
+ default:
+ break;
+ }
+
+ return profile;
+}
+
+static ColorManCache *color_man_cache_new(ColorManProfileType in_type, const gchar *in_file,
+ ColorManProfileType out_type, const gchar *out_file,
+ gint has_alpha)
+{
+ ColorManCache *cc;
+
+ color_man_lib_init();
+
+ cc = g_new0(ColorManCache, 1);
+ cc->refcount = 1;
+
+ cc->profile_in_type = in_type;
+ cc->profile_in_file = g_strdup(in_file);
+
+ cc->profile_out_type = out_type;
+ cc->profile_out_file = g_strdup(out_file);
+
+ cc->has_alpha = has_alpha;
+
+ cc->profile_in = color_man_cache_load_profile(cc->profile_in_type, cc->profile_in_file);
+ cc->profile_out = color_man_cache_load_profile(cc->profile_out_type, cc->profile_out_file);
+
+ if (!cc->profile_in || !cc->profile_out)
+ {
+ if (debug) printf("failed to load color profile for %s: %d %s\n",
+ (!cc->profile_in) ? "input" : "screen",
+ (!cc->profile_in) ? cc->profile_in_type : cc->profile_out_type,
+ (!cc->profile_in) ? cc->profile_in_file : cc->profile_out_file);
+
+ color_man_cache_unref(cc);
+ return NULL;
+ }
+
+ cc->transform = cmsCreateTransform(cc->profile_in,
+ (has_alpha) ? TYPE_RGBA_8 : TYPE_RGB_8,
+ cc->profile_out,
+ (has_alpha) ? TYPE_RGBA_8 : TYPE_RGB_8,
+ INTENT_PERCEPTUAL, 0);
+
+ if (!cc->transform)
+ {
+ if (debug) printf("failed to create color profile transform\n");
+
+ color_man_cache_unref(cc);
+ return NULL;
+ }
+
+ cm_cache_list = g_list_append(cm_cache_list, cc);
+
+ return cc;
+}
+
+static void color_man_cache_free(ColorManCache *cc)
+{
+ if (!cc) return;
+
+ cm_cache_list = g_list_remove(cm_cache_list, cc);
+ color_man_cache_unref(cc);
+}
+
+static void color_man_cache_reset(void)
+{
+ while (cm_cache_list)
+ {
+ ColorManCache *cc;
+
+ cc = cm_cache_list->data;
+ color_man_cache_free(cc);
+ }
+}
+
+static ColorManCache *color_man_cache_find(ColorManProfileType in_type, const gchar *in_file,
+ ColorManProfileType out_type, const gchar *out_file,
+ gint has_alpha)
+{
+ GList *work;
+
+ work = cm_cache_list;
+ while (work)
+ {
+ ColorManCache *cc;
+ gint match = FALSE;
+
+ cc = work->data;
+ work = work->next;
+
+ if (cc->profile_in_type == in_type &&
+ cc->profile_out_type == out_type &&
+ cc->has_alpha == has_alpha)
+ {
+ match = TRUE;
+ }
+
+ if (match && cc->profile_in_type == COLOR_PROFILE_FILE)
+ {
+ match = (cc->profile_in_file && in_file &&
+ strcmp(cc->profile_in_file, in_file) == 0);
+ }
+ if (match && cc->profile_out_type == COLOR_PROFILE_FILE)
+ {
+ match = (cc->profile_out_file && out_file &&
+ strcmp(cc->profile_out_file, out_file) == 0);
+ }
+
+ if (match) return cc;
+ }
+
+ return NULL;
+}
+
+static ColorManCache *color_man_cache_get(ColorManProfileType in_type, const gchar *in_file,
+ ColorManProfileType out_type, const gchar *out_file,
+ gint has_alpha)
+{
+ ColorManCache *cc;
+
+ cc = color_man_cache_find(in_type, in_file, out_type, out_file, has_alpha);
+
+ if (!cc)
+ {
+ cc = color_man_cache_new(in_type, in_file, out_type, out_file, has_alpha);
+ }
+
+ return cc;
+}
+
+
+/*
+ *-------------------------------------------------------------------
+ * color manager
+ *-------------------------------------------------------------------
+ */
+
+static void color_man_done(ColorMan *cm, ColorManReturnType type)
+{
+ if (cm->func_done)
+ {
+ cm->func_done(cm, type, cm->func_done_data);
+ }
+}
+
+static void color_man_correct_region(ColorMan *cm, gint x, gint y, gint w, gint h,
+ gint pixbuf_width, gint pixbuf_height)
+{
+ ColorManCache *cc;
+ guchar *pix;
+ gint rs;
+ gint i;
+
+ cc = cm->profile;
+
+ pix = gdk_pixbuf_get_pixels(cm->pixbuf);
+ rs = gdk_pixbuf_get_rowstride(cm->pixbuf);
+
+ w = MIN(w, pixbuf_width - x);
+ h = MIN(h, pixbuf_height - y);
+
+ pix += x * ((cc->has_alpha) ? 4 : 3);
+ for (i = 0; i < h; i++)
+ {
+ guchar *pbuf;
+
+ pbuf = pix + ((y + i) * rs);
+ cmsDoTransform(cc->transform, pbuf, pbuf, w);
+ }
+
+ image_area_changed(cm->imd, x, y, w, h);
+}
+
+static gint color_man_idle_cb(gpointer data)
+{
+ ColorMan *cm = data;
+ gint width, height;
+ gint rh;
+
+ if (cm->pixbuf != image_get_pixbuf(cm->imd))
+ {
+ cm->idle_id = -1;
+ color_man_done(cm, COLOR_RETURN_IMAGE_CHANGED);
+ return FALSE;
+ }
+
+ width = gdk_pixbuf_get_width(cm->pixbuf);
+ height = gdk_pixbuf_get_height(cm->pixbuf);
+
+ if (cm->row > height)
+ {
+ cm->idle_id = -1;
+ color_man_done(cm, COLOR_RETURN_SUCCESS);
+ return FALSE;
+ }
+
+ rh = COLOR_MAN_CHUNK_SIZE / width + 1;
+ color_man_correct_region(cm, 0, cm->row, width, rh, width, height);
+ cm->row += rh;
+
+ return TRUE;
+}
+
+ColorMan *color_man_new(ImageWindow *imd,
+ ColorManProfileType input_type, const gchar *input_file,
+ ColorManProfileType screen_type, const gchar *screen_file,
+ ColorManDoneFunc done_func, gpointer done_data)
+{
+ ColorMan *cm;
+ GdkPixbuf *pixbuf;
+ gint has_alpha;
+
+ if (!imd) return NULL;
+ if (input_type == COLOR_PROFILE_NONE || screen_type == COLOR_PROFILE_NONE) return NULL;
+
+ pixbuf = image_get_pixbuf(imd);
+ if (!pixbuf) return NULL;
+
+ cm = g_new0(ColorMan, 1);
+ cm->imd = imd;
+ cm->pixbuf = pixbuf;
+ cm->row = 0;
+ cm->idle_id = -1;
+
+ cm->func_done = done_func;
+ cm->func_done_data = done_data;
+
+ has_alpha = gdk_pixbuf_get_has_alpha(pixbuf);
+ cm->profile = color_man_cache_get(input_type, input_file, screen_type, screen_file, has_alpha);
+ if (!cm->profile)
+ {
+ color_man_free(cm);
+ return NULL;
+ }
+
+ color_man_cache_ref(cm->profile);
+
+ cm->idle_id = g_idle_add(color_man_idle_cb, cm);
+
+ return cm;
+}
+
+void color_man_free(ColorMan *cm)
+{
+ if (!cm) return;
+
+ if (cm->idle_id != -1) g_source_remove(cm->idle_id);
+
+ color_man_cache_unref(cm->profile);
+
+ g_free(cm);
+}
+
+void color_man_update(void)
+{
+ color_man_cache_reset();
+}
+
+#else
+/*** color support not enabled ***/
+
+
+ColorMan *color_man_new(ImageWindow *imd,
+ ColorManProfileType input_type, const gchar *input_file,
+ ColorManProfileType screen_type, const gchar *screen_file,
+ ColorManDoneFunc don_func, gpointer done_data)
+{
+ /* no op */
+ return NULL;
+}
+
+void color_man_free(ColorMan *cm)
+{
+ /* no op */
+}
+
+void color_man_update(void)
+{
+ /* no op */
+}
+
+
+#endif
+
+
--- /dev/null
+/*
+ * GQview
+ * (C) 2006 John Ellis
+ *
+ * Author: John Ellis
+ *
+ * This software is released under the GNU General Public License (GNU GPL).
+ * Please read the included file COPYING for more information.
+ * This software comes with no warranty of any kind, use at your own risk!
+ */
+
+
+#ifndef COLOR_MAN_H
+#define COLOR_MAN_H
+
+typedef enum {
+ COLOR_PROFILE_NONE = 0,
+ COLOR_PROFILE_FILE,
+ COLOR_PROFILE_SRGB,
+} ColorManProfileType;
+
+typedef enum {
+ COLOR_RETURN_SUCCESS = 0,
+ COLOR_RETURN_ERROR,
+ COLOR_RETURN_IMAGE_CHANGED
+} ColorManReturnType;
+
+typedef struct _ColorMan ColorMan;
+typedef void (* ColorManDoneFunc)(ColorMan *cm, ColorManReturnType success, gpointer data);
+
+
+struct _ColorMan {
+ ImageWindow *imd;
+ GdkPixbuf *pixbuf;
+ gint row;
+
+ gpointer profile;
+
+ gint idle_id;
+
+ ColorManDoneFunc func_done;
+ gpointer func_done_data;
+};
+
+
+ColorMan *color_man_new(ImageWindow *imd,
+ ColorManProfileType input_type, const gchar *input_file,
+ ColorManProfileType screen_type, const gchar *screen_file,
+ ColorManDoneFunc done_func, gpointer done_data);
+void color_man_free(ColorMan *cm);
+
+void color_man_update(void);
+
+
+#endif
+
gint update_on_time_change = TRUE;
gint exif_rotate_enable = FALSE;
+/* color profiles */
+gint color_profile_enabled = FALSE;
+gint color_profile_input_type = 0;
+gchar *color_profile_input_file[COLOR_PROFILE_INPUTS];
+gchar *color_profile_input_name[COLOR_PROFILE_INPUTS];
+gint color_profile_screen_type = 0;
+gchar *color_profile_screen_file = NULL;
+gint color_profile_use_image = TRUE;
+
+
#define GQVIEW_EDITOR_SLOTS 10
+#define COLOR_PROFILE_INPUTS 4
+
/*
*----------------------------------------------------------------------------
* globals
extern gint update_on_time_change;
extern gint exif_rotate_enable;
+extern gint color_profile_enabled;
+extern gint color_profile_input_type;
+extern gchar *color_profile_input_file[];
+extern gchar *color_profile_input_name[];
+extern gint color_profile_screen_type;
+extern gchar *color_profile_screen_file;
+extern gint color_profile_use_image;
+
/*
*----------------------------------------------------------------------------
* main.c
#include "image-load.h"
#include "collect.h"
+#include "color-man.h"
#include "exif.h"
#include "pixbuf-renderer.h"
#include "pixbuf_util.h"
static void image_update_title(ImageWindow *imd);
+static void image_post_process(ImageWindow *imd, gint clamp);
/*
*-------------------------------------------------------------------
}
}
+static void image_post_process_color_cb(ColorMan *cm, ColorManReturnType type, gpointer data)
+{
+ ImageWindow *imd = data;
+
+ color_man_free((ColorMan *)imd->cm);
+ imd->cm = NULL;
+ imd->state |= IMAGE_STATE_COLOR_ADJ;
+
+ if (type != COLOR_RETURN_IMAGE_CHANGED)
+ {
+ image_post_process(imd, FALSE);
+ }
+}
+
+static gint image_post_process_color(ImageWindow *imd, gint start_row)
+{
+ ColorMan *cm;
+ ColorManProfileType input_type;
+ ColorManProfileType screen_type;
+ const gchar *input_file;
+ const gchar *screen_file;
+
+ if (imd->cm) return FALSE;
+
+ if (imd->color_profile_input >= 1 &&
+ imd->color_profile_input <= COLOR_PROFILE_INPUTS)
+ {
+ gint n;
+
+ n = imd->color_profile_input - 1;
+ if (!color_profile_input_file[n]) return FALSE;
+
+ input_type = COLOR_PROFILE_FILE;
+ input_file = color_profile_input_file[n];
+ }
+ else if (imd->color_profile_input == 0)
+ {
+ input_type = COLOR_PROFILE_SRGB;
+ input_file = NULL;
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ if (imd->color_profile_screen == 1 &&
+ color_profile_screen_file)
+ {
+ screen_type = COLOR_PROFILE_FILE;
+ screen_file = color_profile_screen_file;
+ }
+ else if (imd->color_profile_screen == 0)
+ {
+ screen_type = COLOR_PROFILE_SRGB;
+ screen_file = NULL;
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ cm = color_man_new(imd,
+ input_type, input_file,
+ screen_type, screen_file,
+ image_post_process_color_cb, imd);
+ if (cm)
+ {
+ if (start_row > 0) cm->row = start_row;
+
+ imd->cm = (gpointer)cm;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static void image_post_process(ImageWindow *imd, gint clamp)
{
gint exif_rotated = FALSE;
+ if (imd->color_profile_enable &&
+ !(imd->state & IMAGE_STATE_COLOR_ADJ))
+ {
+ if (image_post_process_color(imd, 0)) return;
+
+ /* fixme: note error to user */
+ imd->state |= IMAGE_STATE_COLOR_ADJ;
+ }
+
if (exif_rotate_enable && image_get_pixbuf(imd))
{
ExifData *ed;
*-------------------------------------------------------------------
*/
-static void image_post_buffer_set(ImageWindow *imd, const gchar *path, GdkPixbuf *pixbuf)
+static void image_post_buffer_set(ImageWindow *imd, const gchar *path, GdkPixbuf *pixbuf, gint color_row)
{
g_free(imd->prev_path);
if (imd->prev_pixbuf) g_object_unref(imd->prev_pixbuf);
g_object_ref(pixbuf);
imd->prev_pixbuf = pixbuf;
+ imd->prev_color_row = color_row;
}
else
{
imd->prev_path = NULL;
imd->prev_pixbuf = NULL;
+ imd->prev_color_row = -1;
}
if (debug) printf("post buffer set: %s\n", path);
imd->image_path && imd->prev_path && strcmp(imd->image_path, imd->prev_path) == 0)
{
image_change_pixbuf(imd, imd->prev_pixbuf, image_zoom_get(imd));
+ if (imd->prev_color_row >= 0)
+ {
+ image_post_process_color(imd, imd->prev_color_row);
+ }
success = TRUE;
}
else
image_loader_free(imd->il);
imd->il = NULL;
+ color_man_free((ColorMan *)imd->cm);
+ imd->cm = NULL;
+
imd->delay_alter_type = ALTER_NONE;
+
+ imd->state = IMAGE_STATE_NONE;
}
/*
GdkPixbuf *prev_pixbuf = NULL;
gchar *prev_path = NULL;
gint prev_clear = FALSE;
+ gint prev_color_row = -1;
imd->collection = cd;
imd->collection_info = info;
prev_path = g_strdup(imd->image_path);
prev_pixbuf = pixbuf;
g_object_ref(prev_pixbuf);
+
+ if (imd->cm)
+ {
+ ColorMan *cm;
+
+ cm = (ColorMan *)imd->cm;
+ prev_color_row = cm->row;
+ }
}
}
if (prev_pixbuf)
{
- image_post_buffer_set(imd, prev_path, prev_pixbuf);
+ image_post_buffer_set(imd, prev_path, prev_pixbuf, prev_color_row);
g_free(prev_path);
g_object_unref(prev_pixbuf);
}
else if (prev_clear)
{
- image_post_buffer_set(imd, NULL, NULL);
+ image_post_buffer_set(imd, NULL, NULL, -1);
}
image_update_title(imd);
source->delay_alter_type = ALTER_NONE;
}
+ imd->color_profile_enable = source->color_profile_enable;
+ imd->color_profile_input = source->color_profile_input;
+ imd->color_profile_screen = source->color_profile_screen;
+ imd->color_profile_use_image = source->color_profile_use_image;
+ color_man_free((ColorMan *)imd->cm);
+ imd->cm = NULL;
+ if (source->cm)
+ {
+ ColorMan *cm;
+
+ imd->cm = source->cm;
+ source->cm = NULL;
+
+ cm = (ColorMan *)imd->cm;
+ cm->imd = imd;
+ cm->func_done_data = imd;
+ }
+
image_loader_free(imd->read_ahead_il);
imd->read_ahead_il = source->read_ahead_il;
source->read_ahead_il = NULL;
if (imd->prev_pixbuf) g_object_unref(imd->prev_pixbuf);
imd->prev_pixbuf = source->prev_pixbuf;
source->prev_pixbuf = NULL;
+ imd->prev_color_row = source->prev_color_row;
+ source->prev_color_row = -1;
g_free(imd->prev_path);
imd->prev_path = source->prev_path;
source->prev_path = NULL;
imd->completed = source->completed;
+ imd->state = source->state;
+ source->state = IMAGE_STATE_NONE;
pixbuf_renderer_move(PIXBUF_RENDERER(imd->pr), PIXBUF_RENDERER(source->pr));
}
{
if (pixbuf_renderer_get_tiles((PixbufRenderer *)imd->pr)) return;
- if (imd->il)
+ if (imd->il || imd->cm)
{
/* still loading, wait till done */
imd->delay_alter_type = type;
pixbuf_renderer_set_color((PixbufRenderer *)imd->pr, color);
}
+void image_color_profile_set(ImageWindow *imd,
+ gint input_type, gint screen_type,
+ gint use_image)
+{
+ if (!imd) return;
+
+ if (input_type < 0 || input_type > COLOR_PROFILE_INPUTS ||
+ screen_type < 0 || screen_type > 1)
+ {
+ return;
+ }
+
+ imd->color_profile_input = input_type;
+ imd->color_profile_screen = screen_type;
+ imd->color_profile_use_image = use_image;
+}
+
+gint image_color_profile_get(ImageWindow *imd,
+ gint *input_type, gint *screen_type,
+ gint *use_image)
+{
+ if (!imd) return FALSE;
+
+ if (input_type) *input_type = imd->color_profile_input;
+ if (screen_type) *screen_type = imd->color_profile_screen;
+ if (use_image) *use_image = imd->color_profile_use_image;
+
+ return TRUE;
+}
+
+void image_color_profile_set_use(ImageWindow *imd, gint enable)
+{
+ if (!imd) return;
+
+ if (imd->color_profile_enable == enable) return;
+
+ imd->color_profile_enable = enable;
+}
+
+gint image_color_profile_get_use(ImageWindow *imd)
+{
+ if (!imd) return FALSE;
+
+ return imd->color_profile_enable;
+}
+
void image_set_delay_flip(ImageWindow *imd, gint delay)
{
if (!imd ||
image_reset(imd);
image_read_ahead_cancel(imd);
- image_post_buffer_set(imd, NULL, NULL);
+ image_post_buffer_set(imd, NULL, NULL, -1);
image_auto_refresh(imd, -1);
g_free(imd->image_path);
imd->read_ahead_path = NULL;
imd->completed = FALSE;
+ imd->state = IMAGE_STATE_NONE;
+
+ imd->color_profile_enable = FALSE;
+ imd->color_profile_input = 0;
+ imd->color_profile_screen = 0;
+ imd->color_profile_use_image = FALSE;
imd->auto_refresh_id = -1;
imd->auto_refresh_interval = -1;
void image_background_set_black(ImageWindow *imd, gint black);
void image_background_set_color(ImageWindow *imd, GdkColor *color);
+/* color profiles */
+void image_color_profile_set(ImageWindow *imd,
+ gint input_type, gint screen_type,
+ gint use_embedded);
+gint image_color_profile_get(ImageWindow *imd,
+ gint *input_type, gint *screen_type,
+ gint *use_image);
+void image_color_profile_set_use(ImageWindow *imd, gint enable);
+gint image_color_profile_get_use(ImageWindow *imd);
+
/* set delayed page flipping */
void image_set_delay_flip(ImageWindow *imd, gint delay);
/*
* GQview
- * (C) 2004 John Ellis
+ * (C) 2006 John Ellis
*
* Author: John Ellis
*
#include "menu.h"
#include "pixbuf-renderer.h"
#include "pixbuf_util.h"
+#include "utilops.h"
#include "view_dir_list.h"
#include "view_dir_tree.h"
#include "view_file_list.h"
LayoutWindow *lw;
SortType type;
+ if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) return;
+
lw = submenu_item_get_data(widget);
if (!lw) return;
return button;
}
+/*
+ *-----------------------------------------------------------------------------
+ * color profile button (and menu)
+ *-----------------------------------------------------------------------------
+ */
+
+static void layout_color_menu_enable_cb(GtkWidget *widget, gpointer data)
+{
+ LayoutWindow *lw = data;
+
+ layout_image_color_profile_set_use(lw, (!layout_image_color_profile_get_use(lw)));
+ layout_image_refresh(lw);
+}
+
+#define COLOR_MENU_KEY "color_menu_key"
+
+static void layout_color_menu_input_cb(GtkWidget *widget, gpointer data)
+{
+ LayoutWindow *lw = data;
+ gint type;
+ gint input, screen, use_image;
+
+ if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) return;
+
+ type = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), COLOR_MENU_KEY));
+ if (type < 0 || type > COLOR_PROFILE_INPUTS) return;
+
+ if (!layout_image_color_profile_get(lw, &input, &screen, &use_image)) return;
+ if (type == input) return;
+
+ layout_image_color_profile_set(lw, type, screen, use_image);
+ layout_image_refresh(lw);
+}
+
+static void layout_color_menu_screen_cb(GtkWidget *widget, gpointer data)
+{
+ LayoutWindow *lw = data;
+ gint type;
+ gint input, screen, use_image;
+
+ if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) return;
+
+ type = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), COLOR_MENU_KEY));
+ if (type < 0 || type > 1) return;
+
+ if (!layout_image_color_profile_get(lw, &input, &screen, &use_image)) return;
+ if (type == screen) return;
+
+ layout_image_color_profile_set(lw, input, type, use_image);
+ layout_image_refresh(lw);
+}
+
+static gchar *layout_color_name_parse(const gchar *name)
+{
+ gchar *result;
+ gchar *p;
+
+ if (!name) name = _("Empty");
+
+ result = g_strdup(name);
+ p = result;
+ while (*p != '\0')
+ {
+ if (*p == '_') *p = '-';
+ p++;
+ }
+ return result;
+}
+
+static void layout_color_button_press_cb(GtkWidget *widget, gpointer data)
+{
+ LayoutWindow *lw = data;
+ GtkWidget *menu;
+ GtkWidget *item;
+ gchar *buf;
+ gchar *front;
+ gchar *end;
+ gint active;
+ gint input = 0;
+ gint screen = 0;
+ gint use_image = 0;
+ gint i;
+
+#ifndef HAVE_LCMS
+ file_util_warning_dialog(_("Color profiles not supported"),
+ _("This installation of GQview was not built with support for color profiles."),
+ GTK_STOCK_DIALOG_INFO, widget);
+ return;
+#endif
+
+ active = layout_image_color_profile_get_use(lw);
+ if (!layout_image_color_profile_get(lw, &input, &screen, &use_image)) return;
+
+ menu = popup_menu_short_lived();
+
+ menu_item_add_check(menu, _("Use _color profiles"), active,
+ G_CALLBACK(layout_color_menu_enable_cb), lw);
+
+ menu_item_add_divider(menu);
+
+ front = g_strdup_printf(_("Input _%d:"), 0);
+ buf = g_strdup_printf("%s %s", front, "sRGB");
+ g_free(front);
+ item = menu_item_add_radio(menu, NULL,
+ buf, (color_profile_input_type == 0),
+ G_CALLBACK(layout_color_menu_input_cb), lw);
+ g_free(buf);
+ g_object_set_data(G_OBJECT(item), COLOR_MENU_KEY, GINT_TO_POINTER(0));
+ gtk_widget_set_sensitive(item, active);
+
+ for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
+ {
+ const gchar *name;
+
+ name = color_profile_input_name[i];
+ if (!name) name = filename_from_path(color_profile_input_file[i]);
+
+ front = g_strdup_printf(_("Input _%d:"), i + 1);
+ end = layout_color_name_parse(name);
+ buf = g_strdup_printf("%s %s", front, end);
+ g_free(front);
+ g_free(end);
+
+ item = menu_item_add_radio(menu, item,
+ buf, (i + 1 == input),
+ G_CALLBACK(layout_color_menu_input_cb), lw);
+ g_free(buf);
+ g_object_set_data(G_OBJECT(item), COLOR_MENU_KEY, GINT_TO_POINTER(i + 1));
+ gtk_widget_set_sensitive(item, active && color_profile_input_file[i]);
+ }
+
+ menu_item_add_divider(menu);
+
+ buf = g_strdup_printf("%s sRGB", _("Screen"));
+ item = menu_item_add_radio(menu, NULL,
+ buf, (screen == 0),
+ G_CALLBACK(layout_color_menu_screen_cb), lw);
+ g_free(buf);
+ g_object_set_data(G_OBJECT(item), COLOR_MENU_KEY, GINT_TO_POINTER(0));
+ gtk_widget_set_sensitive(item, active);
+
+ item = menu_item_add_radio(menu, item,
+ _("_Screen profile"), (screen == 1),
+ G_CALLBACK(layout_color_menu_screen_cb), lw);
+ g_object_set_data(G_OBJECT(item), COLOR_MENU_KEY, GINT_TO_POINTER(1));
+ gtk_widget_set_sensitive(item, active && color_profile_screen_file);
+
+ gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, GDK_CURRENT_TIME);
+}
+
+static GtkWidget *layout_color_button(LayoutWindow *lw)
+{
+ GtkWidget *button;
+ GtkWidget *image;
+ gint enable;
+
+ button = gtk_button_new();
+ image = gtk_image_new_from_stock(GTK_STOCK_SELECT_COLOR, GTK_ICON_SIZE_MENU);
+ gtk_container_add(GTK_CONTAINER(button), image);
+ gtk_widget_show(image);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(layout_color_button_press_cb), lw);
+ gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
+
+ enable = (lw->image) ? lw->image->color_profile_enable : FALSE;
+#ifndef HAVE_LCMS
+ enable = FALSE;
+#endif
+ gtk_widget_set_sensitive(image, enable);
+
+ return button;
+}
+
+
/*
*-----------------------------------------------------------------------------
* status bar
gtk_box_pack_start(GTK_BOX(hbox), lw->info_sort, FALSE, FALSE, 0);
gtk_widget_show(lw->info_sort);
+ lw->info_color = layout_color_button(lw);
+ gtk_widget_show(lw->info_color);
+
+ if (small_format) gtk_box_pack_end(GTK_BOX(hbox), lw->info_color, FALSE, FALSE, 0);
+
lw->info_status = layout_status_label(NULL, lw->info_box, TRUE, 0, (!small_format));
if (small_format)
hbox = lw->info_box;
}
lw->info_details = layout_status_label(NULL, hbox, TRUE, 0, TRUE);
+ if (!small_format) gtk_box_pack_start(GTK_BOX(hbox), lw->info_color, FALSE, FALSE, 0);
lw->info_zoom = layout_status_label(NULL, hbox, FALSE, ZOOM_LABEL_WIDTH, FALSE);
}
lw->info_box = NULL;
lw->info_progress_bar = NULL;
lw->info_sort = NULL;
+ lw->info_color = NULL;
lw->info_status = NULL;
lw->info_details = NULL;
lw->info_zoom = NULL;
/*
* GQview
- * (C) 2004 John Ellis
+ * (C) 2006 John Ellis
*
* Author: John Ellis
*
image_reload(lw->image);
}
+void layout_image_color_profile_set(LayoutWindow *lw,
+ gint input_type, gint screen_type,
+ gint use_image)
+{
+ if (!layout_valid(&lw)) return;
+
+ image_color_profile_set(lw->image, input_type, screen_type, use_image);
+}
+
+gint layout_image_color_profile_get(LayoutWindow *lw,
+ gint *input_type, gint *screen_type,
+ gint *use_image)
+{
+ if (!layout_valid(&lw)) return FALSE;
+
+ return image_color_profile_get(lw->image, input_type, screen_type, use_image);
+}
+
+void layout_image_color_profile_set_use(LayoutWindow *lw, gint enable)
+{
+ if (!layout_valid(&lw)) return;
+
+ image_color_profile_set_use(lw->image, enable);
+
+ if (lw->info_color)
+ {
+#ifndef HAVE_LCMS
+ enable = FALSE;
+#endif
+ gtk_widget_set_sensitive(GTK_BIN(lw->info_color)->child, enable);
+ }
+}
+
+gint layout_image_color_profile_get_use(LayoutWindow *lw)
+{
+ if (!layout_valid(&lw)) return FALSE;
+
+ return image_color_profile_get_use(lw->image);
+}
+
/*
*----------------------------------------------------------------------------
* list walkers
image_attach_window(lw->image, lw->window, NULL, "GQview", FALSE);
image_auto_refresh(lw->image, 0);
+
+ image_color_profile_set(lw->image,
+ color_profile_input_type, color_profile_screen_type,
+ color_profile_use_image);
+ image_color_profile_set_use(lw->image, color_profile_enabled);
}
return lw->image->widget;
/*
* GQview
- * (C) 2004 John Ellis
+ * (C) 2006 John Ellis
*
* Author: John Ellis
*
void layout_image_refresh(LayoutWindow *lw);
+void layout_image_color_profile_set(LayoutWindow *lw,
+ gint input_type, gint screen_type,
+ gint use_image);
+gint layout_image_color_profile_get(LayoutWindow *lw,
+ gint *input_type, gint *screen_type,
+ gint *use_image);
+void layout_image_color_profile_set_use(LayoutWindow *lw, gint enable);
+gint layout_image_color_profile_get_use(LayoutWindow *lw);
+
const gchar *layout_image_get_path(LayoutWindow *lw);
const gchar *layout_image_get_name(LayoutWindow *lw);
g_free(safe_delete_path);
safe_delete_path = concat_dir_and_file(homedir(), GQVIEW_RC_DIR_TRASH);
+
+ for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
+ {
+ color_profile_input_file[i] = NULL;
+ color_profile_input_name[i] = NULL;
+ }
}
static void exit_gqview_final(void)
layout_tools_float_get(NULL, &tools_float, &tools_hidden);
toolbar_hidden = layout_toolbar_hidden(NULL);
+ color_profile_enabled = layout_image_color_profile_get_use(NULL);
+ layout_image_color_profile_get(NULL,
+ &color_profile_input_type, &color_profile_screen_type,
+ &color_profile_use_image);
+
save_options();
keys_save();
return "";
}
-static void submenu_add_sort_item(GtkWidget *menu, GCallback func, SortType type,
- gint show_current, SortType show_type)
+static GtkWidget *submenu_add_sort_item(GtkWidget *menu, GtkWidget *parent,
+ GCallback func, SortType type,
+ gint show_current, SortType show_type)
{
+ GtkWidget *item;
+
if (show_current)
{
- menu_item_add_check(menu, sort_type_get_text(type), (type == show_type),
- func, GINT_TO_POINTER((gint)type));
+ item = menu_item_add_radio(menu, parent,
+ sort_type_get_text(type), (type == show_type),
+ func, GINT_TO_POINTER((gint)type));
}
else
{
- menu_item_add(menu, sort_type_get_text(type),
- func, GINT_TO_POINTER((gint)type));
+ item = menu_item_add(menu, sort_type_get_text(type),
+ func, GINT_TO_POINTER((gint)type));
}
+
+ return item;
}
GtkWidget *submenu_add_sort(GtkWidget *menu, GCallback func, gpointer data,
gint show_current, SortType type)
{
GtkWidget *submenu;
+ GtkWidget *parent;
submenu = gtk_menu_new();
g_object_set_data(G_OBJECT(submenu), "submenu_data", data);
- submenu_add_sort_item(submenu, func, SORT_NAME, show_current, type);
+ parent = submenu_add_sort_item(submenu, NULL, func, SORT_NAME, show_current, type);
#ifdef HAVE_STRVERSCMP
- submenu_add_sort_item(submenu, func, SORT_NUMBER, show_current, type);
+ submenu_add_sort_item(submenu, parent, func, SORT_NUMBER, show_current, type);
#endif
- submenu_add_sort_item(submenu, func, SORT_TIME, show_current, type);
- submenu_add_sort_item(submenu, func, SORT_SIZE, show_current, type);
- if (include_path) submenu_add_sort_item(submenu, func, SORT_PATH, show_current, type);
- if (include_none) submenu_add_sort_item(submenu, func, SORT_NONE, show_current, type);
+ submenu_add_sort_item(submenu, parent, func, SORT_TIME, show_current, type);
+ submenu_add_sort_item(submenu, parent, func, SORT_SIZE, show_current, type);
+ if (include_path) submenu_add_sort_item(submenu, parent, func, SORT_PATH, show_current, type);
+ if (include_none) submenu_add_sort_item(submenu, parent, func, SORT_NONE, show_current, type);
if (menu)
{
static gint update_on_time_change_c;
static gint exif_rotate_enable_c;
+static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
+static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
+static GtkWidget *color_profile_screen_file_entry;
+
/*
*-----------------------------------------------------------------------------
tree_descend_subdirs = tree_descend_subdirs_c;
+#ifdef HAVE_LCMS
+ for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
+ {
+ g_free(color_profile_input_name[i]);
+ color_profile_input_name[i] = NULL;
+ buf = gtk_entry_get_text(GTK_ENTRY(color_profile_input_name_entry[i]));
+ if (buf && strlen(buf) > 0) color_profile_input_name[i] = g_strdup(buf);
+
+ g_free(color_profile_input_file[i]);
+ color_profile_input_file[i] = NULL;
+ buf = gtk_entry_get_text(GTK_ENTRY(color_profile_input_file_entry[i]));
+ if (buf && strlen(buf) > 0) color_profile_input_file[i] = g_strdup(buf);
+ }
+ g_free(color_profile_screen_file);
+ color_profile_screen_file = NULL;
+ buf = gtk_entry_get_text(GTK_ENTRY(color_profile_screen_file_entry));
+ if (buf && strlen(buf) > 0) color_profile_screen_file = g_strdup(buf);
+#endif
+
l_conf = layout_config_get(layout_widget, &new_style);
if (new_style != layout_style ||
G_CALLBACK(quality_menu_cb), option_c);
gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
- GTK_EXPAND | GTK_FILL, FALSE, 0, 0);
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
gtk_widget_show(combo);
}
G_CALLBACK(thumb_size_menu_cb), NULL);
gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
- GTK_EXPAND | GTK_FILL, FALSE, 0, 0);
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
gtk_widget_show(combo);
}
gtk_widget_set_size_request(editor_name_entry[i],80,-1);
if (editor_name[i]) gtk_entry_set_text(GTK_ENTRY(editor_name_entry[i]),editor_name[i]);
gtk_table_attach(GTK_TABLE (table),editor_name_entry[i],1,2,i+1,i+2,
- GTK_FILL | GTK_EXPAND, FALSE, 0, 0);
+ GTK_FILL | GTK_EXPAND, 0, 0, 0);
gtk_widget_show(editor_name_entry[i]);
editor_command_entry[i] = gtk_entry_new();
tab_completion_add_to_entry(editor_command_entry[i], NULL, NULL);
if (editor_command[i]) gtk_entry_set_text(GTK_ENTRY(editor_command_entry[i]), editor_command[i]);
gtk_table_attach(GTK_TABLE (table),editor_command_entry[i],2,3,i+1,i+2,
- GTK_FILL | GTK_EXPAND, FALSE, 0, 0);
+ GTK_FILL | GTK_EXPAND, 0, 0, 0);
gtk_widget_show(editor_command_entry[i]);
}
pref_spin_new_int(group, _("Offscreen cache size (Mb per image):"), NULL,
0, 128, 1, tile_cache_max, &tile_cache_max_c);
+ group = pref_group_new(vbox, FALSE, _("Color profiles"), GTK_ORIENTATION_VERTICAL);
+#ifndef HAVE_LCMS
+ gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
+#endif
+
+ table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 2, FALSE, FALSE);
+ gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
+
+ label = pref_table_label(table, 0, 0, _("Type"), 0.0);
+ pref_label_bold(label, TRUE, FALSE);
+
+ label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
+ pref_label_bold(label, TRUE, FALSE);
+
+ label = pref_table_label(table, 2, 0, _("File"), 0.0);
+ pref_label_bold(label, TRUE, FALSE);
+
+ for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
+ {
+ GtkWidget *entry;
+ gchar *buf;
+
+ buf = g_strdup_printf("Input %d:", i + 1);
+ pref_table_label(table, 0, i + 1, buf, 1.0);
+ g_free(buf);
+
+ entry = gtk_entry_new();
+ gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
+ gtk_widget_set_size_request(editor_name_entry[i], 30, -1);
+ if (color_profile_input_name[i]) gtk_entry_set_text(GTK_ENTRY(entry), color_profile_input_name[i]);
+ gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
+ GTK_FILL | GTK_EXPAND, 0, 0, 0);
+ gtk_widget_show(entry);
+ color_profile_input_name_entry[i] = entry;
+
+ tabcomp = tab_completion_new(&entry, color_profile_input_file[i], NULL, NULL);
+ tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
+ gtk_widget_set_size_request(entry, 160, -1);
+ gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
+ GTK_FILL | GTK_EXPAND, 0, 0, 0);
+ gtk_widget_show(tabcomp);
+ color_profile_input_file_entry[i] = entry;
+ }
+
+ pref_table_label(table, 0, COLOR_PROFILE_INPUTS + 1, _("Screen:"), 1.0);
+ tabcomp = tab_completion_new(&color_profile_screen_file_entry,
+ color_profile_screen_file, NULL, NULL);
+ tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
+ gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
+ gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3,
+ COLOR_PROFILE_INPUTS + 1, COLOR_PROFILE_INPUTS + 2,
+ GTK_FILL | GTK_EXPAND, 0, 0, 0);
+ gtk_widget_show(tabcomp);
+
gtk_widget_show(notebook);
gtk_widget_show(configwindow);
/*
* GQview
- * (C) 2004 John Ellis
+ * (C) 2006 John Ellis
*
* Author: John Ellis
*
write_bool_option(f, "disable_filtering", file_filter_disable);
filter_write_list(f);
+ fprintf(f,"\n##### Color Profiles #####\n\n");
+
+#ifndef HAVE_LCMS
+ fprintf(f,"# NOTICE: GQview was not built with support for color profiles,\n"
+ "# color profile options will have no effect.\n\n");
+#endif
+
+ write_bool_option(f, "color_profile_enabled", color_profile_enabled);
+ write_bool_option(f, "color_profile_use_image", color_profile_use_image);
+ write_int_option(f, "color_profile_input_type", color_profile_input_type);
+ for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
+ {
+ gchar *buf;
+
+ buf = g_strdup_printf("color_profile_input_file_%d", i + 1);
+ write_char_option(f, buf, color_profile_input_file[i]);
+ g_free(buf);
+
+ buf = g_strdup_printf("color_profile_input_name_%d", i + 1);
+ write_char_option(f, buf, color_profile_input_name[i]);
+ g_free(buf);
+ }
+ fprintf(f,"\n");
+ write_int_option(f, "color_profile_screen_type", color_profile_screen_type);
+ write_char_option(f, "color_profile_screen_file_1", color_profile_screen_file);
+
fprintf(f,"\n##### External Programs #####\n");
fprintf(f,"# Maximum of 10 programs (external_1 through external_10)\n");
fprintf(f,"# format: external_n: \"menu name\" \"command line\"\n\n");
filter_parse(value_all);
}
+ /* Color Profiles */
+
+ color_profile_enabled = read_bool_option(f, option,
+ "color_profile_enabled", value, color_profile_enabled);
+ color_profile_use_image = read_bool_option(f, option,
+ "color_profile_use_image", value, color_profile_use_image);
+ color_profile_input_type = read_int_option(f, option,
+ "color_profile_input_type", value, color_profile_input_type);
+
+ if (strncasecmp(option, "color_profile_input_file_", 25) == 0)
+ {
+ i = strtol(option + 25, NULL, 0) - 1;
+ if (i >= 0 && i < COLOR_PROFILE_INPUTS)
+ {
+ color_profile_input_file[i] = read_char_option(f, option,
+ option, value, color_profile_input_file[i]);
+ }
+ }
+ if (strncasecmp(option, "color_profile_input_name_", 25) == 0)
+ {
+ i = strtol(option + 25, NULL, 0) - 1;
+ if (i >= 0 && i < COLOR_PROFILE_INPUTS)
+ {
+ color_profile_input_name[i] = read_char_option(f, option,
+ option, value, color_profile_input_name[i]);
+ }
+ }
+
+ color_profile_screen_type = read_int_option(f, option,
+ "color_profile_screen_type", value, color_profile_screen_type);
+ color_profile_screen_file = read_char_option(f, option,
+ "color_profile_screen_file_1", value, color_profile_screen_file);
+
/* External Programs */
if (strncasecmp(option, "external_", 9) == 0)
} LayoutLocation;
+typedef enum {
+ IMAGE_STATE_NONE = 0,
+ IMAGE_STATE_IMAGE = 1 << 0,
+ IMAGE_STATE_LOADING = 1 << 1,
+ IMAGE_STATE_ERROR = 1 << 2,
+ IMAGE_STATE_COLOR_ADJ = 1 << 3,
+ IMAGE_STATE_ROTATE_AUTO = 1 << 4,
+ IMAGE_STATE_ROTATE_USER = 1 << 5,
+ IMAGE_STATE_DELAY_FLIP = 1 << 6
+} ImageState;
+
typedef struct _ImageLoader ImageLoader;
typedef struct _ThumbLoader ThumbLoader;
gint title_show_zoom; /* option to include zoom in window title */
gint completed;
+ ImageState state; /* mask of IMAGE_STATE_* flags about current image */
void (*func_update)(ImageWindow *, gpointer);
void (*func_complete)(ImageWindow *, gint preload, gpointer);
CollectionData *collection;
CollectInfo *collection_info;
+ /* color profiles */
+ gint color_profile_enable;
+ gint color_profile_input;
+ gint color_profile_screen;
+ gint color_profile_use_image;
+ gpointer *cm;
+
AlterType delay_alter_type;
ImageLoader *read_ahead_il;
GdkPixbuf *prev_pixbuf;
gchar *prev_path;
+ gint prev_color_row;
gint auto_refresh_id;
gint auto_refresh_interval;
GtkWidget *info_box;
GtkWidget *info_progress_bar;
GtkWidget *info_sort;
+ GtkWidget *info_color;
GtkWidget *info_status;
GtkWidget *info_details;
GtkWidget *info_zoom;
return item;
}
+GtkWidget *menu_item_add_radio(GtkWidget *menu, GtkWidget *parent,
+ const gchar *label, gint active,
+ GCallback func, gpointer data)
+{
+ GtkWidget *item;
+ GSList *group = NULL;
+
+ if (parent) group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(parent));
+
+ item = gtk_radio_menu_item_new_with_mnemonic(group, label);
+ if (active) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), active);
+ menu_item_finish(menu, item, func, data);
+
+ return item;
+}
+
void menu_item_add_divider(GtkWidget *menu)
{
GtkWidget *item = gtk_menu_item_new();
GCallback func, gpointer data);
GtkWidget *menu_item_add_check(GtkWidget *menu, const gchar *label, gint active,
GCallback func, gpointer data);
+GtkWidget *menu_item_add_radio(GtkWidget *menu, GtkWidget *parent,
+ const gchar *label, gint active,
+ GCallback func, gpointer data);
void menu_item_add_divider(GtkWidget *menu);
/* use to avoid mnemonics, for example filenames */
}
gtk_table_attach(GTK_TABLE(table), shell, column, column + 1, row, row + 1,
- GTK_EXPAND | GTK_FILL, FALSE, 0, 0);
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
gtk_widget_show(shell);
align = gtk_alignment_new(alignment, 0.50, 0.0, 0.0);
gtk_table_attach(GTK_TABLE(table), align, column, column + 1, row, row + 1,
- GTK_FILL, FALSE, 0, 0);
+ GTK_FILL, 0, 0, 0);
gtk_widget_show(align);
label = gtk_label_new(text);
gtk_container_add(GTK_CONTAINER(align), label);
button = pref_button_new(NULL, stock_id, text, hide_stock_text, func, data);
gtk_table_attach(GTK_TABLE(table), button, column, column + 1, row, row + 1,
- GTK_FILL, FALSE, 0, 0);
+ GTK_FILL, 0, 0, 0);
gtk_widget_show(button);
return button;
{
ViewFileIcon *vfi;
SortType type;
+
+ if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) return;
vfi = submenu_item_get_data(widget);
if (!vfi) return;
{
ViewFileList *vfl;
SortType type;
+
+ if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) return;
vfl = submenu_item_get_data(widget);
if (!vfl) return;