[gimp] Bug 378334 - Plugins with image drop-list crash when image is closed



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]