Updated with upstream update
This commit is contained in:
@ -1195,6 +1195,7 @@ pika_undo_type_get_type (void)
|
||||
{ PIKA_UNDO_GROUP_IMAGE_VECTORS_MERGE, "PIKA_UNDO_GROUP_IMAGE_VECTORS_MERGE", "group-image-vectors-merge" },
|
||||
{ PIKA_UNDO_GROUP_IMAGE_QUICK_MASK, "PIKA_UNDO_GROUP_IMAGE_QUICK_MASK", "group-image-quick-mask" },
|
||||
{ PIKA_UNDO_GROUP_IMAGE_GRID, "PIKA_UNDO_GROUP_IMAGE_GRID", "group-image-grid" },
|
||||
{ PIKA_UNDO_GROUP_IMAGE_COLORMAP_REMAP, "PIKA_UNDO_GROUP_IMAGE_COLORMAP_REMAP", "group-image-colormap-remap" },
|
||||
{ PIKA_UNDO_GROUP_GUIDE, "PIKA_UNDO_GROUP_GUIDE", "group-guide" },
|
||||
{ PIKA_UNDO_GROUP_SAMPLE_POINT, "PIKA_UNDO_GROUP_SAMPLE_POINT", "group-sample-point" },
|
||||
{ PIKA_UNDO_GROUP_DRAWABLE, "PIKA_UNDO_GROUP_DRAWABLE", "group-drawable" },
|
||||
@ -1303,6 +1304,7 @@ pika_undo_type_get_type (void)
|
||||
{ PIKA_UNDO_GROUP_IMAGE_VECTORS_MERGE, NC_("undo-type", "Merge paths"), NULL },
|
||||
{ PIKA_UNDO_GROUP_IMAGE_QUICK_MASK, NC_("undo-type", "Quick Mask"), NULL },
|
||||
{ PIKA_UNDO_GROUP_IMAGE_GRID, NC_("undo-type", "Grid"), NULL },
|
||||
{ PIKA_UNDO_GROUP_IMAGE_COLORMAP_REMAP, NC_("undo-type", "Colormap remapping"), NULL },
|
||||
{ PIKA_UNDO_GROUP_GUIDE, NC_("undo-type", "Guide"), NULL },
|
||||
{ PIKA_UNDO_GROUP_SAMPLE_POINT, NC_("undo-type", "Sample Point"), NULL },
|
||||
{ PIKA_UNDO_GROUP_DRAWABLE, NC_("undo-type", "Layer/Channel"), NULL },
|
||||
|
@ -548,6 +548,7 @@ typedef enum /*< pdb-skip >*/
|
||||
PIKA_UNDO_GROUP_IMAGE_VECTORS_MERGE, /*< desc="Merge paths" >*/
|
||||
PIKA_UNDO_GROUP_IMAGE_QUICK_MASK, /*< desc="Quick Mask" >*/
|
||||
PIKA_UNDO_GROUP_IMAGE_GRID, /*< desc="Grid" >*/
|
||||
PIKA_UNDO_GROUP_IMAGE_COLORMAP_REMAP, /*< desc="Colormap remapping" >*/
|
||||
PIKA_UNDO_GROUP_GUIDE, /*< desc="Guide" >*/
|
||||
PIKA_UNDO_GROUP_SAMPLE_POINT, /*< desc="Sample Point" >*/
|
||||
PIKA_UNDO_GROUP_DRAWABLE, /*< desc="Layer/Channel" >*/
|
||||
|
@ -33,8 +33,10 @@
|
||||
#include "pikacontainer.h"
|
||||
#include "pikacontext.h"
|
||||
#include "pikadisplay.h"
|
||||
#include "pikadrawable.h"
|
||||
#include "pikaimage.h"
|
||||
#include "pikaprogress.h"
|
||||
#include "pikaresource.h"
|
||||
#include "pikawaitable.h"
|
||||
|
||||
#include "about.h"
|
||||
@ -325,17 +327,17 @@ pika_get_empty_display (Pika *pika)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
guint32
|
||||
GBytes *
|
||||
pika_get_display_window_id (Pika *pika,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_PIKA (pika), -1);
|
||||
g_return_val_if_fail (PIKA_IS_DISPLAY (display), -1);
|
||||
g_return_val_if_fail (PIKA_IS_PIKA (pika), NULL);
|
||||
g_return_val_if_fail (PIKA_IS_DISPLAY (display), NULL);
|
||||
|
||||
if (pika->gui.display_get_window_id)
|
||||
return pika->gui.display_get_window_id (display);
|
||||
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PikaDisplay *
|
||||
@ -407,10 +409,11 @@ gboolean
|
||||
pika_pdb_dialog_new (Pika *pika,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaContainer *container,
|
||||
GType contents_type,
|
||||
GBytes *parent_handle,
|
||||
const gchar *title,
|
||||
const gchar *callback_name,
|
||||
const gchar *object_name,
|
||||
PikaObject *object,
|
||||
...)
|
||||
{
|
||||
gboolean retval = FALSE;
|
||||
@ -418,7 +421,10 @@ pika_pdb_dialog_new (Pika *pika,
|
||||
g_return_val_if_fail (PIKA_IS_PIKA (pika), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_CONTEXT (context), FALSE);
|
||||
g_return_val_if_fail (progress == NULL || PIKA_IS_PROGRESS (progress), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_CONTAINER (container), FALSE);
|
||||
g_return_val_if_fail (g_type_is_a (contents_type, PIKA_TYPE_RESOURCE) ||
|
||||
g_type_is_a (contents_type, PIKA_TYPE_DRAWABLE), FALSE);
|
||||
g_return_val_if_fail (object == NULL ||
|
||||
g_type_is_a (G_TYPE_FROM_INSTANCE (object), contents_type), FALSE);
|
||||
g_return_val_if_fail (title != NULL, FALSE);
|
||||
g_return_val_if_fail (callback_name != NULL, FALSE);
|
||||
|
||||
@ -426,12 +432,11 @@ pika_pdb_dialog_new (Pika *pika,
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, object_name);
|
||||
va_start (args, object);
|
||||
|
||||
retval = pika->gui.pdb_dialog_new (pika, context, progress,
|
||||
container, title,
|
||||
callback_name, object_name,
|
||||
args);
|
||||
contents_type, parent_handle, title,
|
||||
callback_name, object, args);
|
||||
|
||||
va_end (args);
|
||||
}
|
||||
@ -440,27 +445,28 @@ pika_pdb_dialog_new (Pika *pika,
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_pdb_dialog_set (Pika *pika,
|
||||
PikaContainer *container,
|
||||
const gchar *callback_name,
|
||||
const gchar *object_name,
|
||||
pika_pdb_dialog_set (Pika *pika,
|
||||
GType contents_type,
|
||||
const gchar *callback_name,
|
||||
PikaObject *object,
|
||||
...)
|
||||
{
|
||||
gboolean retval = FALSE;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PIKA (pika), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_CONTAINER (container), FALSE);
|
||||
g_return_val_if_fail (g_type_is_a (contents_type, PIKA_TYPE_RESOURCE) ||
|
||||
contents_type == PIKA_TYPE_DRAWABLE, FALSE);
|
||||
g_return_val_if_fail (callback_name != NULL, FALSE);
|
||||
g_return_val_if_fail (object_name != NULL, FALSE);
|
||||
g_return_val_if_fail (object == NULL || g_type_is_a (G_TYPE_FROM_INSTANCE (object), contents_type), FALSE);
|
||||
|
||||
if (pika->gui.pdb_dialog_set)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, object_name);
|
||||
va_start (args, object);
|
||||
|
||||
retval = pika->gui.pdb_dialog_set (pika, container, callback_name,
|
||||
object_name, args);
|
||||
retval = pika->gui.pdb_dialog_set (pika, contents_type, callback_name,
|
||||
object, args);
|
||||
|
||||
va_end (args);
|
||||
}
|
||||
@ -470,15 +476,16 @@ pika_pdb_dialog_set (Pika *pika,
|
||||
|
||||
gboolean
|
||||
pika_pdb_dialog_close (Pika *pika,
|
||||
PikaContainer *container,
|
||||
GType contents_type,
|
||||
const gchar *callback_name)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_PIKA (pika), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_CONTAINER (container), FALSE);
|
||||
g_return_val_if_fail (g_type_is_a (contents_type, PIKA_TYPE_RESOURCE) ||
|
||||
contents_type == PIKA_TYPE_DRAWABLE, FALSE);
|
||||
g_return_val_if_fail (callback_name != NULL, FALSE);
|
||||
|
||||
if (pika->gui.pdb_dialog_close)
|
||||
return pika->gui.pdb_dialog_close (pika, container, callback_name);
|
||||
return pika->gui.pdb_dialog_close (pika, contents_type, callback_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ struct _PikaGui
|
||||
|
||||
PikaObject * (* get_window_strategy) (Pika *pika);
|
||||
PikaDisplay * (* get_empty_display) (Pika *pika);
|
||||
guint32 (* display_get_window_id) (PikaDisplay *display);
|
||||
GBytes * (* display_get_window_id) (PikaDisplay *display);
|
||||
PikaDisplay * (* display_create) (Pika *pika,
|
||||
PikaImage *image,
|
||||
PikaUnit unit,
|
||||
@ -77,18 +77,19 @@ struct _PikaGui
|
||||
gboolean (* pdb_dialog_new) (Pika *pika,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaContainer *container,
|
||||
GType contents_type,
|
||||
GBytes *parent_handle,
|
||||
const gchar *title,
|
||||
const gchar *callback_name,
|
||||
const gchar *object_name,
|
||||
PikaObject *object,
|
||||
va_list args);
|
||||
gboolean (* pdb_dialog_set) (Pika *pika,
|
||||
PikaContainer *container,
|
||||
GType contents_type,
|
||||
const gchar *callback_name,
|
||||
const gchar *object_name,
|
||||
PikaObject *object,
|
||||
va_list args);
|
||||
gboolean (* pdb_dialog_close) (Pika *pika,
|
||||
PikaContainer *container,
|
||||
GType contents_type,
|
||||
const gchar *callback_name);
|
||||
gboolean (* recent_list_add_file) (Pika *pika,
|
||||
GFile *file,
|
||||
@ -126,7 +127,7 @@ PikaDisplay * pika_get_display_by_id (Pika *pika,
|
||||
gint ID);
|
||||
gint pika_get_display_id (Pika *pika,
|
||||
PikaDisplay *display);
|
||||
guint32 pika_get_display_window_id (Pika *pika,
|
||||
GBytes * pika_get_display_window_id (Pika *pika,
|
||||
PikaDisplay *display);
|
||||
PikaDisplay * pika_create_display (Pika *pika,
|
||||
PikaImage *image,
|
||||
@ -175,19 +176,21 @@ GFile * pika_get_icon_theme_dir (Pika *pika);
|
||||
gboolean pika_pdb_dialog_new (Pika *pika,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaContainer *container,
|
||||
GType contents_type,
|
||||
GBytes *parent_handle,
|
||||
const gchar *title,
|
||||
const gchar *callback_name,
|
||||
const gchar *object_name,
|
||||
PikaObject *object,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
gboolean pika_pdb_dialog_set (Pika *pika,
|
||||
PikaContainer *container,
|
||||
GType contents_type,
|
||||
const gchar *callback_name,
|
||||
const gchar *object_name,
|
||||
PikaObject *object,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
gboolean pika_pdb_dialog_close (Pika *pika,
|
||||
PikaContainer *container,
|
||||
GType contents_type,
|
||||
const gchar *callback_name);
|
||||
|
||||
gboolean pika_recent_list_add_file (Pika *pika,
|
||||
GFile *file,
|
||||
const gchar *mime_type);
|
||||
|
@ -202,6 +202,7 @@ pika_container_class_init (PikaContainerClass *klass)
|
||||
klass->search = NULL;
|
||||
klass->get_unique_names = NULL;
|
||||
klass->get_child_by_name = NULL;
|
||||
klass->get_children_by_name = NULL;
|
||||
klass->get_child_by_index = NULL;
|
||||
klass->get_child_index = NULL;
|
||||
|
||||
@ -885,6 +886,34 @@ pika_container_get_unique_names (PikaContainer *container)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GList *
|
||||
pika_container_get_children_by_name (PikaContainer *container,
|
||||
const gchar *name)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_CONTAINER (container), NULL);
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
if (PIKA_CONTAINER_GET_CLASS (container)->get_children_by_name != NULL &&
|
||||
! pika_container_get_unique_names (container))
|
||||
{
|
||||
return PIKA_CONTAINER_GET_CLASS (container)->get_children_by_name (container,
|
||||
name);
|
||||
}
|
||||
else
|
||||
{
|
||||
PikaObject *child;
|
||||
|
||||
child = PIKA_CONTAINER_GET_CLASS (container)->get_child_by_name (container, name);
|
||||
|
||||
if (child != NULL)
|
||||
return g_list_prepend (NULL, child);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PikaObject *
|
||||
pika_container_get_child_by_name (PikaContainer *container,
|
||||
const gchar *name)
|
||||
|
@ -79,6 +79,8 @@ struct _PikaContainerClass
|
||||
gboolean (* get_unique_names) (PikaContainer *container);
|
||||
PikaObject * (* get_child_by_name) (PikaContainer *container,
|
||||
const gchar *name);
|
||||
GList * (* get_children_by_name) (PikaContainer *container,
|
||||
const gchar *name);
|
||||
PikaObject * (* get_child_by_index) (PikaContainer *container,
|
||||
gint index);
|
||||
gint (* get_child_index) (PikaContainer *container,
|
||||
@ -121,6 +123,8 @@ PikaObject * pika_container_search (PikaContainer *contain
|
||||
|
||||
gboolean pika_container_get_unique_names (PikaContainer *container);
|
||||
|
||||
GList * pika_container_get_children_by_name (PikaContainer *container,
|
||||
const gchar *name);
|
||||
PikaObject * pika_container_get_child_by_name (PikaContainer *container,
|
||||
const gchar *name);
|
||||
PikaObject * pika_container_get_child_by_index (PikaContainer *container,
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "pika-memsize.h"
|
||||
#include "pikadata.h"
|
||||
#include "pikaidtable.h"
|
||||
#include "pikaimage.h"
|
||||
#include "pikatag.h"
|
||||
#include "pikatagged.h"
|
||||
|
||||
@ -51,6 +52,7 @@ enum
|
||||
PROP_0,
|
||||
PROP_ID,
|
||||
PROP_FILE,
|
||||
PROP_IMAGE,
|
||||
PROP_WRITABLE,
|
||||
PROP_DELETABLE,
|
||||
PROP_MIME_TYPE
|
||||
@ -59,8 +61,10 @@ enum
|
||||
|
||||
struct _PikaDataPrivate
|
||||
{
|
||||
gint ID;
|
||||
GFile *file;
|
||||
gint ID;
|
||||
GFile *file;
|
||||
PikaImage *image;
|
||||
|
||||
GQuark mime_type;
|
||||
guint writable : 1;
|
||||
guint deletable : 1;
|
||||
@ -172,6 +176,11 @@ pika_data_class_init (PikaDataClass *klass)
|
||||
G_TYPE_FILE,
|
||||
PIKA_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_IMAGE,
|
||||
g_param_spec_object ("image", NULL, NULL,
|
||||
PIKA_TYPE_IMAGE,
|
||||
PIKA_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_WRITABLE,
|
||||
g_param_spec_boolean ("writable", NULL, NULL,
|
||||
FALSE,
|
||||
@ -268,6 +277,12 @@ pika_data_set_property (GObject *object,
|
||||
private->deletable);
|
||||
break;
|
||||
|
||||
case PROP_IMAGE:
|
||||
pika_data_set_image (data,
|
||||
g_value_get_object (value),
|
||||
private->writable,
|
||||
private->deletable);
|
||||
break;
|
||||
case PROP_WRITABLE:
|
||||
private->writable = g_value_get_boolean (value);
|
||||
break;
|
||||
@ -307,6 +322,10 @@ pika_data_get_property (GObject *object,
|
||||
g_value_set_object (value, private->file);
|
||||
break;
|
||||
|
||||
case PROP_IMAGE:
|
||||
g_value_set_object (value, private->image);
|
||||
break;
|
||||
|
||||
case PROP_WRITABLE:
|
||||
g_value_set_boolean (value, private->writable);
|
||||
break;
|
||||
@ -462,7 +481,7 @@ pika_data_get_identifier (PikaTagged *tagged)
|
||||
gchar *identifier = NULL;
|
||||
gchar *collection = NULL;
|
||||
|
||||
g_return_val_if_fail (private->internal || private->file != NULL, NULL);
|
||||
g_return_val_if_fail (private->internal || private->file != NULL || private->image != NULL, NULL);
|
||||
|
||||
collection = pika_data_get_collection (data);
|
||||
/* The identifier is guaranteed to be unique because we use 2 directory
|
||||
@ -503,7 +522,7 @@ pika_data_get_collection (PikaData *data)
|
||||
PikaDataPrivate *private = PIKA_DATA_GET_PRIVATE (data);
|
||||
gchar *collection = NULL;
|
||||
|
||||
g_return_val_if_fail (private->internal || private->file != NULL, NULL);
|
||||
g_return_val_if_fail (private->internal || private->file != NULL || private->image != NULL, NULL);
|
||||
|
||||
if (private->file)
|
||||
{
|
||||
@ -551,6 +570,10 @@ pika_data_get_collection (PikaData *data)
|
||||
|
||||
g_free (path);
|
||||
}
|
||||
else if (private->image)
|
||||
{
|
||||
collection = g_strdup_printf ("[image-id-%d]", pika_image_get_id (private->image));
|
||||
}
|
||||
else if (private->internal)
|
||||
{
|
||||
collection = g_strdup (private->collection);
|
||||
@ -603,7 +626,7 @@ pika_data_save (PikaData *data,
|
||||
|
||||
g_return_val_if_fail (private->writable == TRUE, FALSE);
|
||||
|
||||
if (private->internal)
|
||||
if (private->internal || private->image != NULL)
|
||||
{
|
||||
private->dirty = FALSE;
|
||||
return TRUE;
|
||||
@ -862,6 +885,8 @@ pika_data_set_file (PikaData *data,
|
||||
if (private->internal)
|
||||
return;
|
||||
|
||||
g_return_if_fail (private->image == NULL);
|
||||
|
||||
g_set_object (&private->file, file);
|
||||
|
||||
private->writable = FALSE;
|
||||
@ -937,6 +962,53 @@ pika_data_get_file (PikaData *data)
|
||||
return private->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_data_set_image:
|
||||
* @data: A #PikaData object
|
||||
* @image: Image to assign to @data.
|
||||
* @writable: %TRUE if we want to be able to write to this file.
|
||||
* @deletable: %TRUE if we want to be able to delete this file.
|
||||
*
|
||||
* This function assigns an image to @data. This can only be done if no file has
|
||||
* been assigned (a non-internal data can be attached either to a file or to an
|
||||
* image).
|
||||
**/
|
||||
void
|
||||
pika_data_set_image (PikaData *data,
|
||||
PikaImage *image,
|
||||
gboolean writable,
|
||||
gboolean deletable)
|
||||
{
|
||||
PikaDataPrivate *private;
|
||||
|
||||
g_return_if_fail (PIKA_IS_DATA (data));
|
||||
g_return_if_fail (PIKA_IS_IMAGE (image));
|
||||
|
||||
private = PIKA_DATA_GET_PRIVATE (data);
|
||||
|
||||
if (private->internal)
|
||||
return;
|
||||
|
||||
g_return_if_fail (private->file == NULL);
|
||||
|
||||
g_set_object (&private->image, image);
|
||||
|
||||
private->writable = writable ? TRUE : FALSE;
|
||||
private->deletable = deletable ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
PikaImage *
|
||||
pika_data_get_image (PikaData *data)
|
||||
{
|
||||
PikaDataPrivate *private;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_DATA (data), NULL);
|
||||
|
||||
private = PIKA_DATA_GET_PRIVATE (data);
|
||||
|
||||
return private->image;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_data_create_filename:
|
||||
* @data: a #Pikadata object.
|
||||
|
@ -102,6 +102,11 @@ void pika_data_set_file (PikaData *data,
|
||||
gboolean writable,
|
||||
gboolean deletable);
|
||||
GFile * pika_data_get_file (PikaData *data);
|
||||
void pika_data_set_image (PikaData *data,
|
||||
PikaImage *image,
|
||||
gboolean writable,
|
||||
gboolean deletable);
|
||||
PikaImage * pika_data_get_image (PikaData *data);
|
||||
|
||||
void pika_data_create_filename (PikaData *data,
|
||||
GFile *dest_dir);
|
||||
|
@ -403,6 +403,9 @@ pika_data_factory_real_data_save (PikaDataFactory *factory)
|
||||
PikaData *data = list->data;
|
||||
GError *error = NULL;
|
||||
|
||||
if (pika_data_get_image (data))
|
||||
continue;
|
||||
|
||||
if (! pika_data_get_file (data))
|
||||
pika_data_create_filename (data, writable_dir);
|
||||
|
||||
@ -460,6 +463,7 @@ pika_data_factory_real_data_duplicate (PikaDataFactory *factory,
|
||||
gint copy_len;
|
||||
gint number;
|
||||
gchar *new_name;
|
||||
GError *error = NULL;
|
||||
|
||||
ext = strrchr (name, '#');
|
||||
copy_len = strlen (_("copy"));
|
||||
@ -479,8 +483,12 @@ pika_data_factory_real_data_duplicate (PikaDataFactory *factory,
|
||||
|
||||
pika_object_take_name (PIKA_OBJECT (new_data), new_name);
|
||||
|
||||
if (! pika_data_factory_data_save_single (factory, new_data, &error))
|
||||
g_critical ("%s: data saving failed: %s", G_STRFUNC, error->message);
|
||||
|
||||
pika_container_add (priv->container, PIKA_OBJECT (new_data));
|
||||
g_object_unref (new_data);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
return new_data;
|
||||
@ -674,8 +682,14 @@ pika_data_factory_data_new (PikaDataFactory *factory,
|
||||
|
||||
if (data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (! pika_data_factory_data_save_single (factory, data, &error))
|
||||
g_critical ("%s: data saving failed: %s", G_STRFUNC, error->message);
|
||||
|
||||
pika_container_add (priv->container, PIKA_OBJECT (data));
|
||||
g_object_unref (data);
|
||||
g_clear_error (&error);
|
||||
|
||||
return data;
|
||||
}
|
||||
@ -750,7 +764,7 @@ pika_data_factory_data_save_single (PikaDataFactory *factory,
|
||||
g_return_val_if_fail (PIKA_IS_DATA (data), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
if (! pika_data_is_dirty (data))
|
||||
if (! pika_data_is_dirty (data) || pika_data_get_image (data))
|
||||
return TRUE;
|
||||
|
||||
if (! pika_data_get_file (data))
|
||||
|
@ -31,25 +31,43 @@
|
||||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "config/pikageglconfig.h"
|
||||
|
||||
#include "gegl/pika-babl.h"
|
||||
#include "gegl/pika-gegl-loops.h"
|
||||
|
||||
#include "pika.h"
|
||||
#include "pikacontainer.h"
|
||||
#include "pikadatafactory.h"
|
||||
#include "pikadrawable.h"
|
||||
#include "pikaimage.h"
|
||||
#include "pikaimage-colormap.h"
|
||||
#include "pikaimage-private.h"
|
||||
#include "pikaimage-undo.h"
|
||||
#include "pikaimage-undo-push.h"
|
||||
#include "pikapalette.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GeglBuffer *buffer;
|
||||
const Babl *format;
|
||||
|
||||
/* Shared by jobs. */
|
||||
gboolean *found;
|
||||
GRWLock *lock;
|
||||
} IndexUsedJobData;
|
||||
|
||||
|
||||
/* local function prototype */
|
||||
|
||||
static void pika_image_colormap_set_palette_entry (PikaImage *image,
|
||||
const PikaRGB *color,
|
||||
gint index);
|
||||
static void pika_image_colormap_set_palette_entry (PikaImage *image,
|
||||
const PikaRGB *color,
|
||||
gint index);
|
||||
static void pika_image_colormap_thread_is_index_used (IndexUsedJobData *data,
|
||||
gint index);
|
||||
|
||||
|
||||
/* public functions */
|
||||
@ -80,7 +98,7 @@ pika_image_colormap_init (PikaImage *image)
|
||||
|
||||
pika_palette_set_columns (private->palette, 16);
|
||||
|
||||
pika_data_make_internal (PIKA_DATA (private->palette), palette_id);
|
||||
pika_data_set_image (PIKA_DATA (private->palette), image, TRUE, FALSE);
|
||||
|
||||
palettes = pika_data_factory_get_container (image->pika->palette_factory);
|
||||
|
||||
@ -319,9 +337,8 @@ pika_image_set_colormap (PikaImage *image,
|
||||
pika_image_colormap_set_palette_entry (image, &color, i);
|
||||
}
|
||||
|
||||
pika_data_thaw (PIKA_DATA (private->palette));
|
||||
|
||||
pika_image_colormap_changed (image, -1);
|
||||
pika_data_thaw (PIKA_DATA (private->palette));
|
||||
}
|
||||
|
||||
void
|
||||
@ -347,6 +364,45 @@ pika_image_unset_colormap (PikaImage *image,
|
||||
pika_image_colormap_changed (image, -1);
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_image_colormap_is_index_used (PikaImage *image,
|
||||
gint color_index)
|
||||
{
|
||||
GList *layers;
|
||||
GList *iter;
|
||||
GThreadPool *pool;
|
||||
GRWLock lock;
|
||||
gboolean found = FALSE;
|
||||
gint num_processors;
|
||||
|
||||
g_rw_lock_init (&lock);
|
||||
num_processors = PIKA_GEGL_CONFIG (image->pika->config)->num_processors;
|
||||
layers = pika_image_get_layer_list (image);
|
||||
|
||||
pool = g_thread_pool_new_full ((GFunc) pika_image_colormap_thread_is_index_used,
|
||||
GINT_TO_POINTER (color_index),
|
||||
(GDestroyNotify) g_free,
|
||||
num_processors, TRUE, NULL);
|
||||
for (iter = layers; iter; iter = g_list_next (iter))
|
||||
{
|
||||
IndexUsedJobData *job_data;
|
||||
|
||||
job_data = g_malloc (sizeof (IndexUsedJobData ));
|
||||
job_data->buffer = pika_drawable_get_buffer (iter->data);
|
||||
job_data->format = pika_drawable_get_format_without_alpha (iter->data);
|
||||
job_data->found = &found;
|
||||
job_data->lock = &lock;
|
||||
|
||||
g_thread_pool_push (pool, job_data, NULL);
|
||||
}
|
||||
|
||||
g_thread_pool_free (pool, FALSE, TRUE);
|
||||
g_rw_lock_clear (&lock);
|
||||
g_list_free (layers);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void
|
||||
pika_image_get_colormap_entry (PikaImage *image,
|
||||
gint color_index,
|
||||
@ -420,6 +476,57 @@ pika_image_add_colormap_entry (PikaImage *image,
|
||||
pika_image_colormap_changed (image, -1);
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_image_delete_colormap_entry (PikaImage *image,
|
||||
gint color_index,
|
||||
gboolean push_undo)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_IMAGE (image), FALSE);
|
||||
|
||||
if (! pika_image_colormap_is_index_used (image, color_index))
|
||||
{
|
||||
PikaImagePrivate *private;
|
||||
PikaPaletteEntry *entry;
|
||||
GList *layers;
|
||||
GList *iter;
|
||||
|
||||
if (push_undo)
|
||||
{
|
||||
pika_image_undo_group_start (image, PIKA_UNDO_GROUP_IMAGE_COLORMAP_REMAP,
|
||||
C_("undo-type", "Delete Colormap entry"));
|
||||
|
||||
pika_image_undo_push_image_colormap (image, NULL);
|
||||
}
|
||||
|
||||
private = PIKA_IMAGE_GET_PRIVATE (image);
|
||||
layers = pika_image_get_layer_list (image);
|
||||
|
||||
for (iter = layers; iter; iter = g_list_next (iter))
|
||||
{
|
||||
if (push_undo)
|
||||
pika_image_undo_push_drawable_mod (image, NULL, iter->data, TRUE);
|
||||
|
||||
pika_gegl_shift_index (pika_drawable_get_buffer (iter->data), NULL,
|
||||
pika_drawable_get_format (iter->data),
|
||||
color_index, -1);
|
||||
}
|
||||
|
||||
entry = pika_palette_get_entry (private->palette, color_index);
|
||||
pika_palette_delete_entry (private->palette, entry);
|
||||
|
||||
g_list_free (layers);
|
||||
|
||||
if (push_undo)
|
||||
pika_image_undo_group_end (image);
|
||||
|
||||
pika_image_colormap_changed (image, -1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
@ -442,3 +549,22 @@ pika_image_colormap_set_palette_entry (PikaImage *image,
|
||||
|
||||
pika_palette_set_entry (private->palette, index, name, color);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_image_colormap_thread_is_index_used (IndexUsedJobData *data,
|
||||
gint index)
|
||||
{
|
||||
g_rw_lock_reader_lock (data->lock);
|
||||
if (*data->found)
|
||||
{
|
||||
g_rw_lock_reader_unlock (data->lock);
|
||||
return;
|
||||
}
|
||||
g_rw_lock_reader_unlock (data->lock);
|
||||
if (pika_gegl_is_index_used (data->buffer, NULL, data->format, index))
|
||||
{
|
||||
g_rw_lock_writer_lock (data->lock);
|
||||
*data->found = TRUE;
|
||||
g_rw_lock_writer_unlock (data->lock);
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,9 @@ void pika_image_set_colormap (PikaImage *image,
|
||||
void pika_image_unset_colormap (PikaImage *image,
|
||||
gboolean push_undo);
|
||||
|
||||
gboolean pika_image_colormap_is_index_used (PikaImage *image,
|
||||
gint color_index);
|
||||
|
||||
void pika_image_get_colormap_entry (PikaImage *image,
|
||||
gint color_index,
|
||||
PikaRGB *color);
|
||||
@ -59,6 +62,9 @@ void pika_image_set_colormap_entry (PikaImage *image,
|
||||
|
||||
void pika_image_add_colormap_entry (PikaImage *image,
|
||||
const PikaRGB *color);
|
||||
gboolean pika_image_delete_colormap_entry (PikaImage *image,
|
||||
gint color_index,
|
||||
gboolean push_undo);
|
||||
|
||||
|
||||
#endif /* __PIKA_IMAGE_COLORMAP_H__ */
|
||||
|
@ -24,17 +24,22 @@
|
||||
#include <cairo.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
#include <gexiv2/gexiv2.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikacolor/pikacolor.h"
|
||||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "pika.h"
|
||||
#include "pikaimage.h"
|
||||
#include "pikaimage-color-profile.h"
|
||||
#include "pikaimage-metadata.h"
|
||||
#include "pikaimage-private.h"
|
||||
#include "pikaimage-rotate.h"
|
||||
#include "pikaimage-undo.h"
|
||||
#include "pikaimage-undo-push.h"
|
||||
#include "pikalayer-new.h"
|
||||
|
||||
|
||||
/* public functions */
|
||||
@ -186,3 +191,110 @@ pika_image_metadata_update_colorspace (PikaImage *image)
|
||||
pika_metadata_set_colorspace (metadata, space);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_image_metadata_load_thumbnail:
|
||||
* @pika: The #Pika object.
|
||||
* @file: A #GFile image.
|
||||
* @full_image_width: the width of the full image (not the thumbnail).
|
||||
* @full_image_height: the height of the full image (not the thumbnail).
|
||||
* @error: Return location for error message
|
||||
*
|
||||
* Retrieves a thumbnail from metadata in @file if present.
|
||||
* It does not need to actually load the full image, only the metadata through
|
||||
* GExiv2, which makes it fast.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): a #PikaImage of the @file thumbnail.
|
||||
*/
|
||||
PikaImage *
|
||||
pika_image_metadata_load_thumbnail (Pika *pika,
|
||||
GFile *file,
|
||||
gint *full_image_width,
|
||||
gint *full_image_height,
|
||||
const Babl **format,
|
||||
GError **error)
|
||||
{
|
||||
PikaMetadata *metadata;
|
||||
GInputStream *input_stream;
|
||||
GdkPixbuf *pixbuf;
|
||||
guint8 *thumbnail_buffer;
|
||||
gint thumbnail_size;
|
||||
PikaImage *image = NULL;
|
||||
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
metadata = pika_metadata_load_from_file (file, error);
|
||||
if (! metadata)
|
||||
return NULL;
|
||||
|
||||
if (! gexiv2_metadata_get_exif_thumbnail (GEXIV2_METADATA (metadata),
|
||||
&thumbnail_buffer,
|
||||
&thumbnail_size))
|
||||
{
|
||||
g_object_unref (metadata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
input_stream = g_memory_input_stream_new_from_data (thumbnail_buffer,
|
||||
thumbnail_size,
|
||||
(GDestroyNotify) g_free);
|
||||
pixbuf = gdk_pixbuf_new_from_stream (input_stream, NULL, error);
|
||||
g_object_unref (input_stream);
|
||||
|
||||
if (pixbuf)
|
||||
{
|
||||
PikaLayer *layer;
|
||||
|
||||
image = pika_image_new (pika,
|
||||
gdk_pixbuf_get_width (pixbuf),
|
||||
gdk_pixbuf_get_height (pixbuf),
|
||||
PIKA_RGB, PIKA_PRECISION_U8_NON_LINEAR);
|
||||
pika_image_undo_disable (image);
|
||||
|
||||
/* XXX This is possibly wrong, because an image of a given color space may
|
||||
* have a thumbnail stored in a different colorspace. This is even more
|
||||
* true with PIKA which always exports RGB thumbnails (see code in
|
||||
* pika_image_metadata_save_filter()), even for say grayscale images.
|
||||
* Nevertheless other software may store thumbnail using the same
|
||||
* colorspace.
|
||||
*/
|
||||
*format = pika_pixbuf_get_format (pixbuf);
|
||||
layer = pika_layer_new_from_pixbuf (pixbuf, image,
|
||||
pika_image_get_layer_format (image, FALSE),
|
||||
/* No need to localize; this image is short-lived. */
|
||||
"Background",
|
||||
PIKA_OPACITY_OPAQUE,
|
||||
pika_image_get_default_new_layer_mode (image));
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
pika_image_add_layer (image, layer, NULL, 0, FALSE);
|
||||
|
||||
pika_image_apply_metadata_orientation (image, pika_get_user_context (pika), metadata, NULL);
|
||||
}
|
||||
|
||||
/* This is the unoriented dimensions. Should we switch when there is a 90 or
|
||||
* 270 degree rotation? We don't actually know if the metadata orientation is
|
||||
* correct.
|
||||
*/
|
||||
*full_image_width = gexiv2_metadata_get_pixel_width (GEXIV2_METADATA (metadata));
|
||||
*full_image_height = gexiv2_metadata_get_pixel_height (GEXIV2_METADATA (metadata));
|
||||
|
||||
if (*full_image_width < 1 || *full_image_height < 1)
|
||||
{
|
||||
/* Dimensions stored in metadata might be less accurate, yet it's still
|
||||
* informational.
|
||||
*/
|
||||
*full_image_width = gexiv2_metadata_try_get_metadata_pixel_width (GEXIV2_METADATA (metadata), NULL);
|
||||
*full_image_height = gexiv2_metadata_try_get_metadata_pixel_width (GEXIV2_METADATA (metadata), NULL);
|
||||
}
|
||||
if (*full_image_width < 1 || *full_image_height < 1)
|
||||
{
|
||||
*full_image_width = 0;
|
||||
*full_image_height = 0;
|
||||
}
|
||||
|
||||
g_object_unref (metadata);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
@ -33,5 +33,12 @@ void pika_image_metadata_update_bits_per_sample (PikaImage *image);
|
||||
void pika_image_metadata_update_resolution (PikaImage *image);
|
||||
void pika_image_metadata_update_colorspace (PikaImage *image);
|
||||
|
||||
PikaImage * pika_image_metadata_load_thumbnail (Pika *pika,
|
||||
GFile *file,
|
||||
gint *full_image_width,
|
||||
gint *full_image_height,
|
||||
const Babl **format,
|
||||
GError **error);
|
||||
|
||||
|
||||
#endif /* __PIKA_IMAGE_METADATA_H__ */
|
||||
|
@ -282,6 +282,17 @@ pika_image_import_rotation_metadata (PikaImage *image,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pika_image_apply_metadata_orientation (PikaImage *image,
|
||||
PikaContext *context,
|
||||
PikaMetadata *metadata,
|
||||
PikaProgress *progress)
|
||||
{
|
||||
pika_image_metadata_rotate (image, context,
|
||||
gexiv2_metadata_try_get_orientation (GEXIV2_METADATA (metadata), NULL),
|
||||
progress);
|
||||
}
|
||||
|
||||
|
||||
/* Private Functions */
|
||||
|
||||
|
@ -23,14 +23,20 @@
|
||||
#define __PIKA_IMAGE_ROTATE_H__
|
||||
|
||||
|
||||
void pika_image_rotate (PikaImage *image,
|
||||
PikaContext *context,
|
||||
PikaRotationType rotate_type,
|
||||
PikaProgress *progress);
|
||||
void pika_image_rotate (PikaImage *image,
|
||||
PikaContext *context,
|
||||
PikaRotationType rotate_type,
|
||||
PikaProgress *progress);
|
||||
|
||||
void pika_image_import_rotation_metadata (PikaImage *image,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
gboolean interactive);
|
||||
|
||||
void pika_image_apply_metadata_orientation (PikaImage *image,
|
||||
PikaContext *context,
|
||||
PikaMetadata *metadata,
|
||||
PikaProgress *progress);
|
||||
|
||||
void pika_image_import_rotation_metadata (PikaImage *image,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
gboolean interactive);
|
||||
|
||||
#endif /* __PIKA_IMAGE_ROTATE_H__ */
|
||||
|
@ -625,6 +625,9 @@ pika_image_undo_dirty_from_type (PikaUndoType undo_type)
|
||||
case PIKA_UNDO_GROUP_IMAGE_CONVERT:
|
||||
return PIKA_DIRTY_IMAGE | PIKA_DIRTY_DRAWABLE;
|
||||
|
||||
case PIKA_UNDO_GROUP_IMAGE_COLORMAP_REMAP:
|
||||
return PIKA_DIRTY_IMAGE | PIKA_DIRTY_DRAWABLE;
|
||||
|
||||
case PIKA_UNDO_GROUP_IMAGE_LAYERS_MERGE:
|
||||
return PIKA_DIRTY_IMAGE_STRUCTURE | PIKA_DIRTY_DRAWABLE;
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "pikacontainer.h"
|
||||
#include "pikacontext.h"
|
||||
#include "pikaimage.h"
|
||||
#include "pikaimage-metadata.h"
|
||||
#include "pikaimagefile.h"
|
||||
#include "pikapickable.h"
|
||||
#include "pikaprogress.h"
|
||||
@ -486,19 +487,37 @@ pika_imagefile_create_thumbnail (PikaImagefile *imagefile,
|
||||
if (error && *error)
|
||||
{
|
||||
g_printerr ("Info: Thumbnail load procedure failed: %s\n"
|
||||
" Falling back to file load procedure.\n",
|
||||
" Falling back to metadata or file load.\n",
|
||||
(*error)->message);
|
||||
g_clear_error (error);
|
||||
}
|
||||
|
||||
image = file_open_image (private->pika, context, progress,
|
||||
private->file,
|
||||
FALSE, NULL, PIKA_RUN_NONINTERACTIVE,
|
||||
&status, &mime_type, error);
|
||||
|
||||
image = pika_image_metadata_load_thumbnail (private->pika, private->file, &width, &height, &format, error);
|
||||
if (image)
|
||||
pika_thumbnail_set_info_from_image (private->thumbnail,
|
||||
mime_type, image);
|
||||
{
|
||||
pika_thumbnail_set_info (private->thumbnail,
|
||||
mime_type, width, height,
|
||||
format, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error && *error)
|
||||
{
|
||||
g_printerr ("Info: metadata load failed: %s\n"
|
||||
" Falling back to file load procedure.\n",
|
||||
(*error)->message);
|
||||
g_clear_error (error);
|
||||
}
|
||||
|
||||
image = file_open_image (private->pika, context, progress,
|
||||
private->file,
|
||||
FALSE, NULL, PIKA_RUN_NONINTERACTIVE,
|
||||
&status, &mime_type, error);
|
||||
|
||||
if (image)
|
||||
pika_thumbnail_set_info_from_image (private->thumbnail,
|
||||
mime_type, image);
|
||||
}
|
||||
}
|
||||
|
||||
if (image)
|
||||
|
@ -76,6 +76,8 @@ static PikaObject * pika_list_search (PikaContainer *conta
|
||||
PikaContainerSearchFunc func,
|
||||
gpointer user_data);
|
||||
static gboolean pika_list_get_unique_names (PikaContainer *container);
|
||||
static GList * pika_list_get_children_by_name (PikaContainer *container,
|
||||
const gchar *name);
|
||||
static PikaObject * pika_list_get_child_by_name (PikaContainer *container,
|
||||
const gchar *name);
|
||||
static PikaObject * pika_list_get_child_by_index (PikaContainer *container,
|
||||
@ -101,23 +103,24 @@ pika_list_class_init (PikaListClass *klass)
|
||||
PikaObjectClass *pika_object_class = PIKA_OBJECT_CLASS (klass);
|
||||
PikaContainerClass *container_class = PIKA_CONTAINER_CLASS (klass);
|
||||
|
||||
object_class->finalize = pika_list_finalize;
|
||||
object_class->set_property = pika_list_set_property;
|
||||
object_class->get_property = pika_list_get_property;
|
||||
object_class->finalize = pika_list_finalize;
|
||||
object_class->set_property = pika_list_set_property;
|
||||
object_class->get_property = pika_list_get_property;
|
||||
|
||||
pika_object_class->get_memsize = pika_list_get_memsize;
|
||||
pika_object_class->get_memsize = pika_list_get_memsize;
|
||||
|
||||
container_class->add = pika_list_add;
|
||||
container_class->remove = pika_list_remove;
|
||||
container_class->reorder = pika_list_reorder;
|
||||
container_class->clear = pika_list_clear;
|
||||
container_class->have = pika_list_have;
|
||||
container_class->foreach = pika_list_foreach;
|
||||
container_class->search = pika_list_search;
|
||||
container_class->get_unique_names = pika_list_get_unique_names;
|
||||
container_class->get_child_by_name = pika_list_get_child_by_name;
|
||||
container_class->get_child_by_index = pika_list_get_child_by_index;
|
||||
container_class->get_child_index = pika_list_get_child_index;
|
||||
container_class->add = pika_list_add;
|
||||
container_class->remove = pika_list_remove;
|
||||
container_class->reorder = pika_list_reorder;
|
||||
container_class->clear = pika_list_clear;
|
||||
container_class->have = pika_list_have;
|
||||
container_class->foreach = pika_list_foreach;
|
||||
container_class->search = pika_list_search;
|
||||
container_class->get_unique_names = pika_list_get_unique_names;
|
||||
container_class->get_children_by_name = pika_list_get_children_by_name;
|
||||
container_class->get_child_by_name = pika_list_get_child_by_name;
|
||||
container_class->get_child_by_index = pika_list_get_child_by_index;
|
||||
container_class->get_child_index = pika_list_get_child_index;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_UNIQUE_NAMES,
|
||||
g_param_spec_boolean ("unique-names",
|
||||
@ -369,6 +372,29 @@ pika_list_get_unique_names (PikaContainer *container)
|
||||
return list->unique_names;
|
||||
}
|
||||
|
||||
static GList *
|
||||
pika_list_get_children_by_name (PikaContainer *container,
|
||||
const gchar *name)
|
||||
{
|
||||
PikaList *list = PIKA_LIST (container);
|
||||
GList *children = NULL;
|
||||
GList *iter;
|
||||
|
||||
for (iter = list->queue->head; iter; iter = g_list_next (iter))
|
||||
{
|
||||
PikaObject *object = iter->data;
|
||||
|
||||
if (! strcmp (pika_object_get_name (object), name))
|
||||
{
|
||||
children = g_list_prepend (children, object);
|
||||
if (list->unique_names)
|
||||
return children;
|
||||
}
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
static PikaObject *
|
||||
pika_list_get_child_by_name (PikaContainer *container,
|
||||
const gchar *name)
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include "core-types.h"
|
||||
|
||||
#include "pika-memsize.h"
|
||||
#include "pikaimage.h"
|
||||
#include "pikaimage-undo-push.h"
|
||||
#include "pikapalette.h"
|
||||
#include "pikapalette-load.h"
|
||||
#include "pikapalette-save.h"
|
||||
@ -44,6 +46,12 @@
|
||||
|
||||
#define RGB_EPSILON 1e-6
|
||||
|
||||
enum
|
||||
{
|
||||
ENTRY_CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
@ -75,6 +83,8 @@ static gchar * pika_palette_get_description (PikaViewable *viewa
|
||||
static const gchar * pika_palette_get_extension (PikaData *data);
|
||||
static void pika_palette_copy (PikaData *data,
|
||||
PikaData *src_data);
|
||||
static void pika_palette_real_entry_changed (PikaPalette *palette,
|
||||
gint index);
|
||||
|
||||
static void pika_palette_entry_free (PikaPaletteEntry *entry);
|
||||
static gint64 pika_palette_entry_get_memsize (PikaPaletteEntry *entry,
|
||||
@ -88,6 +98,7 @@ G_DEFINE_TYPE_WITH_CODE (PikaPalette, pika_palette, PIKA_TYPE_DATA,
|
||||
|
||||
#define parent_class pika_palette_parent_class
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void
|
||||
pika_palette_class_init (PikaPaletteClass *klass)
|
||||
@ -97,6 +108,14 @@ pika_palette_class_init (PikaPaletteClass *klass)
|
||||
PikaViewableClass *viewable_class = PIKA_VIEWABLE_CLASS (klass);
|
||||
PikaDataClass *data_class = PIKA_DATA_CLASS (klass);
|
||||
|
||||
signals[ENTRY_CHANGED] = g_signal_new ("entry-changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (PikaPaletteClass, entry_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_INT);
|
||||
|
||||
object_class->finalize = pika_palette_finalize;
|
||||
|
||||
pika_object_class->get_memsize = pika_palette_get_memsize;
|
||||
@ -110,6 +129,8 @@ pika_palette_class_init (PikaPaletteClass *klass)
|
||||
data_class->save = pika_palette_save;
|
||||
data_class->get_extension = pika_palette_get_extension;
|
||||
data_class->copy = pika_palette_copy;
|
||||
|
||||
klass->entry_changed = pika_palette_real_entry_changed;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -344,6 +365,16 @@ pika_palette_copy (PikaData *data,
|
||||
pika_data_thaw (data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_palette_real_entry_changed (PikaPalette *palette,
|
||||
gint index)
|
||||
{
|
||||
PikaImage *image = pika_data_get_image (PIKA_DATA (palette));
|
||||
|
||||
if (image != NULL)
|
||||
pika_image_colormap_changed (image, index);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
pika_palette_get_checksum (PikaTagged *tagged)
|
||||
{
|
||||
@ -406,11 +437,17 @@ pika_palette_move_entry (PikaPalette *palette,
|
||||
|
||||
if (g_list_find (palette->colors, entry))
|
||||
{
|
||||
gint old_position = g_list_index (palette->colors, entry);
|
||||
|
||||
palette->colors = g_list_remove (palette->colors,
|
||||
entry);
|
||||
palette->colors = g_list_insert (palette->colors,
|
||||
entry, position);
|
||||
|
||||
if (! pika_data_is_frozen (PIKA_DATA (palette)))
|
||||
for (gint i = MIN (position, old_position); i <= MAX (position, old_position); i++)
|
||||
g_signal_emit (palette, signals[ENTRY_CHANGED], 0, i);
|
||||
|
||||
pika_data_dirty (PIKA_DATA (palette));
|
||||
}
|
||||
}
|
||||
@ -442,6 +479,10 @@ pika_palette_add_entry (PikaPalette *palette,
|
||||
|
||||
palette->n_colors += 1;
|
||||
|
||||
if (! pika_data_is_frozen (PIKA_DATA (palette)))
|
||||
for (gint i = position; i < palette->n_colors; i++)
|
||||
g_signal_emit (palette, signals[ENTRY_CHANGED], 0, i);
|
||||
|
||||
pika_data_dirty (PIKA_DATA (palette));
|
||||
|
||||
return entry;
|
||||
@ -456,12 +497,18 @@ pika_palette_delete_entry (PikaPalette *palette,
|
||||
|
||||
if (g_list_find (palette->colors, entry))
|
||||
{
|
||||
gint old_position = g_list_index (palette->colors, entry);
|
||||
|
||||
pika_palette_entry_free (entry);
|
||||
|
||||
palette->colors = g_list_remove (palette->colors, entry);
|
||||
|
||||
palette->n_colors--;
|
||||
|
||||
if (! pika_data_is_frozen (PIKA_DATA (palette)))
|
||||
for (gint i = old_position; i < palette->n_colors; i++)
|
||||
g_signal_emit (palette, signals[ENTRY_CHANGED], 0, i);
|
||||
|
||||
pika_data_dirty (PIKA_DATA (palette));
|
||||
}
|
||||
}
|
||||
@ -489,6 +536,9 @@ pika_palette_set_entry (PikaPalette *palette,
|
||||
|
||||
entry->name = g_strdup (name);
|
||||
|
||||
if (! pika_data_is_frozen (PIKA_DATA (palette)))
|
||||
g_signal_emit (palette, signals[ENTRY_CHANGED], 0, position);
|
||||
|
||||
pika_data_dirty (PIKA_DATA (palette));
|
||||
|
||||
return TRUE;
|
||||
@ -497,7 +547,8 @@ pika_palette_set_entry (PikaPalette *palette,
|
||||
gboolean
|
||||
pika_palette_set_entry_color (PikaPalette *palette,
|
||||
gint position,
|
||||
const PikaRGB *color)
|
||||
const PikaRGB *color,
|
||||
gboolean push_undo_if_image)
|
||||
{
|
||||
PikaPaletteEntry *entry;
|
||||
|
||||
@ -509,8 +560,15 @@ pika_palette_set_entry_color (PikaPalette *palette,
|
||||
if (! entry)
|
||||
return FALSE;
|
||||
|
||||
if (push_undo_if_image && pika_data_get_image (PIKA_DATA (palette)))
|
||||
pika_image_undo_push_image_colormap (pika_data_get_image (PIKA_DATA (palette)),
|
||||
C_("undo-type", "Change Colormap entry"));
|
||||
|
||||
entry->color = *color;
|
||||
|
||||
if (! pika_data_is_frozen (PIKA_DATA (palette)))
|
||||
g_signal_emit (palette, signals[ENTRY_CHANGED], 0, position);
|
||||
|
||||
pika_data_dirty (PIKA_DATA (palette));
|
||||
|
||||
return TRUE;
|
||||
@ -535,6 +593,9 @@ pika_palette_set_entry_name (PikaPalette *palette,
|
||||
|
||||
entry->name = g_strdup (name);
|
||||
|
||||
if (! pika_data_is_frozen (PIKA_DATA (palette)))
|
||||
g_signal_emit (palette, signals[ENTRY_CHANGED], 0, position);
|
||||
|
||||
pika_data_dirty (PIKA_DATA (palette));
|
||||
|
||||
return TRUE;
|
||||
|
@ -56,6 +56,9 @@ struct _PikaPalette
|
||||
struct _PikaPaletteClass
|
||||
{
|
||||
PikaDataClass parent_class;
|
||||
|
||||
void (* entry_changed) (PikaPalette *palette,
|
||||
gint index);
|
||||
};
|
||||
|
||||
|
||||
@ -85,7 +88,8 @@ gboolean pika_palette_set_entry (PikaPalette *palette,
|
||||
const PikaRGB *color);
|
||||
gboolean pika_palette_set_entry_color (PikaPalette *palette,
|
||||
gint position,
|
||||
const PikaRGB *color);
|
||||
const PikaRGB *color,
|
||||
gboolean push_undo_if_image);
|
||||
gboolean pika_palette_set_entry_name (PikaPalette *palette,
|
||||
gint position,
|
||||
const gchar *name);
|
||||
|
@ -217,7 +217,7 @@ pika_palette_mru_add (PikaPaletteMru *mru,
|
||||
/* Even though they are nearly the same color, let's make them
|
||||
* exactly equal.
|
||||
*/
|
||||
pika_palette_set_entry_color (palette, 0, color);
|
||||
pika_palette_set_entry_color (palette, 0, color, FALSE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ static void pika_pdb_progress_progress_set_value (PikaProgress *progress
|
||||
gdouble percentage);
|
||||
static gdouble pika_pdb_progress_progress_get_value (PikaProgress *progress);
|
||||
static void pika_pdb_progress_progress_pulse (PikaProgress *progress);
|
||||
static guint32 pika_pdb_progress_progress_get_window_id (PikaProgress *progress);
|
||||
static GBytes * pika_pdb_progress_progress_get_window_id (PikaProgress *progress);
|
||||
|
||||
|
||||
static GObjectClass *parent_class = NULL;
|
||||
@ -241,14 +241,13 @@ pika_pdb_progress_set_property (GObject *object,
|
||||
}
|
||||
}
|
||||
|
||||
static gdouble
|
||||
pika_pdb_progress_run_callback (PikaPdbProgress *progress,
|
||||
PikaProgressCommand command,
|
||||
const gchar *text,
|
||||
gdouble value)
|
||||
static void
|
||||
pika_pdb_progress_run_callback (PikaPdbProgress *progress,
|
||||
PikaProgressCommand command,
|
||||
const gchar *text,
|
||||
gdouble value,
|
||||
GBytes **handle)
|
||||
{
|
||||
gdouble retval = 0;
|
||||
|
||||
if (progress->callback_name && ! progress->callback_busy)
|
||||
{
|
||||
PikaValueArray *return_vals;
|
||||
@ -274,17 +273,16 @@ pika_pdb_progress_run_callback (PikaPdbProgress *progress,
|
||||
g_type_name (G_TYPE_FROM_INSTANCE (progress)));
|
||||
}
|
||||
else if (pika_value_array_length (return_vals) >= 2 &&
|
||||
G_VALUE_HOLDS_DOUBLE (pika_value_array_index (return_vals, 1)))
|
||||
handle != NULL &&
|
||||
G_VALUE_HOLDS_BOXED (pika_value_array_index (return_vals, 1)))
|
||||
{
|
||||
retval = g_value_get_double (pika_value_array_index (return_vals, 1));
|
||||
*handle = g_value_dup_boxed (pika_value_array_index (return_vals, 1));
|
||||
}
|
||||
|
||||
pika_value_array_unref (return_vals);
|
||||
|
||||
progress->callback_busy = FALSE;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static PikaProgress *
|
||||
@ -298,7 +296,7 @@ pika_pdb_progress_progress_start (PikaProgress *progress,
|
||||
{
|
||||
pika_pdb_progress_run_callback (pdb_progress,
|
||||
PIKA_PROGRESS_COMMAND_START,
|
||||
message, 0.0);
|
||||
message, 0.0, NULL);
|
||||
|
||||
pdb_progress->active = TRUE;
|
||||
pdb_progress->value = 0.0;
|
||||
@ -318,7 +316,7 @@ pika_pdb_progress_progress_end (PikaProgress *progress)
|
||||
{
|
||||
pika_pdb_progress_run_callback (pdb_progress,
|
||||
PIKA_PROGRESS_COMMAND_END,
|
||||
NULL, 0.0);
|
||||
NULL, 0.0, NULL);
|
||||
|
||||
pdb_progress->active = FALSE;
|
||||
pdb_progress->value = 0.0;
|
||||
@ -342,7 +340,7 @@ pika_pdb_progress_progress_set_text (PikaProgress *progress,
|
||||
if (pdb_progress->active)
|
||||
pika_pdb_progress_run_callback (pdb_progress,
|
||||
PIKA_PROGRESS_COMMAND_SET_TEXT,
|
||||
message, 0.0);
|
||||
message, 0.0, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -355,7 +353,7 @@ pika_pdb_progress_progress_set_value (PikaProgress *progress,
|
||||
{
|
||||
pika_pdb_progress_run_callback (pdb_progress,
|
||||
PIKA_PROGRESS_COMMAND_SET_VALUE,
|
||||
NULL, percentage);
|
||||
NULL, percentage, NULL);
|
||||
pdb_progress->value = percentage;
|
||||
}
|
||||
}
|
||||
@ -377,18 +375,19 @@ pika_pdb_progress_progress_pulse (PikaProgress *progress)
|
||||
if (pdb_progress->active)
|
||||
pika_pdb_progress_run_callback (pdb_progress,
|
||||
PIKA_PROGRESS_COMMAND_PULSE,
|
||||
NULL, 0.0);
|
||||
NULL, 0.0, NULL);
|
||||
}
|
||||
|
||||
static guint32
|
||||
static GBytes *
|
||||
pika_pdb_progress_progress_get_window_id (PikaProgress *progress)
|
||||
{
|
||||
PikaPdbProgress *pdb_progress = PIKA_PDB_PROGRESS (progress);
|
||||
GBytes *handle = NULL;
|
||||
|
||||
return (guint32)
|
||||
pika_pdb_progress_run_callback (pdb_progress,
|
||||
PIKA_PROGRESS_COMMAND_GET_WINDOW,
|
||||
NULL, 0.0);
|
||||
pika_pdb_progress_run_callback (pdb_progress,
|
||||
PIKA_PROGRESS_COMMAND_GET_WINDOW,
|
||||
NULL, 0.0, &handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
PikaPdbProgress *
|
||||
|
@ -209,7 +209,7 @@ pika_progress_pulse (PikaProgress *progress)
|
||||
progress_iface->pulse (progress);
|
||||
}
|
||||
|
||||
guint32
|
||||
GBytes *
|
||||
pika_progress_get_window_id (PikaProgress *progress)
|
||||
{
|
||||
PikaProgressInterface *progress_iface;
|
||||
@ -221,7 +221,7 @@ pika_progress_get_window_id (PikaProgress *progress)
|
||||
if (progress_iface->get_window_id)
|
||||
return progress_iface->get_window_id (progress);
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -48,7 +48,7 @@ struct _PikaProgressInterface
|
||||
gdouble (* get_value) (PikaProgress *progress);
|
||||
void (* pulse) (PikaProgress *progress);
|
||||
|
||||
guint32 (* get_window_id) (PikaProgress *progress);
|
||||
GBytes * (* get_window_id) (PikaProgress *progress);
|
||||
|
||||
gboolean (* message) (PikaProgress *progress,
|
||||
Pika *pika,
|
||||
@ -78,7 +78,7 @@ void pika_progress_set_value (PikaProgress *progress,
|
||||
gdouble pika_progress_get_value (PikaProgress *progress);
|
||||
void pika_progress_pulse (PikaProgress *progress);
|
||||
|
||||
guint32 pika_progress_get_window_id (PikaProgress *progress);
|
||||
GBytes * pika_progress_get_window_id (PikaProgress *progress);
|
||||
|
||||
gboolean pika_progress_message (PikaProgress *progress,
|
||||
Pika *pika,
|
||||
|
@ -59,7 +59,7 @@ static void pika_sub_progress_set_value (PikaProgress *prog
|
||||
gdouble percentage);
|
||||
static gdouble pika_sub_progress_get_value (PikaProgress *progress);
|
||||
static void pika_sub_progress_pulse (PikaProgress *progress);
|
||||
static guint32 pika_sub_progress_get_window_id (PikaProgress *progress);
|
||||
static GBytes * pika_sub_progress_get_window_id (PikaProgress *progress);
|
||||
static gboolean pika_sub_progress_message (PikaProgress *progress,
|
||||
Pika *pika,
|
||||
PikaMessageSeverity severity,
|
||||
@ -228,7 +228,7 @@ pika_sub_progress_pulse (PikaProgress *progress)
|
||||
pika_progress_pulse (sub->progress);
|
||||
}
|
||||
|
||||
static guint32
|
||||
static GBytes *
|
||||
pika_sub_progress_get_window_id (PikaProgress *progress)
|
||||
{
|
||||
PikaSubProgress *sub = PIKA_SUB_PROGRESS (progress);
|
||||
@ -236,7 +236,7 @@ pika_sub_progress_get_window_id (PikaProgress *progress)
|
||||
if (sub->progress)
|
||||
return pika_progress_get_window_id (sub->progress);
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
Reference in New Issue
Block a user