glade-widget-adaptor.c 148 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * Copyright (C) 2001 Ximian, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * Authors:
 *   Tristan Van Berkom <tvb@gnome.org>
 */

#include <config.h>

24 25 26 27
/**
 * SECTION:glade-widget-adaptor
 * @Short_Description: Adaptor base class to add runtime support for each widget class.
 * 
28 29 30 31 32
 * The #GladeWidgetAdaptor object is a proxy for widget class support in Glade.
 * it is automatically generated from the xml and allows you to override its
 * methods in the plugin library for fine grained support on how you load/save
 * widgets and handle thier properties in the runtime and more.
 * 
33 34
 */

35 36 37 38 39
#include "glade.h"
#include "glade-widget-adaptor.h"
#include "glade-xml-utils.h"
#include "glade-property-class.h"
#include "glade-signal.h"
40 41
#include "glade-marshallers.h"
#include "glade-accumulators.h"
42
#include "glade-displayable-values.h"
43
#include "glade-editor-table.h"
44
#include "glade-cursor.h"
45
#include "glade-private.h"
46

47 48 49 50
/* For g_file_exists */
#include <sys/types.h>
#include <string.h>

51
#include <glib.h>
52 53 54 55
#include <glib/gi18n-lib.h>
#include <gmodule.h>
#include <ctype.h>

Vincent Geddes's avatar
Vincent Geddes committed
56
#define DEFAULT_ICON_NAME "widget-gtk-frame"
57

58 59
struct _GladeWidgetAdaptorPrivate
{
60 61 62 63 64
  GType        type;                /* GType of the widget */
  GType        real_type;

  gchar       *name;                /* Name of the widget, for example GtkButton */
  gchar       *generic_name;        /* Used to generate names of new widgets, for
65 66 67
                                     * example "button" so that we generate button1,
                                     * button2, buttonX ..
                                     */
68 69 70 71 72
  gchar       *icon_name;           /* icon name to use for widget class */
  gchar       *missing_icon;        /* the name of the missing icon if it was not found */

  gchar       *title;               /* Translated class name used in the UI */
  GList       *properties;          /* List of GladePropertyClass objects.
73 74 75 76 77 78
                                     * [see glade-property.h] this list contains
                                     * properties about the widget that we are going
                                     * to modify. Like "title", "label", "rows" .
                                     * Each property creates an input in the propety
                                     * editor.
                                     */
79
  GList       *packing_props;       /* List of GladePropertyClass objects that describe
80 81 82 83 84 85
                                     * properties for child objects packing definition -
                                     * note there may be more than one type of child supported
                                     * by a widget and thus they may have different sets
                                     * of properties for each type - this association is
                                     * managed on the GladePropertyClass proper.
                                     */
86 87 88 89
  GList       *signals;              /* List of GladeSignalClass objects */
  GList       *child_packings;       /* Default packing property values */
  GList       *actions;              /* A list of GWActionClass */
  GList       *packing_actions;      /* A list of GWActionClass for child objects */
90
  GList       *internal_children;    /* A list of GladeInternalChild */
91
  gchar       *catalog;              /* The name of the widget catalog this class
92 93
                                      * was declared by.
                                      */
94
  gchar       *book;                 /* DevHelp search namespace for this widget class
95
                                      */
96 97 98 99

  GdkCursor   *cursor;                /* a cursor for inserting widgets */

  gchar       *special_child_type;    /* Special case code for children that
100 101 102
                                       * are special children (like notebook tab 
                                       * widgets for example).
                                       */
103
  gboolean     query;                 /* Do we have to query the user, see glade_widget_adaptor_query() */
104 105
};

106 107 108 109
struct _GladeChildPacking
{
  gchar *parent_name;
  GList *packing_defaults;
110 111
};

112

113 114 115 116
struct _GladePackingDefault
{
  gchar *id;
  gchar *value;
117 118
};

119 120 121 122 123 124
struct _GladeInternalChild
{
  gchar *name;
  gboolean anarchist;
  GList *children;
};
125

126 127 128 129 130 131 132 133 134 135 136
enum
{
  PROP_0,
  PROP_NAME,
  PROP_TYPE,
  PROP_TITLE,
  PROP_GENERIC_NAME,
  PROP_ICON_NAME,
  PROP_CATALOG,
  PROP_BOOK,
  PROP_SPECIAL_TYPE,
137 138
  PROP_CURSOR,
  PROP_QUERY
139 140
};

141 142
typedef struct _GladeChildPacking GladeChildPacking;
typedef struct _GladePackingDefault GladePackingDefault;
143
typedef struct _GladeInternalChild GladeInternalChild;
144

145
static GHashTable *adaptor_hash = NULL;
146

147 148 149 150
/* This object used to be registered as GladeGObjectAdaptor but there is
 * no reason for it since the autogenerated class for GtWidget is GladeGtkWidgetAdaptor
 * TODO: rename GladeWidgetAdaptor to GladeGObjectAdator or GladeObjectAdator
 */
151
G_DEFINE_TYPE_WITH_PRIVATE (GladeWidgetAdaptor, glade_widget_adaptor, G_TYPE_OBJECT);
152

153 154 155 156 157
/*******************************************************************************
                              Helper functions
 *******************************************************************************/

static void
158
gwa_create_cursor (GladeWidgetAdaptor *adaptor)
159
{
160 161 162 163 164 165
  GdkPixbuf *tmp_pixbuf, *widget_pixbuf;
  const GdkPixbuf *add_pixbuf;
  GdkDisplay *display;
  GError *error = NULL;

  /* only certain widget classes need to have cursors */
166 167 168
  if (G_TYPE_IS_INSTANTIATABLE (adaptor->priv->type) == FALSE ||
      G_TYPE_IS_ABSTRACT (adaptor->priv->type) != FALSE ||
      adaptor->priv->generic_name == NULL)
169
    return;
170

171 172 173
  /* cannot continue if 'add widget' cursor pixbuf has not been loaded for any reason */
  if ((add_pixbuf = glade_cursor_get_add_widget_pixbuf ()) == NULL)
    return;
174

175
  display = gdk_display_get_default ();
176

177 178 179
  /* create a temporary pixbuf clear to transparent black */
  tmp_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 32, 32);
  gdk_pixbuf_fill (tmp_pixbuf, 0x00000000);
