示例#1
0
/**
 * bt_persistence_load:
 * @type: a #GObject type
 * @self: a deserialiable object
 * @node: the xml node
 * @err: a GError for deserialisation errors
 * @...: extra parameters NULL terminated name/value pairs.
 *
 * Deserializes the given object from the @node. If @self is %NULL and a @type
 * is given it constructs a new object.
 *
 * Returns: (transfer none): the deserialized object or %NULL.
 */
BtPersistence *
bt_persistence_load (const GType type, const BtPersistence * const self,
    xmlNodePtr node, GError ** err, ...)
{
  BtPersistence *result;
  va_list var_args;

  if (!self) {
    GObjectClass *klass;
    BtPersistenceInterface *iface;

    g_return_val_if_fail (G_TYPE_IS_OBJECT (type), NULL);

    klass = g_type_class_ref (type);
    iface = g_type_interface_peek (klass, BT_TYPE_PERSISTENCE);
    va_start (var_args, err);
    result = iface->load (type, self, node, err, var_args);
    va_end (var_args);
    g_type_class_unref (klass);
  } else {
    g_return_val_if_fail (BT_IS_PERSISTENCE (self), NULL);

    va_start (var_args, err);
    result =
        BT_PERSISTENCE_GET_INTERFACE (self)->load (type, self, node, err,
        var_args);
    va_end (var_args);
  }
  return result;
}
示例#2
0
void notified (GObject *gobject, GParamSpec *pspec,
               gpointer user_data)
{
    GValue value = { 0, };
    GValue strvalue = { 0, };

    g_return_if_fail (gobject != NULL);
    g_return_if_fail (pspec != NULL);

    g_value_init (&value, pspec->value_type);
    g_value_init (&strvalue, G_TYPE_STRING);
    g_object_get_property (gobject, pspec->name, &value);

    if (pspec->value_type == G_TYPE_STRV) {
      gchar** p = (gchar **)g_value_get_boxed (&value);
      g_message ("notify::%s == ", pspec->name);
      while (*p)
        g_message ("%s", *p++);
    } else if (G_TYPE_IS_OBJECT(pspec->value_type)) {
      GObject *o = g_value_get_object (&value);
      g_message ("notify::%s == %s", pspec->name, o ? G_OBJECT_TYPE_NAME (o) : "null");
    } else {
      g_value_transform (&value, &strvalue);
      g_message ("notify::%s  = %s", pspec->name, g_value_get_string (&strvalue));
    }

    g_value_unset (&value);
    g_value_unset (&strvalue);
}
示例#3
0
/**
 * panel_a11y_query_accessible_parent_type
 * @type: widget type
 * @type_info: accessible object type info to complete
 *
 * Standard hack which figures out the #GType of the accessible
 * object for @type's parent type. Also, fills out the class_size
 * and instance_size of @type_info to match the size of the parent
 * type.
 *
 * Basically, this is the hack to use if you want to derive from
 * an accessible object implementation in gail.
 *
 * Returns: the #GType of @type's parent's accessible peer
 */
