[gimp] Bug 378334 - Plugins with image drop-list crash when image is closed
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 378334 - Plugins with image drop-list crash when image is closed
- Date: Mon, 8 Oct 2012 20:05:29 +0000 (UTC)
commit 4aaaa1a7fa9d5f80121f07a01adb79d41ab77684
Author: Michael Natterer <mitch gimp org>
Date: Mon Oct 8 22:01:30 2012 +0200
Bug 378334 - Plugins with image drop-list crash when image is closed
Let image and item combo boxes connect to their own "changed" signal
first, and if the chosen image/item doesn't exist any longer,
reinitialize the combo box and select the first item instead.
Also fixes the type macros in gimpitemcombobox.h which were lacking a
')' and introduces an internal GimpItemComboBox class to hold the
common functionality.
libgimp/gimpimagecombobox.c | 62 ++++++++++--
libgimp/gimpitemcombobox.c | 227 ++++++++++++++++++++++++------------------
libgimp/gimpitemcombobox.h | 8 +-
3 files changed, 187 insertions(+), 110 deletions(-)
---
diff --git a/libgimp/gimpimagecombobox.c b/libgimp/gimpimagecombobox.c
index 55533c7..d723d84 100644
--- a/libgimp/gimpimagecombobox.c
+++ b/libgimp/gimpimagecombobox.c
@@ -51,7 +51,10 @@ typedef struct _GimpImageComboBoxClass GimpImageComboBoxClass;
struct _GimpImageComboBox
{
- GimpIntComboBox parent_instance;
+ GimpIntComboBox parent_instance;
+
+ GimpImageConstraintFunc constraint;
+ gpointer data;
};
struct _GimpImageComboBoxClass
@@ -60,6 +63,7 @@ struct _GimpImageComboBoxClass
};
+static void gimp_image_combo_box_populate (GimpImageComboBox *combo_box);
static void gimp_image_combo_box_model_add (GtkListStore *store,
gint num_images,
gint32 *images,
@@ -74,6 +78,8 @@ static void gimp_image_combo_box_drag_data_received (GtkWidget *widget,
guint info,
guint time);
+static void gimp_image_combo_box_changed (GimpImageComboBox *combo_box);
+
static const GtkTargetEntry target = { "application/x-gimp-image-id", 0 };
@@ -123,30 +129,46 @@ GtkWidget *
gimp_image_combo_box_new (GimpImageConstraintFunc constraint,
gpointer data)
{
- GtkWidget *combo_box;
- GtkTreeModel *model;
- GtkTreeIter iter;
- gint32 *images;
- gint num_images;
+ GimpImageComboBox *combo_box;
combo_box = g_object_new (GIMP_TYPE_IMAGE_COMBO_BOX,
"width-request", WIDTH_REQUEST,
"ellipsize", PANGO_ELLIPSIZE_MIDDLE,
NULL);
+ combo_box->constraint = constraint;
+ combo_box->data = data;
+
+ gimp_image_combo_box_populate (combo_box);
+
+ g_signal_connect (combo_box, "changed",
+ G_CALLBACK (gimp_image_combo_box_changed),
+ NULL);
+
+ return GTK_WIDGET (combo_box);
+}
+
+static void
+gimp_image_combo_box_populate (GimpImageComboBox *combo_box)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gint32 *images;
+ gint num_images;
+
model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
images = gimp_image_list (&num_images);
gimp_image_combo_box_model_add (GTK_LIST_STORE (model),
num_images, images,
- constraint, data);
+ combo_box->constraint,
+ combo_box->data);
+
g_free (images);
if (gtk_tree_model_get_iter_first (model, &iter))
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_box), &iter);
-
- return combo_box;
}
static void
@@ -225,3 +247,25 @@ gimp_image_combo_box_drag_data_received (GtkWidget *widget,
g_free (str);
}
+
+static void
+gimp_image_combo_box_changed (GimpImageComboBox *combo_box)
+{
+ gint image_ID;
+
+ if (gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (combo_box),
+ &image_ID))
+ {
+ if (! gimp_image_is_valid (image_ID))
+ {
+ GtkTreeModel *model;
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+
+ g_signal_stop_emission_by_name (combo_box, "changed");
+
+ gtk_list_store_clear (GTK_LIST_STORE (model));
+ gimp_image_combo_box_populate (combo_box);
+ }
+ }
+}
diff --git a/libgimp/gimpitemcombobox.c b/libgimp/gimpitemcombobox.c
index 39b98d0..762e0be 100644
--- a/libgimp/gimpitemcombobox.c
+++ b/libgimp/gimpitemcombobox.c
@@ -49,73 +49,86 @@
#define THUMBNAIL_SIZE 24
#define WIDTH_REQUEST 200
-typedef enum
-{
- DRAWABLE_COMBO_BOX,
- CHANNEL_COMBO_BOX,
- LAYER_COMBO_BOX,
- VECTORS_COMBO_BOX
-} GimpComboBoxType;
+#define GIMP_TYPE_ITEM_COMBO_BOX (gimp_item_combo_box_get_type ())
+#define GIMP_ITEM_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_ITEM_COMBO_BOX, GimpItemComboBox))
+#define GIMP_IS_ITEM_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_ITEM_COMBO_BOX))
+
+GType gimp_item_combo_box_get_type (void) G_GNUC_CONST;
+
+typedef struct _GimpItemComboBox GimpItemComboBox;
+typedef struct _GimpItemComboBoxClass GimpItemComboBoxClass;
typedef struct _GimpDrawableComboBoxClass GimpDrawableComboBoxClass;
typedef struct _GimpChannelComboBoxClass GimpChannelComboBoxClass;
typedef struct _GimpLayerComboBoxClass GimpLayerComboBoxClass;
typedef struct _GimpVectorsComboBoxClass GimpVectorsComboBoxClass;
+struct _GimpItemComboBox
+{
+ GimpIntComboBox parent_instance;
+
+ GimpItemConstraintFunc constraint;
+ gpointer data;
+};
+
+struct _GimpItemComboBoxClass
+{
+ GimpIntComboBoxClass parent_class;
+};
+
struct _GimpDrawableComboBox
{
- GimpIntComboBox parent_instance;
+ GimpItemComboBox parent_instance;
};
struct _GimpDrawableComboBoxClass
{
- GimpIntComboBoxClass parent_class;
+ GimpItemComboBoxClass parent_class;
};
struct _GimpChannelComboBox
{
- GimpIntComboBox parent_instance;
+ GimpItemComboBox parent_instance;
};
struct _GimpChannelComboBoxClass
{
- GimpIntComboBoxClass parent_class;
+ GimpItemComboBoxClass parent_class;
};
struct _GimpLayerComboBox
{
- GimpIntComboBox parent_instance;
+ GimpItemComboBox parent_instance;
};
struct _GimpLayerComboBoxClass
{
- GimpIntComboBoxClass parent_class;
+ GimpItemComboBoxClass parent_class;
};
struct _GimpVectorsComboBox
{
- GimpIntComboBox parent_instance;
+ GimpItemComboBox parent_instance;
};
struct _GimpVectorsComboBoxClass
{
- GimpIntComboBoxClass parent_class;
+ GimpItemComboBoxClass parent_class;
};
-static GtkWidget * gimp_item_combo_box_new (GimpComboBoxType type,
+static GtkWidget * gimp_item_combo_box_new (GType type,
GimpItemConstraintFunc constraint,
gpointer data);
-static void gimp_item_combo_box_model_add (GtkListStore *store,
+static void gimp_item_combo_box_populate (GimpItemComboBox *combo_box);
+static void gimp_item_combo_box_model_add (GimpItemComboBox *combo_box,
+ GtkListStore *store,
gint32 image,
gint num_items,
gint32 *items,
- gint tree_level,
- GimpComboBoxType type,
- GimpItemConstraintFunc constraint,
- gpointer data);
+ gint tree_level);
static void gimp_item_combo_box_drag_data_received (GtkWidget *widget,
GdkDragContext *context,
@@ -125,6 +138,8 @@ static void gimp_item_combo_box_drag_data_received (GtkWidget *widget,
guint info,
guint time);
+static void gimp_item_combo_box_changed (GimpItemComboBox *combo_box);
+
static const GtkTargetEntry targets[] =
{
@@ -134,12 +149,11 @@ static const GtkTargetEntry targets[] =
};
-G_DEFINE_TYPE (GimpDrawableComboBox, gimp_drawable_combo_box,
+G_DEFINE_TYPE (GimpItemComboBox, gimp_item_combo_box,
GIMP_TYPE_INT_COMBO_BOX)
-
static void
-gimp_drawable_combo_box_class_init (GimpDrawableComboBoxClass *klass)
+gimp_item_combo_box_class_init (GimpItemComboBoxClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
@@ -147,6 +161,20 @@ gimp_drawable_combo_box_class_init (GimpDrawableComboBoxClass *klass)
}
static void
+gimp_item_combo_box_init (GimpItemComboBox *combo_box)
+{
+}
+
+
+G_DEFINE_TYPE (GimpDrawableComboBox, gimp_drawable_combo_box,
+ GIMP_TYPE_ITEM_COMBO_BOX)
+
+static void
+gimp_drawable_combo_box_class_init (GimpDrawableComboBoxClass *klass)
+{
+}
+
+static void
gimp_drawable_combo_box_init (GimpDrawableComboBox *combo_box)
{
gtk_drag_dest_set (GTK_WIDGET (combo_box),
@@ -180,22 +208,17 @@ GtkWidget *
gimp_drawable_combo_box_new (GimpDrawableConstraintFunc constraint,
gpointer data)
{
- return gimp_item_combo_box_new (DRAWABLE_COMBO_BOX, constraint, data);
+ return gimp_item_combo_box_new (GIMP_TYPE_DRAWABLE_COMBO_BOX,
+ constraint, data);
}
-G_DEFINE_TYPE(GimpChannelComboBox,
- gimp_channel_combo_box,
- GIMP_TYPE_INT_COMBO_BOX);
+G_DEFINE_TYPE (GimpChannelComboBox, gimp_channel_combo_box,
+ GIMP_TYPE_ITEM_COMBO_BOX)
static void
gimp_channel_combo_box_class_init (GimpChannelComboBoxClass *klass)
{
- GtkWidgetClass *widget_class;
-
- widget_class = GTK_WIDGET_CLASS (klass);
-
- widget_class->drag_data_received = gimp_item_combo_box_drag_data_received;
}
static void
@@ -225,20 +248,17 @@ GtkWidget *
gimp_channel_combo_box_new (GimpDrawableConstraintFunc constraint,
gpointer data)
{
- return gimp_item_combo_box_new (CHANNEL_COMBO_BOX, constraint, data);
+ return gimp_item_combo_box_new (GIMP_TYPE_CHANNEL_COMBO_BOX,
+ constraint, data);
}
-G_DEFINE_TYPE(GimpLayerComboBox,
- gimp_layer_combo_box,
- GIMP_TYPE_INT_COMBO_BOX);
+G_DEFINE_TYPE (GimpLayerComboBox, gimp_layer_combo_box,
+ GIMP_TYPE_ITEM_COMBO_BOX)
static void
gimp_layer_combo_box_class_init (GimpLayerComboBoxClass *klass)
{
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
- widget_class->drag_data_received = gimp_item_combo_box_drag_data_received;
}
static void
@@ -268,19 +288,17 @@ GtkWidget *
gimp_layer_combo_box_new (GimpDrawableConstraintFunc constraint,
gpointer data)
{
- return gimp_item_combo_box_new (LAYER_COMBO_BOX, constraint, data);
+ return gimp_item_combo_box_new (GIMP_TYPE_LAYER_COMBO_BOX,
+ constraint, data);
}
G_DEFINE_TYPE (GimpVectorsComboBox, gimp_vectors_combo_box,
- GIMP_TYPE_INT_COMBO_BOX)
+ GIMP_TYPE_ITEM_COMBO_BOX)
static void
gimp_vectors_combo_box_class_init (GimpVectorsComboBoxClass *klass)
{
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
- widget_class->drag_data_received = gimp_item_combo_box_drag_data_received;
}
static void
@@ -294,6 +312,7 @@ gimp_vectors_combo_box_init (GimpVectorsComboBox *combo_box)
GDK_ACTION_COPY);
}
+
/**
* gimp_vectors_combo_box_new:
* @constraint: a #GimpVectorsConstraintFunc or %NULL
@@ -317,44 +336,44 @@ GtkWidget *
gimp_vectors_combo_box_new (GimpVectorsConstraintFunc constraint,
gpointer data)
{
- return gimp_item_combo_box_new (VECTORS_COMBO_BOX, constraint, data);
+ return gimp_item_combo_box_new (GIMP_TYPE_VECTORS_COMBO_BOX,
+ constraint, data);
}
static GtkWidget *
-gimp_item_combo_box_new (GimpComboBoxType type,
+gimp_item_combo_box_new (GType type,
GimpItemConstraintFunc constraint,
gpointer data)
{
- GType combo_box_type = G_TYPE_NONE;
- GtkWidget *combo_box;
+ GimpItemComboBox *combo_box;
+
+ combo_box = g_object_new (type,
+ "width-request", WIDTH_REQUEST,
+ "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
+ NULL);
+
+ combo_box->constraint = constraint;
+ combo_box->data = data;
+
+ gimp_item_combo_box_populate (combo_box);
+
+ g_signal_connect (combo_box, "changed",
+ G_CALLBACK (gimp_item_combo_box_changed),
+ NULL);
+
+ return GTK_WIDGET (combo_box);
+}
+
+static void
+gimp_item_combo_box_populate (GimpItemComboBox *combo_box)
+{
GtkTreeModel *model;
GtkTreeIter iter;
gint32 *images;
gint num_images;
gint i;
- switch (type)
- {
- case DRAWABLE_COMBO_BOX:
- combo_box_type = GIMP_TYPE_DRAWABLE_COMBO_BOX;
- break;
- case CHANNEL_COMBO_BOX:
- combo_box_type = GIMP_TYPE_CHANNEL_COMBO_BOX;
- break;
- case LAYER_COMBO_BOX:
- combo_box_type = GIMP_TYPE_LAYER_COMBO_BOX;
- break;
- case VECTORS_COMBO_BOX:
- combo_box_type = GIMP_TYPE_VECTORS_COMBO_BOX;
- break;
- }
-
- combo_box = g_object_new (combo_box_type,
- "width-request", WIDTH_REQUEST,
- "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
- NULL);
-
model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
images = gimp_image_list (&num_images);
@@ -364,35 +383,32 @@ gimp_item_combo_box_new (GimpComboBoxType type,
gint32 *items;
gint num_items;
- if (type == DRAWABLE_COMBO_BOX ||
- type == LAYER_COMBO_BOX)
+ if (GIMP_IS_DRAWABLE_COMBO_BOX (combo_box) ||
+ GIMP_IS_LAYER_COMBO_BOX (combo_box))
{
items = gimp_image_get_layers (images[i], &num_items);
- gimp_item_combo_box_model_add (GTK_LIST_STORE (model),
+ gimp_item_combo_box_model_add (combo_box, GTK_LIST_STORE (model),
images[i],
- num_items, items, 0, type,
- constraint, data);
+ num_items, items, 0);
g_free (items);
}
- if (type == DRAWABLE_COMBO_BOX ||
- type == CHANNEL_COMBO_BOX)
+ if (GIMP_IS_DRAWABLE_COMBO_BOX (combo_box) ||
+ GIMP_IS_CHANNEL_COMBO_BOX (combo_box))
{
items = gimp_image_get_channels (images[i], &num_items);
- gimp_item_combo_box_model_add (GTK_LIST_STORE (model),
+ gimp_item_combo_box_model_add (combo_box, GTK_LIST_STORE (model),
images[i],
- num_items, items, 0, type,
- constraint, data);
+ num_items, items, 0);
g_free (items);
}
- if (type == VECTORS_COMBO_BOX)
+ if (GIMP_IS_VECTORS_COMBO_BOX (combo_box))
{
items = gimp_image_get_vectors (images[i], &num_items);
- gimp_item_combo_box_model_add (GTK_LIST_STORE (model),
+ gimp_item_combo_box_model_add (combo_box, GTK_LIST_STORE (model),
images[i],
- num_items, items, 0, type,
- constraint, data);
+ num_items, items, 0);
g_free (items);
}
}
@@ -401,20 +417,15 @@ gimp_item_combo_box_new (GimpComboBoxType type,
if (gtk_tree_model_get_iter_first (model, &iter))
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_box), &iter);
-
- return combo_box;
}
-
static void
-gimp_item_combo_box_model_add (GtkListStore *store,
+gimp_item_combo_box_model_add (GimpItemComboBox *combo_box,
+ GtkListStore *store,
gint32 image,
gint num_items,
gint32 *items,
- gint tree_level,
- GimpComboBoxType type,
- GimpItemConstraintFunc constraint,
- gpointer data)
+ gint tree_level)
{
GtkTreeIter iter;
gint i;
@@ -434,7 +445,8 @@ gimp_item_combo_box_model_add (GtkListStore *store,
for (i = 0; i < num_items; i++)
{
- if (! constraint || (* constraint) (image, items[i], data))
+ if (! combo_box->constraint ||
+ (* combo_box->constraint) (image, items[i], combo_box->data))
{
gchar *image_name = gimp_image_get_name (image);
gchar *item_name = gimp_item_get_name (items[i]);
@@ -448,7 +460,7 @@ gimp_item_combo_box_model_add (GtkListStore *store,
g_free (item_name);
g_free (image_name);
- if (type == VECTORS_COMBO_BOX)
+ if (GIMP_IS_VECTORS_COMBO_BOX (combo_box))
thumb = NULL;
else
thumb = gimp_drawable_get_thumbnail (items[i],
@@ -473,11 +485,10 @@ gimp_item_combo_box_model_add (GtkListStore *store,
gint n_children;
children = gimp_item_get_children (items[i], &n_children);
- gimp_item_combo_box_model_add (store,
+ gimp_item_combo_box_model_add (combo_box, store,
image,
n_children, children,
- tree_level + 1, type,
- constraint, data);
+ tree_level + 1);
g_free (children);
}
}
@@ -521,3 +532,25 @@ gimp_item_combo_box_drag_data_received (GtkWidget *widget,
g_free (str);
}
+
+static void
+gimp_item_combo_box_changed (GimpItemComboBox *combo_box)
+{
+ gint item_ID;
+
+ if (gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (combo_box),
+ &item_ID))
+ {
+ if (! gimp_item_is_valid (item_ID))
+ {
+ GtkTreeModel *model;
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
+
+ g_signal_stop_emission_by_name (combo_box, "changed");
+
+ gtk_list_store_clear (GTK_LIST_STORE (model));
+ gimp_item_combo_box_populate (combo_box);
+ }
+ }
+}
diff --git a/libgimp/gimpitemcombobox.h b/libgimp/gimpitemcombobox.h
index d0d58fe..91760ae 100644
--- a/libgimp/gimpitemcombobox.h
+++ b/libgimp/gimpitemcombobox.h
@@ -34,19 +34,19 @@ G_BEGIN_DECLS
#define GIMP_TYPE_DRAWABLE_COMBO_BOX (gimp_drawable_combo_box_get_type ())
#define GIMP_DRAWABLE_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_DRAWABLE_COMBO_BOX, GimpDrawableComboBox))
-#define GIMP_IS_DRAWABLE_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_DRAWABLE_COMBO_BOX)
+#define GIMP_IS_DRAWABLE_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_DRAWABLE_COMBO_BOX))
#define GIMP_TYPE_CHANNEL_COMBO_BOX (gimp_channel_combo_box_get_type ())
#define GIMP_CHANNEL_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_CHANNEL_COMBO_BOX, GimpChannelComboBox))
-#define GIMP_IS_CHANNEL_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_CHANNEL_COMBO_BOX)
+#define GIMP_IS_CHANNEL_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_CHANNEL_COMBO_BOX))
#define GIMP_TYPE_LAYER_COMBO_BOX (gimp_layer_combo_box_get_type ())
#define GIMP_LAYER_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_LAYER_COMBO_BOX, GimpLayerComboBox))
-#define GIMP_IS_LAYER_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_LAYER_COMBO_BOX)
+#define GIMP_IS_LAYER_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_LAYER_COMBO_BOX))
#define GIMP_TYPE_VECTORS_COMBO_BOX (gimp_vectors_combo_box_get_type ())
#define GIMP_VECTORS_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_VECTORS_COMBO_BOX, GimpVectorsComboBox))
-#define GIMP_IS_VECTORS_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_VECTORS_COMBO_BOX)
+#define GIMP_IS_VECTORS_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_VECTORS_COMBO_BOX))
typedef gboolean (* GimpItemConstraintFunc) (gint32 image_id,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]