180

181
  if (gtk_icon_theme_has_icon
182
      (gtk_icon_theme_get_default (), adaptor->priv->icon_name))
183 184
    {
      widget_pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
185
                                                adaptor->priv->icon_name,
186 187 188 189 190
                                                22, 0, &error);

      if (error)
        {
          g_warning ("Could not load image data for named icon '%s': %s",
191
                     adaptor->priv->icon_name, error->message);
192 193 194
          g_error_free (error);
          return;
        }
195

196 197 198 199 200
    }
  else
    {
      return;
    }
201

202 203 204
  /* composite pixbufs */
  gdk_pixbuf_composite (widget_pixbuf, tmp_pixbuf,
                        8, 8, 22, 22, 8, 8, 1, 1, GDK_INTERP_NEAREST, 255);
205

206 207
  gdk_pixbuf_composite (add_pixbuf, tmp_pixbuf,
                        0, 0, 12, 12, 0, 0, 1, 1, GDK_INTERP_NEAREST, 255);
208 209


210 211
  adaptor->priv->cursor =
      gdk_cursor_new_from_pixbuf (display, tmp_pixbuf, 6, 6);
212

213 214
  g_object_unref (tmp_pixbuf);
  g_object_unref (widget_pixbuf);
215 216
}

217
static gboolean
218 219
glade_widget_adaptor_hash_find (gpointer key,
                                gpointer value, 
220
                                gpointer user_data)
221
{
222 223 224
  GladeWidgetAdaptor *adaptor = value;
  GType *type = user_data;

225
  if (g_type_is_a (adaptor->priv->type, *type))
226
    {
227
      *type = adaptor->priv->type;
228 229 230 231
      return TRUE;
    }

  return FALSE;
232 233 234 235 236
}

static void
glade_abort_if_derived_adaptors_exist (GType type)
{
237 238 239 240 241 242 243 244 245
  if (adaptor_hash)
    {
      GType retval = type;

      g_hash_table_find (adaptor_hash, glade_widget_adaptor_hash_find, &retval);
      if (retval != type)
        g_error (_("A derived adaptor (%s) of %s already exist!"),
                 g_type_name (retval), g_type_name (type));
    }
246
}
247

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
static GladeInternalChild *
gwa_internal_child_find (GList *list, const gchar *name)
{
  GList *l;

  for (l = list; l; l = g_list_next (l))
    {
      GladeInternalChild *data = l->data;

      if (strcmp (data->name, name) == 0)
        return data;
      
      if (data->children)
        {
          GladeInternalChild *child;
          if ((child = gwa_internal_child_find (data->children, name)))
            return child;
        }
    }
  
  return NULL;
}

271 272 273
/*******************************************************************************
                     Base Object Implementation detail
 *******************************************************************************/
274 275
#define gwa_get_parent_adaptor(a) glade_widget_adaptor_get_parent_adaptor (a)

276 277
static GladeWidgetAdaptor *
glade_widget_adaptor_get_parent_adaptor_by_type (GType adaptor_type)
278
{
279 280
  GladeWidgetAdaptor *parent_adaptor = NULL;
  GType iter_type;
281

282 283 284 285 286 287 288
  for (iter_type = g_type_parent (adaptor_type);
       iter_type > 0; iter_type = g_type_parent (iter_type))
    {
      if ((parent_adaptor =
           glade_widget_adaptor_get_by_type (iter_type)) != NULL)
        return parent_adaptor;
    }
289

290
  return NULL;
291 292
}

293 294 295 296 297
/**
 * glade_widget_adaptor_get_parent_adaptor:
 * @adaptor: a #GladeWidgetAdaptor
 *
 * Returns: (transfer none): the parent #GladeWidgetAdaptor according to @adaptor type
298 299
 */
GladeWidgetAdaptor *
300
glade_widget_adaptor_get_parent_adaptor (GladeWidgetAdaptor *adaptor)
301
{
302
  g_return_val_if_fail (GLADE_IS_WIDGET_ADAPTOR (adaptor), NULL);
303

304
  return glade_widget_adaptor_get_parent_adaptor_by_type (adaptor->priv->type);
305
}
306

307 308 309 310 311 312 313
gboolean
glade_widget_adaptor_has_internal_children (GladeWidgetAdaptor *adaptor)
{
  g_return_val_if_fail (GLADE_IS_WIDGET_ADAPTOR (adaptor), FALSE);
  return adaptor->priv->internal_children != NULL;
}

314
static gint
315
gwa_signal_comp (gpointer a, gpointer b)
316
{
317 318 319
  GladeSignalClass *signal_a = a, *signal_b = b;

  return strcmp (glade_signal_class_get_name (signal_b), 
320
                 glade_signal_class_get_name (signal_a));
321 322
}

323
static gint
324
gwa_signal_find_comp (gpointer a, gpointer b)
325
{
326 327 328
  GladeSignalClass *signal = a;
  gchar *name = b;
  return strcmp (name, glade_signal_class_get_name (signal));
329 330
}

331
static void
332
gwa_add_signals (GladeWidgetAdaptor *adaptor, GList **signals, GType type)
333
{
334
  guint               count, *sig_ids, num_signals;
335
  GladeWidgetAdaptor *type_adaptor;
336 337
  GladeSignalClass   *signal;
  GList              *list = NULL;
338 339 340

  type_adaptor = glade_widget_adaptor_get_by_type (type);

341
  sig_ids = g_signal_list_ids (type, &num_signals);
342

343 344 345
  for (count = 0; count < num_signals; count++)
    {
      signal = glade_signal_class_new (type_adaptor ? 
346 347
                                       type_adaptor : adaptor,
                                       type, sig_ids[count]);
348

349
      list = g_list_prepend (list, signal);
350
    }
351 352 353 354
  g_free (sig_ids);

  list = g_list_sort (list, (GCompareFunc)gwa_signal_comp);
  *signals = g_list_concat (list, *signals);
355 356 357
}

