static void
champlain_map_source_desc_get_property (GObject *object,
    guint prop_id,
    GValue *value,
    GParamSpec *pspec)
{
  ChamplainMapSourceDescPrivate *priv = CHAMPLAIN_MAP_SOURCE_DESC (object)->priv;

  switch (prop_id)
    {
    case PROP_ID:
      g_value_set_string (value, priv->id);
      break;

    case PROP_NAME:
      g_value_set_string (value, priv->name);
      break;

    case PROP_LICENSE:
      g_value_set_string (value, priv->license);
      break;

    case PROP_LICENSE_URI:
      g_value_set_string (value, priv->license_uri);
      break;

    case PROP_URI_FORMAT:
      g_value_set_string (value, priv->uri_format);
      break;

    case PROP_MIN_ZOOM_LEVEL:
      g_value_set_uint (value, priv->min_zoom_level);
      break;

    case PROP_MAX_ZOOM_LEVEL:
      g_value_set_uint (value, priv->max_zoom_level);
      break;

    case PROP_TILE_SIZE:
      g_value_set_uint (value, priv->tile_size);
      break;

    case PROP_PROJECTION:
      g_value_set_enum (value, priv->projection);
      break;

    case PROP_CONSTRUCTOR:
      g_value_set_pointer (value, priv->constructor);
      break;

    case PROP_DATA:
      g_value_set_pointer (value, priv->data);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}
static void
champlain_map_source_desc_set_property (GObject *object,
    guint prop_id,
    const GValue *value,
    GParamSpec *pspec)
{
  ChamplainMapSourceDesc *desc = CHAMPLAIN_MAP_SOURCE_DESC (object);

  switch (prop_id)
    {
    case PROP_ID:
      set_id (desc, g_value_get_string (value));

    case PROP_NAME:
      set_name (desc, g_value_get_string (value));
      break;

    case PROP_LICENSE:
      set_license (desc, g_value_get_string (value));
      break;

    case PROP_LICENSE_URI:
      set_license_uri (desc, g_value_get_string (value));
      break;

    case PROP_URI_FORMAT:
      set_uri_format (desc, g_value_get_string (value));
      break;

    case PROP_MIN_ZOOM_LEVEL:
      set_min_zoom_level (desc, g_value_get_uint (value));
      break;

    case PROP_MAX_ZOOM_LEVEL:
      set_max_zoom_level (desc, g_value_get_uint (value));
      break;

    case PROP_TILE_SIZE:
      set_tile_size (desc, g_value_get_uint (value));
      break;

    case PROP_PROJECTION:
      set_projection (desc, g_value_get_enum (value));
      break;

    case PROP_CONSTRUCTOR:
      set_constructor (desc, g_value_get_pointer (value));
      break;

    case PROP_DATA:
      set_data (desc, g_value_get_pointer (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}
static void
champlain_map_source_desc_finalize (GObject *object)
{
  ChamplainMapSourceDescPrivate *priv = CHAMPLAIN_MAP_SOURCE_DESC (object)->priv;

  g_free (priv->id);
  g_free (priv->name);
  g_free (priv->license);
  g_free (priv->license_uri);
  g_free (priv->uri_format);

  G_OBJECT_CLASS (champlain_map_source_desc_parent_class)->finalize (object);
}
/**
 * champlain_map_source_factory_create:
 * @factory: the Factory
 * @id: the wanted map source id
 *
 * The id should not contain any character that can't be in a filename as it
 * will be used as the cache directory name for that map source.
 *
 * Returns: a ready to use #ChamplainMapSource matching the given name, returns
 * NULL is none match.
 *
 * Since: 0.4
 */
ChamplainMapSource *
champlain_map_source_factory_create (ChamplainMapSourceFactory *factory,
    const gchar *id)
{
  GSList *item;

  item = factory->priv->registered_sources;

  while (item != NULL)
    {
      ChamplainMapSourceDesc *desc = CHAMPLAIN_MAP_SOURCE_DESC (item->data);
      if (strcmp (desc->id, id) == 0)
        return desc->constructor (desc, desc->data);
      item = g_slist_next (item);
    }

  return NULL;
}
static void
build_combo_box (GtkComboBox *box)
{
  ChamplainMapSourceFactory *factory;
  GSList *sources, *iter;
  GtkTreeStore *store;
  GtkTreeIter parent;
  GtkCellRenderer *cell;

  store = gtk_tree_store_new (N_COLS, G_TYPE_STRING, /* id */
        G_TYPE_STRING, /* name */
        -1);

  factory = champlain_map_source_factory_dup_default ();
  sources = champlain_map_source_factory_get_registered (factory);

  iter = sources;
  while (iter != NULL)
    {
      ChamplainMapSourceDesc *desc = CHAMPLAIN_MAP_SOURCE_DESC (iter->data);
      const gchar *id = champlain_map_source_desc_get_id (desc);
      const gchar *name = champlain_map_source_desc_get_name (desc);

      gtk_tree_store_append (store, &parent, NULL);
      gtk_tree_store_set (store, &parent, COL_ID, id,
          COL_NAME, name, -1);

      iter = g_slist_next (iter);
    }

  g_slist_free (sources);
  g_object_unref (factory);

  gtk_combo_box_set_model (box, GTK_TREE_MODEL (store));

  cell = gtk_cell_renderer_text_new ();
  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (box), cell, FALSE);
  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (box), cell,
      "text", COL_NAME, NULL);
}