GType
panel_a11y_query_accessible_parent_type (GType      type,
					 GTypeInfo *type_info)
{
	AtkObjectFactory *factory;
	GType             parent_type;
	GType             accessible_parent_type;

	g_return_val_if_fail (G_TYPE_IS_OBJECT (type), G_TYPE_INVALID);

	parent_type = g_type_parent (type);

	factory = atk_registry_get_factory (atk_get_default_registry (), parent_type);

	accessible_parent_type = atk_object_factory_get_accessible_type (factory);

	if (type_info) {
		GTypeQuery query;

		g_type_query (accessible_parent_type, &query);

		type_info->class_size    = query.class_size;
		type_info->instance_size = query.instance_size;
	}

	return atk_object_factory_get_accessible_type (factory);
}
示例#4
0
gpointer
_g_type_struct_ref (GType the_type)
{
  if (G_TYPE_IS_INTERFACE (the_type))
    return g_type_default_interface_ref (the_type);
  else if (G_TYPE_IS_OBJECT (the_type))
    return g_type_class_ref (the_type);
  else
    g_return_val_if_reached (NULL);
}
示例#5
0
void
_g_type_struct_unref (GType    the_type,
                      gpointer type_struct)
{
  if (G_TYPE_IS_INTERFACE (the_type))
    g_type_default_interface_unref (type_struct);
  else if (G_TYPE_IS_OBJECT (the_type))
    g_type_class_unref (type_struct);
  else
    g_return_if_reached ();
}
示例#6
0
static GParamSpec *
_g_type_struct_find_property (GType        the_type,
                              gpointer     type_struct,
                              const gchar *property_name)
{
  if (G_TYPE_IS_INTERFACE (the_type))
    return g_object_interface_find_property (type_struct, property_name);
  else if (G_TYPE_IS_OBJECT (the_type))
    return g_object_class_find_property (type_struct, property_name);
  else
    g_return_val_if_reached (NULL);
}
示例#7
0
void
gkm_credential_set_data (GkmCredential *self, GType type, gpointer data)
{
	g_return_if_fail (GKM_IS_CREDENTIAL (self));

	if (data) {
		g_return_if_fail (type);
		g_return_if_fail (G_TYPE_IS_BOXED (type) || G_TYPE_IS_OBJECT (type));
	}

	clear_data (self);

	if (data) {
		self->pv->user_type = type;
		if (G_TYPE_IS_BOXED (type))
			self->pv->user_data = g_boxed_copy (type, data);
		else if (G_TYPE_IS_OBJECT (type))
			self->pv->user_data = g_object_ref (data);
		else
			g_assert_not_reached ();
	}
}
示例#8
0
static void
clear_data (GkmCredential *self)
{
	if (!self->pv->user_data)
		return;
	if (G_TYPE_IS_BOXED (self->pv->user_type))
		g_boxed_free (self->pv->user_type, self->pv->user_data);
	else if (G_TYPE_IS_OBJECT (self->pv->user_type))
		g_object_unref (self->pv->user_data);
	else
		g_assert_not_reached ();
	self->pv->user_data = NULL;
	self->pv->user_type = 0;
}
示例#9
0
static GVariant *
serialize_pspec(GvsSerializer *self, GParamSpec *pspec, const GValue *value)
{
    GvsPropertySerializeFunc func = NULL;
    GVariant *variant = NULL;
    GType type = pspec->value_type;

    /* Try to find the right serialization function */
    func = g_param_spec_get_qdata(pspec, gvs_property_serialize_func_quark());

    if (func == NULL)
    {
        if (G_TYPE_IS_FUNDAMENTAL(type))
        {
            func = serialize_fundamental;
        }
        else if (G_TYPE_IS_ENUM(type))
        {
            func = serialize_enum;
        }
        else if (G_TYPE_IS_FLAGS(type))
        {
            func = serialize_flags;
        }
        else if (G_TYPE_IS_OBJECT(type) || G_TYPE_IS_INTERFACE (type))
        {
            func = serialize_object_property;
        }
        else if (g_type_is_a(type, G_TYPE_BOXED))
        {
            func = serialize_boxed_property;
        }
    }

    if (func)
    {
        variant = func(self, value, NULL);
    }
    else
    {
        g_warning("Could not serialize property %s of type %s\n"
                  "Use gvs_register_property_serialize_func() in your class_init function\n",
                  pspec->name, g_type_name(pspec->value_type));
    }

    return variant;
}
示例#10
0
std::string
get_defs(GType gtype, GTypeIsAPointerFunc is_a_pointer_func)
{
  std::string strObjectName = g_type_name(gtype);
  std::string strDefs;

  if (G_TYPE_IS_OBJECT(gtype) || G_TYPE_IS_INTERFACE(gtype))
  {
    strDefs = ";; From " + strObjectName + "\n\n";
    strDefs += get_signals(gtype, is_a_pointer_func);
    strDefs += get_properties(gtype);
  }
  else
    strDefs = ";; " + strObjectName +
              " is neither a GObject nor a GInterface. Not checked for signals and properties.\n\n";

  return strDefs;
}
示例#11
0
gpointer
gkm_credential_pop_data (GkmCredential *self, GType type)
{
	gpointer data = NULL;
	g_return_val_if_fail (GKM_IS_CREDENTIAL (self), NULL);

	if (self->pv->user_data) {
		g_return_val_if_fail (type == self->pv->user_type, NULL);
		if (G_TYPE_IS_BOXED (self->pv->user_type))
			data = g_boxed_copy (self->pv->user_type, self->pv->user_data);
		else if (G_TYPE_IS_OBJECT (self->pv->user_type))
			data = g_object_ref (self->pv->user_data);
		else
			g_assert_not_reached ();
	}

	gkm_object_mark_used (GKM_OBJECT (self));
	return data;
}
示例#12
0
文件: object.c 项目: aswinas/gtk-
/* --- main test program --- */
int
main (int   argc,
      char *argv[])
{
  const GType *otypes;
  guint i;
  /* initialize test program */
  gtk_test_init (&argc, &argv);
  gtk_test_register_all_types ();
  /* install a property test for each widget type */
  otypes = gtk_test_list_all_types (NULL);
  for (i = 0; otypes[i]; i++)
    if (g_type_is_a (otypes[i], GTK_TYPE_WIDGET) &&
        G_TYPE_IS_OBJECT (otypes[i]) &&
        !G_TYPE_IS_ABSTRACT (otypes[i]))
      {
        gchar *testpath = g_strdup_printf ("/properties/%s", g_type_name (otypes[i]));
        g_test_add_data_func (testpath, (void*) otypes[i], widget_property_tests);
        g_free (testpath);
      }
  return g_test_run ();
}
示例#13
0
static void
print_signal_info (GstElement * element)
{
  /* Signals/Actions Block */
  guint *signals;
  guint nsignals;
  gint i = 0, j, k;
  GSignalQuery *query = NULL;
  GType type;
  GSList *found_signals, *l;

  for (k = 0; k < 2; k++) {
    found_signals = NULL;

    /* For elements that have sometimes pads, also list a few useful GstElement
     * signals. Put these first, so element-specific ones come later. */
    if (k == 0 && has_sometimes_template (element)) {
      query = g_new0 (GSignalQuery, 1);
      g_signal_query (g_signal_lookup ("pad-added", GST_TYPE_ELEMENT), query);
      found_signals = g_slist_append (found_signals, query);
      query = g_new0 (GSignalQuery, 1);
      g_signal_query (g_signal_lookup ("pad-removed", GST_TYPE_ELEMENT), query);
      found_signals = g_slist_append (found_signals, query);
      query = g_new0 (GSignalQuery, 1);
      g_signal_query (g_signal_lookup ("no-more-pads", GST_TYPE_ELEMENT),
          query);
      found_signals = g_slist_append (found_signals, query);
    }

    for (type = G_OBJECT_TYPE (element); type; type = g_type_parent (type)) {
      if (type == GST_TYPE_ELEMENT || type == GST_TYPE_OBJECT)
        break;

      if (type == GST_TYPE_BIN && G_OBJECT_TYPE (element) != GST_TYPE_BIN)
        continue;

      signals = g_signal_list_ids (type, &nsignals);
      for (i = 0; i < nsignals; i++) {
        query = g_new0 (GSignalQuery, 1);
        g_signal_query (signals[i], query);

        if ((k == 0 && !(query->signal_flags & G_SIGNAL_ACTION)) ||
            (k == 1 && (query->signal_flags & G_SIGNAL_ACTION)))
          found_signals = g_slist_append (found_signals, query);
        else
          g_free (query);
      }
      g_free (signals);
      signals = NULL;
    }

    if (found_signals) {
      n_print ("\n");
      if (k == 0)
        n_print ("Element Signals:\n");
      else
        n_print ("Element Actions:\n");
    } else {
      continue;
    }

    for (l = found_signals; l; l = l->next) {
      gchar *indent;
      const gchar *pmark;
      int indent_len;

      query = (GSignalQuery *) l->data;
      indent_len = strlen (query->signal_name) +
          strlen (g_type_name (query->return_type)) + 24;


      if (query->return_type == G_TYPE_POINTER) {
        pmark = "";
      } else if (G_TYPE_FUNDAMENTAL (query->return_type) == G_TYPE_POINTER
          || G_TYPE_IS_BOXED (query->return_type)
          || G_TYPE_IS_OBJECT (query->return_type)) {
        pmark = "* ";
        indent_len += 2;
      } else {
        pmark = "";
      }

      indent = g_new0 (gchar, indent_len + 1);
      memset (indent, ' ', indent_len);

      n_print ("  \"%s\" :  %s %suser_function (%s* object",
          query->signal_name, g_type_name (query->return_type), pmark,
          g_type_name (type));

      for (j = 0; j < query->n_params; j++) {
        g_print (",\n");
        if (G_TYPE_IS_FUNDAMENTAL (query->param_types[j])) {
          n_print ("%s%s arg%d", indent,
              g_type_name (query->param_types[j]), j);
        } else if (G_TYPE_IS_ENUM (query->param_types[j])) {
          n_print ("%s%s arg%d", indent,
              g_type_name (query->param_types[j]), j);
        } else {
          n_print ("%s%s* arg%d", indent,
              g_type_name (query->param_types[j]), j);
        }
      }

      if (k == 0) {
        g_print (",\n");
        n_print ("%sgpointer user_data);\n", indent);
      } else
        g_print (");\n");

      g_free (indent);
    }

    if (found_signals) {
      g_slist_foreach (found_signals, (GFunc) g_free, NULL);
      g_slist_free (found_signals);
    }
  }
}
示例#14
0
/**
 * gimp_config_deserialize_property:
 * @config: a #GimpConfig.
 * @scanner: a #GScanner.
 * @nest_level: the nest level
 *
 * This function deserializes a single property of @config. You
 * shouldn't need to call this function directly. If possible, use
 * gimp_config_deserialize_properties() instead.
 *
 * Return value: %G_TOKEN_RIGHT_PAREN on success, otherwise the
 * expected #GTokenType or %G_TOKEN_NONE if the expected token was
 * found but couldn't be parsed.
 *
 * Since: GIMP 2.4
 **/