static GList *
358
gwa_list_signals (GladeWidgetAdaptor *adaptor, GType real_type)
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
{
  GList *signals = NULL;
  GType type, parent, *i, *p;

  g_return_val_if_fail (real_type != 0, NULL);

  for (type = real_type; g_type_is_a (type, G_TYPE_OBJECT); type = parent)
    {
      parent = g_type_parent (type);

      /* Add class signals */
      gwa_add_signals (adaptor, &signals, type);

      /* Add class interfaces signals */
      for (i = p = g_type_interfaces (type, NULL); *i; i++)
374
        if (!g_type_is_a (parent, *i))
375 376 377 378 379 380 381 382 383
          gwa_add_signals (adaptor, &signals, *i);

      g_free (p);
    }

  return g_list_reverse (signals);
}

static GList *
384
gwa_clone_parent_properties (GladeWidgetAdaptor *adaptor, gboolean is_packing)
385 386 387 388 389 390
{
  GladeWidgetAdaptor *parent_adaptor;
  GList *properties = NULL, *list, *proplist;

  if ((parent_adaptor = gwa_get_parent_adaptor (adaptor)) != NULL)
    {
391 392
      gboolean reset_version;

393
      proplist = is_packing ?
394
          parent_adaptor->priv->packing_props : parent_adaptor->priv->properties;
395

396
      /* Reset versioning in derived catalogs just once */
397
      reset_version = strcmp (adaptor->priv->catalog, parent_adaptor->priv->catalog) != 0;
398

399 400
      for (list = proplist; list; list = list->next)
        {
401 402
          GladePropertyClass *pclass = glade_property_class_clone (list->data, reset_version);

403
          glade_property_class_set_adaptor (pclass, adaptor);
404 405 406 407 408 409

          properties = g_list_prepend (properties, pclass);
        }
    }

  return g_list_reverse (properties);
410 411 412
}

static void
413
gwa_setup_introspected_props_from_pspecs (GladeWidgetAdaptor *adaptor,
414 415 416
                                          GParamSpec        **specs,
                                          gint                n_specs,
                                          gboolean            is_packing)
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
{
  GladeWidgetAdaptor *parent_adaptor = gwa_get_parent_adaptor (adaptor);
  GladePropertyClass *property_class;
  gint i;
  GList *list = NULL;

  for (i = 0; i < n_specs; i++)
    {
      if (parent_adaptor == NULL ||
          /* Dont create it if it already exists */
          (!is_packing &&
           !glade_widget_adaptor_get_property_class (parent_adaptor,
                                                     specs[i]->name)) ||
          (is_packing &&
           !glade_widget_adaptor_get_pack_property_class (parent_adaptor,
                                                          specs[i]->name)))
        {
          if ((property_class =
               glade_property_class_new_from_spec (adaptor, specs[i])) != NULL)
            list = g_list_prepend (list, property_class);
        }
    }

  if (is_packing)
441 442
    adaptor->priv->packing_props =
        g_list_concat (adaptor->priv->packing_props, g_list_reverse (list));
443
  else
444 445
    adaptor->priv->properties =
        g_list_concat (adaptor->priv->properties, g_list_reverse (list));
446 447 448
}

static void
449
gwa_setup_properties (GladeWidgetAdaptor *adaptor,
450 451
                      GObjectClass       *object_class,
                      gboolean            is_packing)
452 453 454 455 456 457
{
  GParamSpec **specs = NULL;
  guint n_specs = 0;
  GList *l;

  /* only GtkContainer child propeties can be introspected */
458
  if (is_packing && !g_type_is_a (adaptor->priv->type, GTK_TYPE_CONTAINER))
459 460 461 462
    return;

  /* First clone the parents properties */
  if (is_packing)
463
    adaptor->priv->packing_props = gwa_clone_parent_properties (adaptor, is_packing);
464
  else
465
    adaptor->priv->properties = gwa_clone_parent_properties (adaptor, is_packing);
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487

  /* Now automaticly introspect new properties added in this class,
   * allow the class writer to decide what to override in the resulting
   * list of properties.
   */
  if (is_packing)
    specs = gtk_container_class_list_child_properties (object_class, &n_specs);
  else
    specs = g_object_class_list_properties (object_class, &n_specs);
  gwa_setup_introspected_props_from_pspecs (adaptor, specs, n_specs,
                                            is_packing);
  g_free (specs);

  if (is_packing)
    {
      /* We have to mark packing properties from GladeWidgetAdaptor
       * because GladePropertyClass doesnt have a valid parent GType
       * to introspect it.
       *
       * (which could be used to call gtk_container_class_find_child_property()
       * and properly introspect whether or not its a packing property).
       */
488
      for (l = adaptor->priv->packing_props; l; l = l->next)
489 490
        {
          GladePropertyClass *property_class = l->data;
491

492
          glade_property_class_set_is_packing (property_class, TRUE);
493 494
        }
    }
495 496 497
}

static GList *
498
gwa_inherit_child_packing (GladeWidgetAdaptor *adaptor)
499
{
500 501
  GladeWidgetAdaptor *parent_adaptor;
  GList *child_packings = NULL, *packing_list, *default_list;
502

503 504
  if ((parent_adaptor = gwa_get_parent_adaptor (adaptor)) != NULL)
    {
505
      for (packing_list = parent_adaptor->priv->child_packings;
506 507 508 509
           packing_list; packing_list = packing_list->next)
        {
          GladeChildPacking *packing = packing_list->data;
          GladeChildPacking *packing_dup = g_new0 (GladeChildPacking, 1);
510

511
          packing_dup->parent_name = g_strdup (packing->parent_name);
512

513 514 515 516 517
          for (default_list = packing->packing_defaults;
               default_list; default_list = default_list->next)
            {
              GladePackingDefault *def = default_list->data;
              GladePackingDefault *def_dup = g_new0 (GladePackingDefault, 1);
518

519 520
              def_dup->id = g_strdup (def->id);
              def_dup->value = g_strdup (def->value);
521

522 523 524
              packing_dup->packing_defaults =
                  g_list_prepend (packing_dup->packing_defaults, def_dup);
            }
525

526 527 528 529
          child_packings = g_list_prepend (child_packings, packing_dup);
        }
    }
  return child_packings;
530 531
}

532
static void
533
gwa_inherit_signals (GladeWidgetAdaptor *adaptor)
534 535 536 537 538 539 540
{
  GladeWidgetAdaptor *parent_adaptor;
  GList *list, *node;
  GladeSignalClass *signal, *parent_signal;

  if ((parent_adaptor = gwa_get_parent_adaptor (adaptor)) != NULL)
    {
541
      for (list = adaptor->priv->signals; list; list = list->next)
542 543 544
        {
          signal = list->data;

545
          if ((node = g_list_find_custom (parent_adaptor->priv->signals, 
546 547
                                          glade_signal_class_get_name (signal),
                                          (GCompareFunc) gwa_signal_find_comp)) != NULL)
548 549 550
            {
              parent_signal = node->data;

551
              /* XXX FIXME: This is questionable, why should derived catalogs
552 553 554 555
               * reset the derived signal versions ???
               *
               * Reset versioning in derived catalogs just once
               */
556 557
              if (strcmp (adaptor->priv->catalog,
                          parent_adaptor->priv->catalog))
558
                glade_signal_class_set_since (signal, 0, 0);
559
              else
560 561 562
                glade_signal_class_set_since (signal, 
                                              glade_signal_class_since_major (parent_signal),
                                              glade_signal_class_since_minor (parent_signal));
563

564
              glade_signal_class_set_deprecated (signal, glade_signal_class_deprecated (parent_signal));
565 566 567
            }
        }
    }
568 569
}

570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
static GladeInternalChild *
gwa_internal_children_new (gchar *name, gboolean anarchist)
{
  GladeInternalChild *data = g_slice_new0 (GladeInternalChild);

  data->name = g_strdup (name);
  data->anarchist = anarchist;

  return data;
}

static GList *
gwa_internal_children_clone (GList *children)
{
  GList *l, *retval = NULL;
  
  for (l = children; l; l = g_list_next (l))
    {
      GladeInternalChild *data, *child = l->data;

      data = gwa_internal_children_new (child->name, child->anarchist);
      retval = g_list_prepend (retval, data);

      if (child->children)
        data->children = gwa_internal_children_clone (child->children);
    }

  return g_list_reverse (retval);
}

600
static GObject *
601 602 603
glade_widget_adaptor_constructor (GType                  type,
                                  guint                  n_construct_properties,
                                  GObjectConstructParam *construct_properties)
604 605 606 607 608 609 610
{
  GladeWidgetAdaptor *adaptor, *parent_adaptor;
  GObject *ret_obj;
  GObjectClass *object_class;

  glade_abort_if_derived_adaptors_exist (type);

611
  ret_obj = G_OBJECT_CLASS (glade_widget_adaptor_parent_class)->constructor
612 613 614 615 616
      (type, n_construct_properties, construct_properties);

  adaptor = GLADE_WIDGET_ADAPTOR (ret_obj);
  parent_adaptor = gwa_get_parent_adaptor (adaptor);

617
  if (adaptor->priv->type == G_TYPE_NONE)
618
    g_warning ("Adaptor created without a type");
619
  if (adaptor->priv->name == NULL)
620 621 622
    g_warning ("Adaptor created without a name");

  /* Build decorations */
623
  if (!adaptor->priv->icon_name)
624
    adaptor->priv->icon_name = g_strdup ("image-missing");
625 626

  /* Let it leek */
627
  if ((object_class = g_type_class_ref (adaptor->priv->type)))
628 629
    {
      /* Build signals & properties */
630
      adaptor->priv->signals = gwa_list_signals (adaptor, adaptor->priv->type);
631 632 633 634 635 636 637

      gwa_inherit_signals (adaptor);
      gwa_setup_properties (adaptor, object_class, FALSE);
      gwa_setup_properties (adaptor, object_class, TRUE);
    }

  /* Inherit packing defaults here */
638
  adaptor->priv->child_packings = gwa_inherit_child_packing (adaptor);
639 640 641 642 643 644 645 646 647 648

  /* Inherit special-child-type */
  if (parent_adaptor)
    adaptor->priv->special_child_type =
        parent_adaptor->priv->special_child_type ?
        g_strdup (parent_adaptor->priv->special_child_type) : NULL;


  /* Reset version numbering if we're in a new catalog just once */
  if (parent_adaptor &&
649
      strcmp (adaptor->priv->catalog, parent_adaptor->priv->catalog))
650 651 652 653 654 655 656 657 658 659
    {
      GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor)->version_since_major =
          GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor)->version_since_minor = 0;
    }

  /* Copy parent actions */
  if (parent_adaptor)
    {
      GList *l;

660
      if (parent_adaptor->priv->actions)
661
        {
662
          for (l = parent_adaptor->priv->actions; l; l = g_list_next (l))
663 664
            {
              GWActionClass *child = glade_widget_action_class_clone (l->data);
665
              adaptor->priv->actions = g_list_prepend (adaptor->priv->actions, child);
666
            }
667
          adaptor->priv->actions = g_list_reverse (adaptor->priv->actions);
668 669
        }

670
      if (parent_adaptor->priv->packing_actions)
671
        {
672
          for (l = parent_adaptor->priv->packing_actions; l; l = g_list_next (l))
673 674
            {
              GWActionClass *child = glade_widget_action_class_clone (l->data);
675 676
              adaptor->priv->packing_actions =
                  g_list_prepend (adaptor->priv->packing_actions, child);
677
            }
678
          adaptor->priv->packing_actions = g_list_reverse (adaptor->priv->packing_actions);
679 680 681
        }
    }

682 683 684 685
  /* Copy parent internal children */
  if (parent_adaptor && parent_adaptor->priv->internal_children)
    adaptor->priv->internal_children = gwa_internal_children_clone (parent_adaptor->priv->internal_children);

686
  return ret_obj;
687 688 689
}