GTokenType
gimp_config_deserialize_property (GimpConfig *config,
                                  GScanner   *scanner,
                                  gint        nest_level)
{
  GimpConfigInterface *config_iface = NULL;
  GimpConfigInterface *parent_iface = NULL;
  GParamSpec          *prop_spec;
  GTokenType           token = G_TOKEN_RIGHT_PAREN;
  GValue               value = { 0, };
  guint                old_scope_id;

  old_scope_id = g_scanner_set_scope (scanner, 0);

  prop_spec = G_PARAM_SPEC (scanner->value.v_symbol);

  g_value_init (&value, prop_spec->value_type);

  if (G_TYPE_IS_OBJECT (prop_spec->owner_type))
    {
      GTypeClass *owner_class = g_type_class_peek (prop_spec->owner_type);

      config_iface = g_type_interface_peek (owner_class, GIMP_TYPE_CONFIG);

      /*  We must call deserialize_property() *only* if the *exact* class
       *  which implements it is param_spec->owner_type's class.
       *
       *  Therefore, we ask param_spec->owner_type's immediate parent class
       *  for it's GimpConfigInterface and check if we get a different
       *  pointer.
       *
       *  (if the pointers are the same, param_spec->owner_type's
       *   GimpConfigInterface is inherited from one of it's parent classes
       *   and thus not able to handle param_spec->owner_type's properties).
       */
      if (config_iface)
        {
          GTypeClass *owner_parent_class;

          owner_parent_class = g_type_class_peek_parent (owner_class);

          parent_iface = g_type_interface_peek (owner_parent_class,
                                                GIMP_TYPE_CONFIG);
        }
    }

  if (config_iface                       &&
      config_iface != parent_iface       && /* see comment above */
      config_iface->deserialize_property &&
      config_iface->deserialize_property (config,
                                          prop_spec->param_id,
                                          &value,
                                          prop_spec,
                                          scanner,
                                          &token))
    {
      /* nop */
    }
  else
    {
      if (G_VALUE_HOLDS_OBJECT (&value))
        token = gimp_config_deserialize_object (&value,
                                                config, prop_spec,
                                                scanner, nest_level);
      else
        token = gimp_config_deserialize_value (&value,
                                               config, prop_spec, scanner);
    }

  if (token == G_TOKEN_RIGHT_PAREN &&
      g_scanner_peek_next_token (scanner) == token)
    {
      if (! (G_VALUE_HOLDS_OBJECT (&value) &&
             (prop_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE)))
        g_object_set_property (G_OBJECT (config), prop_spec->name, &value);
    }
#ifdef CONFIG_DEBUG
  else
    {
      g_warning ("%s: couldn't deserialize property %s::%s of type %s",
                 G_STRFUNC,
                 g_type_name (G_TYPE_FROM_INSTANCE (config)),
                 prop_spec->name,
                 g_type_name (prop_spec->value_type));
    }
#endif

  g_value_unset (&value);

  g_scanner_set_scope (scanner, old_scope_id);

  return token;
}
示例#15
0
std::string
get_signals(GType gtype, GTypeIsAPointerFunc is_a_pointer_func)
{
  std::string strResult;
  std::string strObjectName = g_type_name(gtype);

  gpointer gclass_ref = nullptr;
  gpointer ginterface_ref = nullptr;

  if (G_TYPE_IS_OBJECT(gtype))
    gclass_ref = g_type_class_ref(gtype); // Ensures that class_init() is called.
  else if (G_TYPE_IS_INTERFACE(gtype))
    ginterface_ref = g_type_default_interface_ref(gtype); // install signals.

  // Get the list of signals:
  guint iCount = 0;
  guint* pIDs = g_signal_list_ids(gtype, &iCount);

  // Loop through the list of signals:
  if (pIDs)
  {
    for (guint i = 0; i < iCount; i++)
    {
      guint signal_id = pIDs[i];

      // Name:
      std::string strName = g_signal_name(signal_id);
      strResult += "(define-signal " + strName + "\n";
      strResult += "  (of-object \"" + strObjectName + "\")\n";

      // Other information about the signal:
      GSignalQuery signalQuery = {
        0, nullptr, 0, GSignalFlags(0), 0, 0, nullptr,
      };
      g_signal_query(signal_id, &signalQuery);

      // Return type:
      std::string strReturnTypeName =
        get_type_name_signal(signalQuery.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE,
          is_a_pointer_func); // The type is mangled with a flag. Hacky.
      // bool bReturnTypeHasStaticScope = (signalQuery.return_type & G_SIGNAL_TYPE_STATIC_SCOPE) ==
      // G_SIGNAL_TYPE_STATIC_SCOPE;
      strResult += "  (return-type \"" + strReturnTypeName + "\")\n";

      // Flags:
      std::string strFlags;
      add_signal_flag_if(strFlags, "Run First", signalQuery, G_SIGNAL_RUN_FIRST);
      add_signal_flag_if(strFlags, "Run Last", signalQuery, G_SIGNAL_RUN_LAST);
      add_signal_flag_if(strFlags, "Run Cleanup", signalQuery, G_SIGNAL_RUN_CLEANUP);
      add_signal_flag_if(strFlags, "No Recurse", signalQuery, G_SIGNAL_NO_RECURSE);
      add_signal_flag_if(strFlags, "Action", signalQuery, G_SIGNAL_ACTION);
      add_signal_flag_if(strFlags, "No Hooks", signalQuery, G_SIGNAL_NO_HOOKS);
      add_signal_flag_if(strFlags, "Must Collect", signalQuery, G_SIGNAL_MUST_COLLECT);
      strResult += "  (flags \"" + strFlags + "\")\n";

      if (signalQuery.signal_flags & G_SIGNAL_DETAILED)
        strResult += "  (detailed #t)\n"; // Default: not detailed

      if (signalQuery.signal_flags & G_SIGNAL_DEPRECATED)
        strResult += "  (deprecated #t)\n"; // Default: not deprecated

      // Loop through the list of parameters:
      const GType* pParameters = signalQuery.param_types;
      if (pParameters)
      {
        strResult += "  (parameters\n";

        for (unsigned j = 0; j < signalQuery.n_params; j++)
        {
          GType typeParamMangled = pParameters[j];

          // Parameter name:
          // We can't get the real parameter name from the GObject system. It's not registered with
          // g_signal_new().
          gchar* pchNum = g_strdup_printf("%d", j);
          std::string strParamName = "p" + std::string(pchNum);
          g_free(pchNum);
          pchNum = nullptr;

          // Just like above, for the return type:
          std::string strTypeName =
            get_type_name_signal(typeParamMangled & ~G_SIGNAL_TYPE_STATIC_SCOPE,
              is_a_pointer_func); // The type is mangled with a flag. Hacky.
          // bool bTypeHasStaticScope = (typeParamMangled & G_SIGNAL_TYPE_STATIC_SCOPE) ==
          // G_SIGNAL_TYPE_STATIC_SCOPE;

          strResult += "    '(\"" + strTypeName + "\" \"" + strParamName + "\")\n";
        }

        strResult += "  )\n"; // close (parameters
      }

      strResult += ")\n\n"; // close (define-signal
    }
  }

  g_free(pIDs);

  if (gclass_ref)
    g_type_class_unref(gclass_ref); // to match the g_type_class_ref() above.
  else if (ginterface_ref)
    g_type_default_interface_unref(ginterface_ref); // for interface ref above.

  return strResult;
}
示例#16
0
// Until the glib bug https://bugzilla.gnome.org/show_bug.cgi?id=465631
// is fixed, get_properties() must be called for a GObject before it's
// called for a GInterface.
std::string
get_properties(GType gtype)
{
  std::string strResult;
  std::string strObjectName = g_type_name(gtype);

  // Get the list of properties:
  GParamSpec** ppParamSpec = nullptr;
  guint iCount = 0;
  if (G_TYPE_IS_OBJECT(gtype))
  {
    GObjectClass* pGClass = G_OBJECT_CLASS(g_type_class_ref(gtype));
    ppParamSpec = g_object_class_list_properties(pGClass, &iCount);
    g_type_class_unref(pGClass);

    if (!ppParamSpec)
    {
      strResult += ";; Warning: g_object_class_list_properties() returned NULL for " +
                   std::string(g_type_name(gtype)) + "\n";
    }
  }
  else if (G_TYPE_IS_INTERFACE(gtype))
  {
    gpointer pGInterface = g_type_default_interface_ref(gtype);
    if (pGInterface)
    {
      ppParamSpec = g_object_interface_list_properties(pGInterface, &iCount);
      g_type_default_interface_unref(pGInterface);

      if (!ppParamSpec)
      {
        strResult += ";; Warning: g_object_interface_list_properties() returned NULL for " +
                     std::string(g_type_name(gtype)) + "\n";
      }
    }
    else
      strResult += ";; Warning: g_type_default_interface_ref() returned NULL for " +
                   std::string(g_type_name(gtype)) + "\n";
  }

  // This extra check avoids an occasional crash
  if (!ppParamSpec)
    iCount = 0;

  for (guint i = 0; i < iCount; i++)
  {
    GParamSpec* pParamSpec = ppParamSpec[i];
    // Generate the property if the specified gtype actually owns the property.
    // (Generally all properties, including any base classes' properties are
    // retrieved by g_object_interface_list_properties() for a given gtype.
    // The base classes' properties should not be generated).
    if (pParamSpec && pParamSpec->owner_type == gtype)
    {
      strResult += get_property_with_node_name(pParamSpec, strObjectName, "define-property");
    }
  }

  g_free(ppParamSpec);

  return strResult;
}
示例#17
0
gboolean is_type_object(GType t) {
    return G_TYPE_IS_OBJECT(t);
}
示例#18
0
/**
 * mex_proxy_start_at:
 * @proxy: Proxy to add content to
 * @start_at_content: First content item in the model to add to
 * the proxy
 * @loop: Whether to loop back to the beginning of the
 * associated #MexModel's content items once the last item is reached;
 * if %TRUE, content items before the @start_at_content will be
 * added once the last of the model's content items is reached;
 * if %FALSE, only content items from @start_at_content to the last of
 * the model's content items are added
 *
 * Add content from a model to a proxy.
 */