static void
690
gwa_packing_default_free (GladePackingDefault *def)
691
{
692 693 694
  g_clear_pointer (&def->id, g_free);
  g_clear_pointer (&def->value, g_free);
  g_free (def);
695 696 697
}

static void
698
gwa_child_packing_free (GladeChildPacking *packing)
699
{
700
  g_clear_pointer (&packing->parent_name, g_free);
701

702 703 704 705
  g_list_free_full (packing->packing_defaults,
                    (GDestroyNotify) gwa_packing_default_free);
  packing->packing_defaults = NULL;
  g_free (packing);
706 707
}

708 709 710
static void
gwa_glade_internal_child_free (GladeInternalChild *child)
{
711
  g_clear_pointer (&child->name, g_free);
712 713
  if (child->children)
    {
714 715 716
      g_list_free_full (child->children,
                        (GDestroyNotify) gwa_glade_internal_child_free);
      child->children = NULL;
717 718
    }

719
  g_slice_free (GladeInternalChild, child);
720 721
}

722
static void
723
glade_widget_adaptor_finalize (GObject *object)
724 725
{
  GladeWidgetAdaptor *adaptor = GLADE_WIDGET_ADAPTOR (object);
726

727
  /* Free properties and signals */
728 729 730
  g_list_free_full (adaptor->priv->properties,
                    (GDestroyNotify) glade_property_class_free);
  adaptor->priv->properties = NULL;
731

732 733 734
  g_list_free_full (adaptor->priv->packing_props,
                    (GDestroyNotify) glade_property_class_free);
  adaptor->priv->packing_props = NULL;
735

736 737 738
  g_list_free_full (adaptor->priv->signals,
                    (GDestroyNotify) glade_signal_class_free);
  adaptor->priv->signals = NULL;
739 740

  /* Free child packings */
741 742 743 744 745 746 747 748 749 750 751 752 753 754 755
  g_list_free_full (adaptor->priv->child_packings,
                    (GDestroyNotify) gwa_child_packing_free);
  adaptor->priv->child_packings = NULL;

  g_clear_pointer (&adaptor->priv->book, g_free);
  g_clear_pointer (&adaptor->priv->catalog, g_free);
  g_clear_pointer (&adaptor->priv->special_child_type, g_free);

  g_clear_object (&adaptor->priv->cursor);

  g_clear_pointer (&adaptor->priv->name, g_free);
  g_clear_pointer (&adaptor->priv->generic_name, g_free);
  g_clear_pointer (&adaptor->priv->title, g_free);
  g_clear_pointer (&adaptor->priv->icon_name, g_free);
  g_clear_pointer (&adaptor->priv->missing_icon, g_free);
756 757 758

  if (adaptor->priv->actions)
    {
759 760 761
      g_list_free_full (adaptor->priv->actions,
                        (GDestroyNotify) glade_widget_action_class_free);
      adaptor->priv->actions = NULL;
762 763
    }

764
  if (adaptor->priv->packing_actions)
765
    {
766 767 768
      g_list_free_full (adaptor->priv->packing_actions,
                        (GDestroyNotify) glade_widget_action_class_free);
      adaptor->priv->packing_actions = NULL;
769 770
    }

771 772 773 774 775 776
  if (adaptor->priv->internal_children)
    {
      g_list_free_full (adaptor->priv->internal_children,
                        (GDestroyNotify) gwa_glade_internal_child_free);
      adaptor->priv->internal_children = NULL;
    }
777

778
  G_OBJECT_CLASS (glade_widget_adaptor_parent_class)->finalize (object);
779 780 781
}

static void
782 783
glade_widget_adaptor_real_set_property (GObject      *object,
                                        guint         prop_id,
784
                                        const GValue *value,
785
                                        GParamSpec   *pspec)