void
mex_proxy_start_at (MexProxy   *proxy,
                    MexContent *start_at_content,
                    gboolean    loop)
{
  gint i;
  MexContent *content;
  MexProxyPrivate *priv;
  GController *controller;

  g_return_if_fail (MEX_IS_PROXY (proxy));

  priv = proxy->priv;

  if (priv->started)
    {
      g_warning (G_STRLOC ": Trying to start an already started proxy");
      return;
    }

  mex_proxy_clear (proxy);
  priv->started = TRUE;

  if (!priv->model)
    return;

  if (!G_TYPE_IS_OBJECT (priv->object_type))
    {
      g_warning (G_STRLOC ": Proxy type is not an object type");
      return;
    }

  /* Iterate over existing objects */
  if (!start_at_content)
    {
      i = 0;
      while ((content = mex_model_get_content (priv->model, i++)))
        mex_proxy_add_content (proxy, content);
    }
  else
    {
      gint start_at;
      gboolean looped = FALSE;

      start_at = mex_model_index (priv->model, start_at_content);

      if (start_at == -1)
        {
          g_critical (G_STRLOC ": Content %p not found in %p model",
                      start_at_content, priv->model);
          return;
        }

      for (i = start_at; TRUE; i++)
        {
          /* break out if looped and back around to start_at */
          if (loop && looped && i == start_at)
            break;

          if ((content = mex_model_get_content (priv->model, i)))
            {
              mex_proxy_add_content (proxy, content);
            }
          else
            {
              if (loop)
                {
                  looped = TRUE;
                  i = -1;
                }
              else
                break;
            }

        }
    }

  controller = mex_model_get_controller (priv->model);
  g_signal_connect_after (controller, "changed",
                          G_CALLBACK (mex_proxy_controller_changed_cb), proxy);
}