786 787 788 789 790 791 792 793 794
{
  GladeWidgetAdaptor *adaptor;

  adaptor = GLADE_WIDGET_ADAPTOR (object);

  switch (prop_id)
    {
      case PROP_NAME:
        /* assume once (construct-only) */
795 796
        adaptor->priv->name = g_value_dup_string (value);
        adaptor->priv->real_type = g_type_from_name (adaptor->priv->name);
797 798 799
        break;
      case PROP_ICON_NAME:
        /* assume once (construct-only) */
800
        adaptor->priv->icon_name = g_value_dup_string (value);
801 802
        break;
      case PROP_TYPE:
803
        adaptor->priv->type = g_value_get_gtype (value);
804 805
        break;
      case PROP_TITLE:
806
        g_clear_pointer (&adaptor->priv->title, g_free);
807
        adaptor->priv->title = g_value_dup_string (value);
808 809
        break;
      case PROP_GENERIC_NAME:
810
        g_clear_pointer (&adaptor->priv->generic_name, g_free);
811
        adaptor->priv->generic_name = g_value_dup_string (value);
812 813 814
        break;
      case PROP_CATALOG:
        /* assume once (construct-only) */
815
        g_clear_pointer (&adaptor->priv->catalog, g_free);
816 817 818 819
        adaptor->priv->catalog = g_value_dup_string (value);
        break;
      case PROP_BOOK:
        /* assume once (construct-only) */
820
        g_clear_pointer (&adaptor->priv->book, g_free);
821 822 823
        adaptor->priv->book = g_value_dup_string (value);
        break;
      case PROP_SPECIAL_TYPE:
824
        /* assume once (construct-only) */ 
825
        g_clear_pointer (&adaptor->priv->special_child_type, g_free);
826
        adaptor->priv->special_child_type = g_value_dup_string (value);
827
        break;
828 829 830
      case PROP_QUERY:
        adaptor->priv->query = g_value_get_boolean (value);
        break;
831 832 833 834
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
835 836 837
}

static void
838 839 840
glade_widget_adaptor_real_get_property (GObject    *object,
                                        guint       prop_id,
                                        GValue     *value,
841
                                        GParamSpec *pspec)
842 843 844 845 846 847 848 849 850
{

  GladeWidgetAdaptor *adaptor;

  adaptor = GLADE_WIDGET_ADAPTOR (object);

  switch (prop_id)
    {
      case PROP_NAME:
851
        g_value_set_string (value, adaptor->priv->name);
852 853
        break;
      case PROP_TYPE:
854
        g_value_set_gtype (value, adaptor->priv->type);
855 856
        break;
      case PROP_TITLE:
857
        g_value_set_string (value, adaptor->priv->title);
858 859
        break;
      case PROP_GENERIC_NAME:
860
        g_value_set_string (value, adaptor->priv->generic_name);
861 862
        break;
      case PROP_ICON_NAME:
863
        g_value_set_string (value, adaptor->priv->icon_name);
864 865 866 867 868 869 870 871 872 873 874 875 876
        break;
      case PROP_CATALOG:
        g_value_set_string (value, adaptor->priv->catalog);
        break;
      case PROP_BOOK:
        g_value_set_string (value, adaptor->priv->book);
        break;
      case PROP_SPECIAL_TYPE:
        g_value_set_string (value, adaptor->priv->special_child_type);
        break;
      case PROP_CURSOR:
        g_value_set_pointer (value, adaptor->priv->cursor);
        break;
877 878 879
      case PROP_QUERY:
        g_value_set_boolean (value, adaptor->priv->query);
        break;
880 881 882 883
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
884 885
}

886 887 888
/*******************************************************************************
                  GladeWidgetAdaptor base class implementations
 *******************************************************************************/
889
static GladeWidget *
890
glade_widget_adaptor_object_create_widget (GladeWidgetAdaptor *adaptor,
891 892
                                           const gchar        *first_property_name,
                                           va_list             var_args)
893
{
894 895
  return GLADE_WIDGET (g_object_new_valist (GLADE_TYPE_WIDGET,
                                            first_property_name, var_args));
896 897
}

898
static GObject *
899
glade_widget_adaptor_object_construct_object (GladeWidgetAdaptor *adaptor,
900 901
                                              guint               n_parameters,
                                              GParameter         *parameters)
902
{
903
  return g_object_newv (adaptor->priv->type, n_parameters, parameters);
904 905
}

906 907
static void
glade_widget_adaptor_object_destroy_object (GladeWidgetAdaptor *adaptor,
908
                                            GObject            *object)
909 910 911 912
{
  /* Do nothing, just have a method here incase classes chain up */
}

913 914 915

static GObject *
glade_widget_adaptor_object_get_internal_child (GladeWidgetAdaptor *adaptor,
916 917
                                                GObject            *object,
                                                const gchar        *name)
918 919 920 921 922 923 924 925 926 927 928
{
  static GtkBuilder *builder = NULL;
  
  g_return_val_if_fail (GTK_IS_BUILDABLE (object), NULL);

  /* Dummy object just in case the interface use it for something */
  if (builder == NULL) builder = gtk_builder_new ();
  
  return gtk_buildable_get_internal_child (GTK_BUILDABLE (object), builder, name);
}

929 930
static gboolean
glade_widget_adaptor_object_add_verify (GladeWidgetAdaptor *adaptor,
931 932 933
                                        GObject            *parent,
                                        GObject            *child,
                                        gboolean            user_feedback)
934 935 936
{
  if (user_feedback)
    glade_util_ui_message (glade_app_get_window (),
937 938 939
                           GLADE_UI_INFO, NULL,
                           _("%s does not support adding any children."), 
                           adaptor->priv->title);
940 941 942

  return FALSE;
}
943

944
static void
945
glade_widget_adaptor_object_set_property (GladeWidgetAdaptor *adaptor,
946 947 948
                                          GObject            *object,
                                          const gchar        *property_name,
                                          const GValue       *value)
949
{
950
  g_object_set_property (object, property_name, value);
951 952 953
}

static void
954
glade_widget_adaptor_object_get_property (GladeWidgetAdaptor *adaptor,
955 956 957
                                          GObject            *object,
                                          const gchar        *property_name,
                                          GValue             *value)
958
{
959
  g_object_get_property (object, property_name, value);
960 961
}

962
static void
963
glade_widget_adaptor_object_action_activate (GladeWidgetAdaptor *adaptor,
964 965
                                             GObject            *object,
                                             const gchar        *action_id)
966
{
967
  g_message ("No action_activate() support in adaptor %s for action '%s'",
968
             adaptor->priv->name, action_id);
969
}
970

971
static void
972
glade_widget_adaptor_object_child_action_activate (GladeWidgetAdaptor *adaptor,
973 974 975
                                                   GObject            *container,
                                                   GObject            *object,
                                                   const gchar        *action_id)
976
{
977
  g_message ("No child_action_activate() support in adaptor %s for action '%s'",
978
             adaptor->priv->name, action_id);
979 980
}

981
static void
982
glade_widget_adaptor_object_read_widget (GladeWidgetAdaptor *adaptor,
983 984
                                         GladeWidget        *widget,
                                         GladeXmlNode       *node)
985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
{
  GladeXmlNode *iter_node;
  GladeSignal *signal;
  GladeProperty *property;
  gchar *name, *prop_name;
  GList *read_properties = NULL, *l;

  /* Read in the properties */
  for (iter_node = glade_xml_node_get_children (node);
       iter_node; iter_node = glade_xml_node_next (iter_node))
    {
      if (!glade_xml_node_verify_silent (iter_node, GLADE_XML_TAG_PROPERTY))
        continue;

      /* Get prop name from node and lookup property ... */
      if (!(name = glade_xml_get_property_string_required
            (iter_node, GLADE_XML_TAG_NAME, NULL)))
        continue;

      prop_name = glade_util_read_prop_name (name);

      /* Some properties may be special child type of custom, just leave them for the adaptor */
      if ((property = glade_widget_get_property (widget, prop_name)) != NULL)
        {
1009
          glade_property_read (property, glade_widget_get_project (widget), iter_node);
1010 1011 1012 1013 1014 1015 1016 1017
          read_properties = g_list_prepend (read_properties, property);
        }

      g_free (prop_name);
      g_free (name);
    }

  /* Sync the remaining values not read in from the Glade file.. */
1018
  for (l = glade_widget_get_properties (widget); l; l = l->next)
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
    {
      property = l->data;

      if (!g_list_find (read_properties, property))
        glade_property_sync (property);
    }
  g_list_free (read_properties);

  /* Read in the signals */
  for (iter_node = glade_xml_node_get_children (node);
       iter_node; iter_node = glade_xml_node_next (iter_node))
    {
      if (!glade_xml_node_verify_silent (iter_node, GLADE_XML_TAG_SIGNAL))
        continue;

1034
      if (!(signal = glade_signal_read (iter_node, adaptor)))
1035 1036
        continue;

1037 1038
      /* The widget doesnt use the signal handler directly but rather
       * creates it's own copy */
1039
      glade_widget_add_signal_handler (widget, signal);
1040
      g_object_unref (signal);
1041 1042 1043 1044 1045 1046 1047 1048 1049
    }

  /* Read in children */
  for (iter_node = glade_xml_node_get_children (node);
       iter_node; iter_node = glade_xml_node_next (iter_node))
    {
      if (glade_xml_node_verify_silent (iter_node, GLADE_XML_TAG_CHILD))
        glade_widget_read_child (widget, iter_node);

1050
      if (glade_project_load_cancelled (glade_widget_get_project (widget)))
1051 1052
        return;
    }
1053 1054 1055
}

static void
1056
glade_widget_adaptor_object_write_widget (GladeWidgetAdaptor *adaptor,
1057 1058 1059
                                          GladeWidget        *widget,
                                          GladeXmlContext    *context,
                                          GladeXmlNode       *node)
1060
{
1061
  GList *props;
1062

1063
  /* Write the properties */
1064
  for (props = glade_widget_get_properties (widget); props; props = props->next)
1065
    {
1066 1067 1068
      GladeProperty      *property = props->data;
      GladePropertyClass *klass = glade_property_get_class (property);

1069
      if (glade_property_class_save (klass) && 
1070
          glade_property_get_enabled (property))
1071 1072
        glade_property_write (GLADE_PROPERTY (props->data), context, node);
    }
1073 1074
}

1075 1076
static void
glade_widget_adaptor_object_write_widget_after (GladeWidgetAdaptor *adaptor,
1077 1078 1079
                                                GladeWidget        *widget,
                                                GladeXmlContext    *context,
                                                GladeXmlNode       *node)
1080 1081 1082 1083
{

}

1084
static void
1085
glade_widget_adaptor_object_read_child (GladeWidgetAdaptor *adaptor,
1086 1087
                                        GladeWidget        *widget,
                                        GladeXmlNode       *node)
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
{
  GladeXmlNode *widget_node, *packing_node, *iter_node;
  GladeWidget *child_widget;
  gchar *internal_name;
  gchar *name, *prop_name;
  GladeProperty *property;

  if (!glade_xml_node_verify (node, GLADE_XML_TAG_CHILD))
    return;

  internal_name =
      glade_xml_get_property_string (node, GLADE_XML_TAG_INTERNAL_CHILD);

  if ((widget_node =
       glade_xml_search_child (node, GLADE_XML_TAG_WIDGET)) != NULL)
    {
      child_widget =
1105 1106
        glade_widget_read (glade_widget_get_project (widget),
                           widget, widget_node, internal_name);
1107 1108 1109 1110 1111 1112

      if (child_widget)
        {
          if (!internal_name)
            {
              glade_widget_set_child_type_from_node
1113
                (widget, glade_widget_get_object (child_widget), node);
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140
              glade_widget_add_child (widget, child_widget, FALSE);
            }

          if ((packing_node =
               glade_xml_search_child (node, GLADE_XML_TAG_PACKING)) != NULL)
            {

              /* Read in the properties */
              for (iter_node = glade_xml_node_get_children (packing_node);
                   iter_node; iter_node = glade_xml_node_next (iter_node))
                {
                  if (!glade_xml_node_verify_silent
                      (iter_node, GLADE_XML_TAG_PROPERTY))
                    continue;

                  /* Get prop name from node and lookup property ... */
                  if (!(name = glade_xml_get_property_string_required
                        (iter_node, GLADE_XML_TAG_NAME, NULL)))
                    continue;

                  prop_name = glade_util_read_prop_name (name);

                  /* Some properties may be special child type of custom, 
                   * just leave them for the adaptor */
                  if ((property =
                       glade_widget_get_pack_property (child_widget,
                                                       prop_name)) != NULL)
1141
                    glade_property_read (property, 
1142
                                         glade_widget_get_project (child_widget),
1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
                                         iter_node);

                  g_free (prop_name);
                  g_free (name);
                }
            }
        }

    }
  else
    {
      GObject *palaceholder = G_OBJECT (glade_placeholder_new ());
      glade_widget_set_child_type_from_node (widget, palaceholder, node);
1156
      glade_widget_adaptor_add (adaptor, glade_widget_get_object (widget), palaceholder);
1157 1158
    }
  g_free (internal_name);
1159 1160 1161
}

static void
1162
glade_widget_adaptor_object_write_child (GladeWidgetAdaptor *adaptor,
1163 1164 1165
                                         GladeWidget        *widget,
                                         GladeXmlContext    *context,
                                         GladeXmlNode       *node)
1166 1167 1168 1169 1170 1171 1172 1173
{
  GladeXmlNode *child_node, *packing_node;
  GList *props;

  child_node = glade_xml_node_new (context, GLADE_XML_TAG_CHILD);
  glade_xml_node_append_child (node, child_node);

  /* Set internal child */
1174
  if (glade_widget_get_internal (widget))
1175 1176
    glade_xml_node_set_property_string (child_node,
                                        GLADE_XML_TAG_INTERNAL_CHILD,
1177
                                        glade_widget_get_internal (widget));
1178 1179 1180 1181 1182 1183 1184 1185

  /* Write out the widget */
  glade_widget_write (widget, context, child_node);

  /* Write out packing properties and special-child-type */
  packing_node = glade_xml_node_new (context, GLADE_XML_TAG_PACKING);
  glade_xml_node_append_child (child_node, packing_node);

1186
  for (props = glade_widget_get_packing_properties (widget); props; props = props->next)
1187
    {
1188 1189 1190
      GladeProperty      *property = props->data;
      GladePropertyClass *klass = glade_property_get_class (property);

1191
      if (glade_property_class_save (klass) && 
1192
          glade_property_get_enabled (property))
1193 1194 1195 1196
        glade_property_write (GLADE_PROPERTY (props->data),
                              context, packing_node);
    }

1197 1198
  glade_widget_write_special_child_prop (glade_widget_get_parent (widget),
                                         glade_widget_get_object (widget), 
1199
                                         context, child_node);
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212

  /* Default packing properties and such are not saved,
   * so lets check afterwords if there was anything saved
   * and then just remove the node.
   */
  if (!glade_xml_node_get_children (packing_node))
    {
      glade_xml_node_remove (packing_node);
      glade_xml_node_delete (packing_node);
    }
}

static GType
1213
glade_widget_adaptor_get_eprop_type (GParamSpec *pspec)
1214 1215 1216 1217 1218 1219 1220 1221 1222
{
  GType type = 0;

  if (G_IS_PARAM_SPEC_ENUM (pspec))
    type = GLADE_TYPE_EPROP_ENUM;
  else if (G_IS_PARAM_SPEC_FLAGS (pspec))
    type = GLADE_TYPE_EPROP_FLAGS;
  else if (G_IS_PARAM_SPEC_VALUE_ARRAY (pspec))
    {
1223 1224
      /* Require deprecated code */
      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1225 1226
      if (pspec->value_type == G_TYPE_VALUE_ARRAY)
        type = GLADE_TYPE_EPROP_TEXT;
1227
      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1228 1229 1230
    }
  else if (G_IS_PARAM_SPEC_BOXED (pspec))
    {
1231
      if (pspec->value_type == GDK_TYPE_COLOR ||
1232
          pspec->value_type == GDK_TYPE_RGBA)
1233 1234 1235 1236
        type = GLADE_TYPE_EPROP_COLOR;
      else if (pspec->value_type == G_TYPE_STRV)
        type = GLADE_TYPE_EPROP_TEXT;
    }
1237 1238
  else if (G_IS_PARAM_SPEC_STRING (pspec) ||
           G_IS_PARAM_SPEC_VARIANT (pspec))
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253
    type = GLADE_TYPE_EPROP_TEXT;
  else if (G_IS_PARAM_SPEC_BOOLEAN (pspec))
    type = GLADE_TYPE_EPROP_BOOL;
  else if (G_IS_PARAM_SPEC_FLOAT (pspec) ||
           G_IS_PARAM_SPEC_DOUBLE (pspec) ||
           G_IS_PARAM_SPEC_INT (pspec) ||
           G_IS_PARAM_SPEC_UINT (pspec) ||
           G_IS_PARAM_SPEC_LONG (pspec) ||
           G_IS_PARAM_SPEC_ULONG (pspec) ||
           G_IS_PARAM_SPEC_INT64 (pspec) || G_IS_PARAM_SPEC_UINT64 (pspec))
    type = GLADE_TYPE_EPROP_NUMERIC;
  else if (G_IS_PARAM_SPEC_UNICHAR (pspec))
    type = GLADE_TYPE_EPROP_UNICHAR;
  else if (G_IS_PARAM_SPEC_OBJECT (pspec))
    {
1254 1255
      if (pspec->value_type == GDK_TYPE_PIXBUF ||
          pspec->value_type == G_TYPE_FILE)
1256 1257 1258 1259 1260 1261 1262 1263
        type = GLADE_TYPE_EPROP_TEXT;
      else
        type = GLADE_TYPE_EPROP_OBJECT;
    }
  else if (GLADE_IS_PARAM_SPEC_OBJECTS (pspec))
    type = GLADE_TYPE_EPROP_OBJECTS;

  return type;
1264 1265 1266
}

static GladeEditorProperty *
1267 1268
glade_widget_adaptor_object_create_eprop (GladeWidgetAdaptor *adaptor,
                                          GladePropertyClass *klass,
1269
                                          gboolean            use_command)
1270
{
1271
  GladeEditorProperty *eprop;
1272 1273 1274 1275
  GParamSpec          *pspec;
  GType                type = 0;

  pspec = glade_property_class_get_pspec (klass);
1276 1277 1278 1279

  /* Find the right type of GladeEditorProperty for this
   * GladePropertyClass.
   */
1280
  if ((type = glade_widget_adaptor_get_eprop_type (pspec)) == 0)
1281
    return NULL;
1282

1283
  /* special case for string specs that denote themed application icons. */
1284
  if (glade_property_class_themed_icon (klass))
1285
    type = GLADE_TYPE_EPROP_NAMED_ICON;
1286

1287 1288 1289 1290
  /* Create and return the correct type of GladeEditorProperty */
  eprop = g_object_new (type,
                        "property-class", klass,
                        "use-command", use_command, NULL);
1291

1292
  return eprop;
1293 1294 1295
}

static gchar *
1296 1297
glade_widget_adaptor_object_string_from_value (GladeWidgetAdaptor *adaptor,
                                               GladePropertyClass *klass,
1298
                                               const GValue       *value)
1299
{
1300
  return glade_property_class_make_string_from_gvalue (klass, value);
1301 1302
}

1303
static GladeEditable *
1304
glade_widget_adaptor_object_create_editable (GladeWidgetAdaptor *adaptor,
1305
                                             GladeEditorPageType type)
1306
{
1307
  return (GladeEditable *) glade_editor_table_new (adaptor, type);
1308 1309
}

1310 1311 1312 1313 1314
static void
glade_internal_child_append (GladeWidgetAdaptor *adaptor,
                             GObject            *object,
                             GList              *list,
                             GList             **children)
1315
{
1316 1317
  GList *l;

1318 1319 1320 1321 1322 1323 1324 1325 1326
  for (l = list; l; l = g_list_next (l))
    {
      GladeInternalChild *internal = l->data;
      GObject *child;
        
      child = glade_widget_adaptor_get_internal_child (adaptor,
                                                       object,
                                                       internal->name);
      if (child)
1327 1328 1329 1330 1331