[libchamplain] New map and cache loading infrastructure
- From: Pierre-Luc Beaudoin <plbeaudoin src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [libchamplain] New map and cache loading infrastructure
- Date: Sun, 24 Jan 2010 20:15:07 +0000 (UTC)
commit c8508f5e1dcdf44e5353ebd2474034c830ff8b93
Author: JiÅ?Ã Techet <techet gmail com>
Date: Mon Jan 18 00:51:10 2010 +0100
New map and cache loading infrastructure
New infrastructure for mutually cooperating and exchangeable caches
and map sources.
Signed-off-by: JiÅ?Ã Techet <techet gmail com>
champlain/Makefile.am | 33 +-
champlain/champlain-cache.c | 870 ----------------------------
champlain/champlain-cache.h | 94 ---
champlain/champlain-defines.h | 4 +-
champlain/champlain-error-tile-source.c | 130 +++++
champlain/champlain-error-tile-source.h | 57 ++
champlain/champlain-file-cache.c | 897 +++++++++++++++++++++++++++++
champlain/champlain-file-cache.h | 68 +++
champlain/champlain-map-data-source.c | 2 +-
champlain/champlain-map-data-source.h | 4 +-
champlain/champlain-map-source-chain.c | 288 +++++++++
champlain/champlain-map-source-chain.h | 61 ++
champlain/champlain-map-source-desc.h | 2 +-
champlain/champlain-map-source-factory.c | 46 ++-
champlain/champlain-map-source.c | 835 ++++++---------------------
champlain/champlain-map-source.h | 107 ++--
champlain/champlain-memphis-map-source.c | 651 +++++++++------------
champlain/champlain-memphis-map-source.h | 27 +-
champlain/champlain-network-map-source.c | 642 ---------------------
champlain/champlain-network-map-source.h | 77 ---
champlain/champlain-network-tile-source.c | 570 ++++++++++++++++++
champlain/champlain-network-tile-source.h | 78 +++
champlain/champlain-private.h | 3 -
champlain/champlain-tile-cache.c | 273 +++++++++
champlain/champlain-tile-cache.h | 74 +++
champlain/champlain-tile-source.c | 510 ++++++++++++++++
champlain/champlain-tile-source.h | 86 +++
champlain/champlain-tile.c | 132 +-----
champlain/champlain-tile.h | 6 -
champlain/champlain-view.c | 33 +-
champlain/champlain.h | 8 +-
demos/launcher-gtk.c | 26 +-
demos/local-rendering.c | 171 +++---
33 files changed, 3836 insertions(+), 3029 deletions(-)
---
diff --git a/champlain/Makefile.am b/champlain/Makefile.am
index 6495b7e..30e049d 100644
--- a/champlain/Makefile.am
+++ b/champlain/Makefile.am
@@ -27,7 +27,12 @@ libchamplain_headers = \
champlain-enum-types.h \
champlain-tile.h \
champlain-map-source.h \
- champlain-network-map-source.h \
+ champlain-map-source-chain.h \
+ champlain-tile-source.h \
+ champlain-tile-cache.h \
+ champlain-network-tile-source.h \
+ champlain-error-tile-source.h \
+ champlain-file-cache.h \
champlain-map-source-factory.h \
champlain-map-source-desc.h \
champlain-polygon.h \
@@ -51,11 +56,15 @@ libchamplain_0_5_la_SOURCES = \
champlain-zoom-level.c \
champlain-tile.c \
champlain-map-source.c \
- champlain-network-map-source.c \
+ champlain-map-source-chain.c \
+ champlain-tile-source.c \
+ champlain-tile-cache.c \
+ champlain-network-tile-source.c \
+ champlain-error-tile-source.c \
+ champlain-file-cache.c \
champlain-map-source-factory.c \
champlain-map-source-desc.c \
champlain-point.c \
- champlain-cache.c \
champlain-polygon.c \
champlain-memphis-map-source.c \
champlain-map-data-source.c \
@@ -75,10 +84,15 @@ noinst_HEADERS = \
champlain-tile.h \
champlain-enum-types.h \
champlain-map-source.h \
- champlain-network-map-source.h \
+ champlain-map-source-chain.h \
+ champlain-tile-source.h \
+ champlain-tile-cache.h \
+ champlain-network-tile-source.h \
+ champlain-error-tile-source.h \
+ champlain-file-cache.h \
+ champlain-enum-types.h \
champlain-map-source-factory.h \
champlain-map-source-desc.h \
- champlain-cache.h \
champlain-polygon.h \
champlain-version.h
@@ -91,15 +105,20 @@ libchamplain_include_HEADERS = \
champlain-layer.h \
champlain-selection-layer.h \
champlain-map-source.h \
- champlain-network-map-source.h \
+ champlain-map-source-chain.h \
+ champlain-tile-source.h \
+ champlain-tile-cache.h \
+ champlain-network-tile-source.h \
+ champlain-error-tile-source.h \
+ champlain-file-cache.h \
champlain-map-source-factory.h \
champlain-map-source-desc.h \
champlain-tile.h \
champlain-zoom-level.h \
champlain-base-marker.h \
champlain-marker.h \
- champlain-cache.h \
champlain-polygon.h \
+ champlain-version.h
champlain-version.h \
champlain-memphis-map-source.h \
champlain-map-data-source.h \
diff --git a/champlain/champlain-defines.h b/champlain/champlain-defines.h
index 8a279a5..90755f9 100644
--- a/champlain/champlain-defines.h
+++ b/champlain/champlain-defines.h
@@ -29,6 +29,8 @@
typedef struct _ChamplainView ChamplainView;
typedef struct _ChamplainViewClass ChamplainViewClass;
+typedef struct _ChamplainMapSource ChamplainMapSource;
+
#define CHAMPLAIN_PARAM_READABLE \
(G_PARAM_READABLE | \
G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB)
@@ -42,8 +44,6 @@ typedef enum
CHAMPLAIN_STATE_NONE,
CHAMPLAIN_STATE_INIT,
CHAMPLAIN_STATE_LOADING,
- CHAMPLAIN_STATE_VALIDATING_CACHE, /* Use by tiles when there is cache,
- but it is being validated */
CHAMPLAIN_STATE_DONE
} ChamplainState;
diff --git a/champlain/champlain-error-tile-source.c b/champlain/champlain-error-tile-source.c
new file mode 100644
index 0000000..918e90a
--- /dev/null
+++ b/champlain/champlain-error-tile-source.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2008-2009 Pierre-Luc Beaudoin <pierre-luc pierlux com>
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "champlain-error-tile-source.h"
+
+G_DEFINE_TYPE (ChamplainErrorTileSource, champlain_error_tile_source, CHAMPLAIN_TYPE_TILE_SOURCE);
+
+#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHAMPLAIN_TYPE_ERROR_TILE_SOURCE, ChamplainErrorTileSourcePrivate))
+
+typedef struct _ChamplainErrorTileSourcePrivate ChamplainErrorTileSourcePrivate;
+
+struct _ChamplainErrorTileSourcePrivate
+{
+ ClutterActor *error_actor;
+};
+
+static void fill_tile (ChamplainMapSource *map_source, ChamplainTile *tile);
+
+static void
+champlain_error_tile_source_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (champlain_error_tile_source_parent_class)->dispose (object);
+}
+
+static void
+champlain_error_tile_source_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (champlain_error_tile_source_parent_class)->finalize (object);
+}
+
+static void
+champlain_error_tile_source_class_init (ChamplainErrorTileSourceClass *klass)
+{
+ ChamplainMapSourceClass *map_source_class = CHAMPLAIN_MAP_SOURCE_CLASS (klass);
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (ChamplainErrorTileSourcePrivate));
+
+ object_class->finalize = champlain_error_tile_source_finalize;
+ object_class->dispose = champlain_error_tile_source_dispose;
+
+ map_source_class->fill_tile = fill_tile;
+}
+
+static void
+champlain_error_tile_source_init (ChamplainErrorTileSource *error_source)
+{
+ ChamplainErrorTileSourcePrivate *priv = GET_PRIVATE(error_source);
+ priv->error_actor = NULL;
+}
+
+ChamplainErrorTileSource* champlain_error_tile_source_new_full (guint tile_size)
+{
+ return g_object_new (CHAMPLAIN_TYPE_ERROR_TILE_SOURCE, "tile-size", tile_size, NULL);
+}
+
+static void
+fill_tile (ChamplainMapSource *map_source, ChamplainTile *tile)
+{
+ g_return_if_fail (CHAMPLAIN_IS_ERROR_TILE_SOURCE (map_source));
+ g_return_if_fail (CHAMPLAIN_IS_TILE (tile));
+
+ ChamplainErrorTileSourcePrivate *priv = GET_PRIVATE(map_source);
+ ClutterActor *clone;
+ guint size;
+
+ if (champlain_tile_get_content(tile))
+ /* cache is just validating tile - don't generate error tile in this case */
+ return;
+
+ size = champlain_map_source_get_tile_size (map_source);
+
+ if (!priv->error_actor)
+ {
+ cairo_t *cr;
+ cairo_pattern_t *pat;
+ ClutterActor *stage;
+
+ priv->error_actor = clutter_cairo_texture_new (size, size);
+ cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (priv->error_actor));
+ stage = clutter_stage_get_default ();
+
+ /* draw a linear gray to white pattern */
+ pat = cairo_pattern_create_linear (size / 2.0, 0.0, size, size / 2.0);
+ cairo_pattern_add_color_stop_rgb (pat, 0, 0.686, 0.686, 0.686);
+ cairo_pattern_add_color_stop_rgb (pat, 1, 0.925, 0.925, 0.925);
+ cairo_set_source (cr, pat);
+ cairo_rectangle (cr, 0, 0, size, size);
+ cairo_fill (cr);
+
+ cairo_pattern_destroy (pat);
+
+ /* draw the red cross */
+ cairo_set_source_rgb (cr, 0.424, 0.078, 0.078);
+ cairo_set_line_width (cr, 14.0);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_move_to (cr, 24, 24);
+ cairo_line_to (cr, 50, 50);
+ cairo_move_to (cr, 50, 24);
+ cairo_line_to (cr, 24, 50);
+ cairo_stroke (cr);
+
+ cairo_destroy (cr);
+
+ clutter_container_add_actor (CLUTTER_CONTAINER (stage), priv->error_actor);
+ clutter_actor_hide (priv->error_actor);
+ }
+
+ clone = clutter_clone_new (priv->error_actor);
+
+ champlain_tile_set_content (tile, clone, TRUE);
+ champlain_tile_set_size (tile, size);
+ champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
+}
diff --git a/champlain/champlain-error-tile-source.h b/champlain/champlain-error-tile-source.h
new file mode 100644
index 0000000..aaea565
--- /dev/null
+++ b/champlain/champlain-error-tile-source.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008-2009 Pierre-Luc Beaudoin <pierre-luc pierlux com>
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if !defined (__CHAMPLAIN_CHAMPLAIN_H_INSIDE__) && !defined (CHAMPLAIN_COMPILATION)
+#error "Only <champlain/champlain.h> can be included directly."
+#endif
+
+#ifndef _CHAMPLAIN_ERROR_TILE_SOURCE_H_
+#define _CHAMPLAIN_ERROR_TILE_SOURCE_H_
+
+#include <champlain/champlain-tile-source.h>
+
+G_BEGIN_DECLS
+
+#define CHAMPLAIN_TYPE_ERROR_TILE_SOURCE (champlain_error_tile_source_get_type ())
+#define CHAMPLAIN_ERROR_TILE_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CHAMPLAIN_TYPE_ERROR_TILE_SOURCE, ChamplainErrorTileSource))
+#define CHAMPLAIN_ERROR_TILE_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CHAMPLAIN_TYPE_ERROR_TILE_SOURCE, ChamplainErrorTileSourceClass))
+#define CHAMPLAIN_IS_ERROR_TILE_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CHAMPLAIN_TYPE_ERROR_TILE_SOURCE))
+#define CHAMPLAIN_IS_ERROR_TILE_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CHAMPLAIN_TYPE_ERROR_TILE_SOURCE))
+#define CHAMPLAIN_ERROR_TILE_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CHAMPLAIN_TYPE_ERROR_TILE_SOURCE, ChamplainErrorTileSourceClass))
+
+typedef struct _ChamplainErrorTileSource ChamplainErrorTileSource;
+typedef struct _ChamplainErrorTileSourceClass ChamplainErrorTileSourceClass;
+
+struct _ChamplainErrorTileSource
+{
+ ChamplainTileSource parent_instance;
+};
+
+struct _ChamplainErrorTileSourceClass
+{
+ ChamplainTileSourceClass parent_class;
+};
+
+GType champlain_error_tile_source_get_type (void);
+
+ChamplainErrorTileSource* champlain_error_tile_source_new_full (guint tile_size);
+
+G_END_DECLS
+
+#endif /* _CHAMPLAIN_ERROR_TILE_SOURCE_H_ */
diff --git a/champlain/champlain-file-cache.c b/champlain/champlain-file-cache.c
new file mode 100644
index 0000000..b18c916
--- /dev/null
+++ b/champlain/champlain-file-cache.c
@@ -0,0 +1,897 @@
+/*
+ * Copyright (C) 2009 Pierre-Luc Beaudoin <pierre-luc pierlux com>
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define DEBUG_FLAG CHAMPLAIN_DEBUG_CACHE
+#include "champlain-debug.h"
+
+#include "champlain-file-cache.h"
+
+#include <sqlite3.h>
+#include <errno.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <string.h>
+#include <stdlib.h>
+
+G_DEFINE_TYPE (ChamplainFileCache, champlain_file_cache, CHAMPLAIN_TYPE_TILE_CACHE);
+
+#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHAMPLAIN_TYPE_FILE_CACHE, ChamplainFileCachePrivate))
+
+enum
+{
+ PROP_0,
+ PROP_SIZE_LIMIT,
+ PROP_CACHE_DIR
+};
+
+typedef struct _ChamplainFileCachePrivate ChamplainFileCachePrivate;
+
+struct _ChamplainFileCachePrivate
+{
+ guint size_limit;
+ gchar *cache_dir;
+
+ gchar *real_cache_dir;
+ sqlite3 *db;
+ sqlite3_stmt *stmt_select;
+ sqlite3_stmt *stmt_update;
+};
+
+static void finalize_sql(ChamplainFileCache *file_cache);
+static void delete_temp_cache (ChamplainFileCache *file_cache);
+static void init_cache (ChamplainFileCache *file_cache);
+static gchar *get_filename (ChamplainFileCache *file_cache, ChamplainTile *tile);
+static gboolean tile_is_expired (ChamplainFileCache *file_cache, ChamplainTile *tile);
+static void delete_tile (ChamplainFileCache *file_cache, const gchar *filename);
+static void delete_dir_recursive (GFile *parent);
+
+static void fill_tile (ChamplainMapSource *map_source,
+ ChamplainTile *tile);
+
+static void store_tile (ChamplainTileCache *tile_cache,
+ ChamplainTile *tile,
+ const gchar *contents,
+ gsize size);
+static void refresh_tile_time (ChamplainTileCache *tile_cache, ChamplainTile *tile);
+static void on_tile_filled (ChamplainTileCache *tile_cache, ChamplainTile *tile);
+static void clean (ChamplainTileCache *tile_cache);
+
+static void
+champlain_file_cache_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE (object);
+
+ switch (property_id)
+ {
+ case PROP_SIZE_LIMIT:
+ g_value_set_uint (value, champlain_file_cache_get_size_limit (file_cache));
+ break;
+ case PROP_CACHE_DIR:
+ g_value_set_string (value, champlain_file_cache_get_cache_dir (file_cache));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+champlain_file_cache_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE (object);
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (object);
+
+ switch (property_id)
+ {
+ case PROP_SIZE_LIMIT:
+ champlain_file_cache_set_size_limit (file_cache, g_value_get_uint (value));
+ break;
+ case PROP_CACHE_DIR:
+ priv->cache_dir = g_strdup (g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+champlain_file_cache_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (champlain_file_cache_parent_class)->dispose (object);
+}
+
+static void
+finalize_sql(ChamplainFileCache *file_cache)
+{
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (file_cache);
+ gint error;
+
+ if (priv->stmt_select)
+ {
+ sqlite3_finalize (priv->stmt_select);
+ priv->stmt_select = NULL;
+ }
+
+ if (priv->stmt_update)
+ {
+ sqlite3_finalize (priv->stmt_update);
+ priv->stmt_update = NULL;
+ }
+
+ if (priv->db)
+ {
+ error = sqlite3_close (priv->db);
+ if (error != SQLITE_OK)
+ DEBUG ("Sqlite returned error %d when closing cache.db", error);
+ priv->db = NULL;
+ }
+}
+
+static void
+delete_temp_cache (ChamplainFileCache *file_cache)
+{
+ ChamplainTileCache *tile_cache = CHAMPLAIN_TILE_CACHE(file_cache);
+ ChamplainFileCachePrivate *priv = GET_PRIVATE(file_cache);
+
+ if (!champlain_tile_cache_get_persistent(tile_cache) && priv->real_cache_dir)
+ {
+ GFile *file = NULL;
+
+ /* delete the directory contents */
+ file = g_file_new_for_path (priv->real_cache_dir);
+ delete_dir_recursive (file);
+
+ /* delete the directory itself */
+ if (!g_file_delete (file, NULL, NULL))
+ g_warning ("Failed to remove temporary cache main directory");
+
+ g_object_unref (file);
+ }
+}
+
+static void
+champlain_file_cache_finalize (GObject *object)
+{
+ ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE(object);
+ ChamplainTileCache *tile_cache = CHAMPLAIN_TILE_CACHE(file_cache);
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (file_cache);
+
+ finalize_sql (file_cache);
+
+ if (!champlain_tile_cache_get_persistent(tile_cache))
+ delete_temp_cache(file_cache);
+
+ g_free(priv->real_cache_dir);
+ g_free(priv->cache_dir);
+
+ G_OBJECT_CLASS (champlain_file_cache_parent_class)->finalize (object);
+}
+
+static void
+init_cache (ChamplainFileCache *file_cache)
+{
+ ChamplainTileCache *tile_cache = CHAMPLAIN_TILE_CACHE(file_cache);
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (file_cache);
+ gchar *filename = NULL;
+ gchar *error_msg = NULL;
+ gint error;
+
+ /* If needed, create the cache's dirs */
+ if (priv->cache_dir)
+ {
+ if (g_mkdir_with_parents (priv->cache_dir, 0700) == -1 && errno != EEXIST)
+ {
+ g_warning ("Unable to create the image cache path '%s': %s",
+ priv->cache_dir, g_strerror (errno));
+ return;
+ }
+ }
+
+ if (champlain_tile_cache_get_persistent(tile_cache))
+ priv->real_cache_dir = g_strdup(priv->cache_dir);
+ else
+ {
+ /* Create temporary directory for non-persistent caches */
+ gchar *tmplate = NULL;
+
+ if (priv->cache_dir)
+ tmplate = g_build_filename (priv->cache_dir, "champlain-XXXXXX", NULL);
+ else
+ tmplate = g_build_filename (g_get_tmp_dir (), "champlain-XXXXXX", NULL);
+
+ priv->real_cache_dir = mkdtemp(tmplate);
+
+ if (!priv->real_cache_dir)
+ {
+ g_warning ("Filed to create filename for temporary cache");
+ g_free(tmplate);
+ }
+ }
+
+ g_return_if_fail (priv->real_cache_dir);
+
+ filename = g_build_filename (priv->real_cache_dir,
+ "cache.db", NULL);
+ error = sqlite3_open_v2 (filename, &priv->db,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
+ g_free (filename);
+
+ if (error == SQLITE_ERROR)
+ {
+ DEBUG ("Sqlite returned error %d when opening cache.db", error);
+ return;
+ }
+
+ sqlite3_exec (priv->db,
+ "PRAGMA synchronous=OFF;"
+ "PRAGMA count_changes=OFF;",
+ NULL, NULL, &error_msg);
+ if (error_msg != NULL)
+ {
+ DEBUG ("Set PRAGMA: %s", error_msg);
+ sqlite3_free (error_msg);
+ return;
+ }
+
+ sqlite3_exec (priv->db,
+ "CREATE TABLE IF NOT EXISTS tiles ("
+ "filename TEXT PRIMARY KEY, "
+ "etag TEXT, "
+ "popularity INT DEFAULT 1, "
+ "size INT DEFAULT 0)",
+ NULL, NULL, &error_msg);
+ if (error_msg != NULL)
+ {
+ DEBUG ("Creating table 'tiles' failed: %s", error_msg);
+ sqlite3_free (error_msg);
+ return;
+ }
+
+ error = sqlite3_prepare_v2 (priv->db,
+ "SELECT etag FROM tiles WHERE filename = ?", -1,
+ &priv->stmt_select, NULL);
+ if (error != SQLITE_OK)
+ {
+ priv->stmt_select = NULL;
+ DEBUG ("Failed to prepare the select Etag statement, error:%d: %s",
+ error, sqlite3_errmsg (priv->db));
+ return;
+ }
+
+ error = sqlite3_prepare_v2 (priv->db,
+ "UPDATE tiles SET popularity = popularity + 1 WHERE filename = ?", -1,
+ &priv->stmt_update, NULL);
+ if (error != SQLITE_OK)
+ {
+ priv->stmt_update = NULL;
+ DEBUG ("Failed to prepare the update popularity statement, error: %s",
+ sqlite3_errmsg (priv->db));
+ return;
+ }
+
+ g_object_notify (G_OBJECT (file_cache), "cache-dir");
+}
+
+static void
+champlain_file_cache_constructed (GObject *object)
+{
+ ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE(object);
+
+ init_cache(file_cache);
+
+ G_OBJECT_CLASS (champlain_file_cache_parent_class)->constructed (object);
+}
+
+static void
+champlain_file_cache_class_init (ChamplainFileCacheClass *klass)
+{
+ ChamplainMapSourceClass *map_source_class = CHAMPLAIN_MAP_SOURCE_CLASS (klass);
+ ChamplainTileCacheClass *tile_cache_class = CHAMPLAIN_TILE_CACHE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GParamSpec *pspec;
+
+ g_type_class_add_private (klass, sizeof (ChamplainFileCachePrivate));
+
+ object_class->finalize = champlain_file_cache_finalize;
+ object_class->dispose = champlain_file_cache_dispose;
+ object_class->get_property = champlain_file_cache_get_property;
+ object_class->set_property = champlain_file_cache_set_property;
+ object_class->constructed = champlain_file_cache_constructed;
+
+ pspec = g_param_spec_uint ("size-limit",
+ "Size Limit",
+ "The cache's size limit (Mb)",
+ 1,
+ G_MAXINT,
+ 100000000,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_SIZE_LIMIT, pspec);
+
+ pspec = g_param_spec_string ("cache-dir",
+ "Cache Directory",
+ "The directory of the cache",
+ "",
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_CACHE_DIR, pspec);
+
+ tile_cache_class->store_tile = store_tile;
+ tile_cache_class->refresh_tile_time = refresh_tile_time;
+ tile_cache_class->on_tile_filled = on_tile_filled;
+ tile_cache_class->clean = clean;
+
+ map_source_class->fill_tile = fill_tile;
+}
+
+static void
+champlain_file_cache_init (ChamplainFileCache *file_cache)
+{
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (file_cache);
+
+ priv->size_limit = 0;
+ priv->cache_dir = NULL;
+
+ priv->real_cache_dir = NULL;
+ priv->db = NULL;
+ priv->stmt_select = NULL;
+ priv->stmt_update = NULL;
+}
+
+ChamplainFileCache* champlain_file_cache_new_full (guint size_limit,
+ const gchar *cache_dir, gboolean persistent)
+{
+ ChamplainFileCache * cache;
+ cache = g_object_new (CHAMPLAIN_TYPE_FILE_CACHE, "size-limit", size_limit,
+ "cache-dir", cache_dir, "persistent-cache", persistent, NULL);
+ return cache;
+}
+
+guint
+champlain_file_cache_get_size_limit (ChamplainFileCache *file_cache)
+{
+ g_return_val_if_fail(CHAMPLAIN_IS_FILE_CACHE (file_cache), 0);
+
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (file_cache);
+ return priv->size_limit;
+}
+
+const gchar *
+champlain_file_cache_get_cache_dir (ChamplainFileCache *file_cache)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_FILE_CACHE (file_cache), NULL);
+
+ ChamplainFileCachePrivate *priv = GET_PRIVATE(file_cache);
+ return priv->cache_dir;
+}
+
+void
+champlain_file_cache_set_size_limit (ChamplainFileCache *file_cache,
+ guint size_limit)
+{
+ g_return_if_fail (CHAMPLAIN_IS_FILE_CACHE (file_cache));
+
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (file_cache);
+
+ priv->size_limit = size_limit;
+ g_object_notify (G_OBJECT (file_cache), "size-limit");
+}
+
+static gchar *
+get_filename (ChamplainFileCache *file_cache, ChamplainTile *tile)
+{
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (file_cache);
+
+ g_return_val_if_fail (CHAMPLAIN_IS_FILE_CACHE (file_cache), NULL);
+ g_return_val_if_fail(CHAMPLAIN_IS_TILE (tile), NULL);
+ g_return_val_if_fail(priv->real_cache_dir, NULL);
+
+ ChamplainMapSource* map_source = CHAMPLAIN_MAP_SOURCE(file_cache);
+
+ gchar *filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S
+ "%s" G_DIR_SEPARATOR_S
+ "%d" G_DIR_SEPARATOR_S
+ "%d" G_DIR_SEPARATOR_S "%d.png",
+ priv->real_cache_dir,
+ champlain_map_source_get_id (map_source),
+ champlain_tile_get_zoom_level (tile),
+ champlain_tile_get_x (tile),
+ champlain_tile_get_y (tile));
+ return filename;
+}
+
+static gboolean
+tile_is_expired (ChamplainFileCache *file_cache, ChamplainTile *tile)
+{
+ g_return_val_if_fail(CHAMPLAIN_FILE_CACHE (file_cache), FALSE);
+ g_return_val_if_fail(CHAMPLAIN_TILE (tile), FALSE);
+
+ GTimeVal now = {0, };
+ const GTimeVal *modified_time = champlain_tile_get_modified_time (tile);
+ gboolean validate_cache = TRUE;
+
+ if (modified_time)
+ {
+ g_get_current_time (&now);
+ g_time_val_add (&now, (-24ul * 60ul * 60ul * 1000ul * 1000ul * 7ul)); // Cache expires in 7 days
+ validate_cache = modified_time->tv_sec < now.tv_sec;
+ }
+
+ DEBUG ("%p is %s expired", tile, (validate_cache ? "": "not"));
+
+ return validate_cache;
+}
+
+static void
+fill_tile (ChamplainMapSource *map_source,
+ ChamplainTile *tile)
+{
+ g_return_if_fail(CHAMPLAIN_IS_FILE_CACHE (map_source));
+ g_return_if_fail(CHAMPLAIN_IS_TILE (tile));
+
+ ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE(map_source);
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (file_cache);
+ GFileInfo *info = NULL;
+ GFile *file = NULL;
+ GError *gerror = NULL;
+ ClutterActor *actor = NULL;
+ gchar *filename = NULL;
+ GTimeVal modified_time = {0,};
+
+ if (champlain_tile_get_content (tile))
+ /* Previous cache in the chain is validating its contents */
+ goto load_next;
+
+ filename = get_filename (file_cache, tile);
+ DEBUG ("fill of %s", filename);
+
+ /* Load the cached version */
+ actor = clutter_texture_new_from_file (filename, &gerror);
+ if (actor)
+ {
+ champlain_tile_set_content (tile, actor, FALSE);
+ champlain_tile_set_size (tile, champlain_map_source_get_tile_size(map_source));
+ }
+ else
+ {
+ DEBUG ("Failed to load tile %s, error: %s",
+ filename, gerror->message);
+ g_error_free (gerror);
+ goto load_next;
+ }
+
+ /* Retrieve modification time */
+ file = g_file_new_for_path (filename);
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED "," G_FILE_ATTRIBUTE_ETAG_VALUE,
+ G_FILE_QUERY_INFO_NONE, NULL, NULL);
+ if (info)
+ {
+ g_file_info_get_modification_time (info, &modified_time);
+ champlain_tile_set_modified_time (tile, &modified_time);
+ }
+ g_object_unref (file);
+ g_object_unref (info);
+
+ /* Notify other caches that the tile has been filled */
+ if (CHAMPLAIN_IS_TILE_CACHE(next_source))
+ {
+ on_tile_filled(CHAMPLAIN_TILE_CACHE(next_source), tile);
+ }
+
+ if (tile_is_expired (file_cache, tile))
+ {
+ int sql_rc = SQLITE_OK;
+
+ /* Retrieve etag */
+ sql_rc = sqlite3_bind_text (priv->stmt_select, 1, filename, -1, SQLITE_STATIC);
+ if (sql_rc == SQLITE_ERROR)
+ {
+ DEBUG ("Failed to prepare the SQL query for finding the Etag of '%s', error: %s",
+ filename, sqlite3_errmsg (priv->db));
+ goto load_next;
+ }
+
+ sql_rc = sqlite3_step (priv->stmt_select);
+ if (sql_rc == SQLITE_ROW)
+ {
+ const gchar *etag = (const gchar *) sqlite3_column_text (priv->stmt_select, 0);
+ champlain_tile_set_etag (CHAMPLAIN_TILE (tile), etag);
+ }
+ else if (sql_rc == SQLITE_DONE)
+ {
+ DEBUG ("'%s' does't have an etag",
+ filename);
+ goto load_next;
+ }
+ else if (sql_rc == SQLITE_ERROR)
+ {
+ DEBUG ("Failed to finding the Etag of '%s', %d error: %s",
+ filename, sql_rc, sqlite3_errmsg (priv->db));
+ goto load_next;
+ }
+
+ /* Validate the tile */
+ /* goto load_next; */
+ }
+ else
+ {
+ /* Tile loaded and no validation needed - done */
+ champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
+ goto cleanup;
+ }
+
+load_next:
+ if (CHAMPLAIN_IS_MAP_SOURCE(next_source))
+ {
+ champlain_map_source_fill_tile(next_source, tile);
+ }
+ champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
+
+cleanup:
+ sqlite3_reset (priv->stmt_select);
+ g_free(filename);
+}
+
+static void
+refresh_tile_time (ChamplainTileCache *tile_cache, ChamplainTile *tile)
+{
+ g_return_if_fail (CHAMPLAIN_IS_FILE_CACHE (tile_cache));
+
+ ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE(tile_cache);
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
+ ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE(tile_cache);
+ gchar *filename = NULL;
+ GFile *file;
+ GFileInfo *info;
+
+ filename = get_filename (file_cache, tile);
+ file = g_file_new_for_path (filename);
+ g_free (filename);
+
+ info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NONE, NULL, NULL);
+
+ if (info)
+ {
+ GTimeVal now = {0, };
+
+ g_get_current_time (&now);
+
+ g_file_info_set_modification_time (info, &now);
+ g_file_set_attributes_from_info (file, info, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+ }
+
+ g_object_unref (file);
+ g_object_unref (info);
+
+ if (CHAMPLAIN_IS_TILE_CACHE(next_source))
+ {
+ refresh_tile_time(CHAMPLAIN_TILE_CACHE(next_source), tile);
+ }
+}
+
+static void
+store_tile (ChamplainTileCache *tile_cache,
+ ChamplainTile *tile,
+ const gchar *contents,
+ gsize size)
+{
+ g_return_if_fail (CHAMPLAIN_IS_FILE_CACHE (tile_cache));
+
+ ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE(tile_cache);
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
+ ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE(tile_cache);
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (file_cache);
+ gchar *query = NULL;
+ gchar *error = NULL;
+ gchar *path = NULL;
+ gchar *filename = NULL;
+ GError *gerror = NULL;
+ GFile *file;
+ GFileOutputStream *ostream;
+ gsize bytes_written;
+
+ DEBUG ("Update of %p", tile);
+
+ filename = get_filename (file_cache, tile);
+ file = g_file_new_for_path(filename);
+
+ /* If the file exists, delete it */
+ g_file_delete(file, NULL, NULL);
+
+ /* If needed, create the cache's dirs */
+ path = g_path_get_dirname (filename);
+ if (g_mkdir_with_parents (path, 0700) == -1)
+ {
+ if (errno != EEXIST)
+ {
+ g_warning ("Unable to create the image cache path '%s': %s",
+ path, g_strerror (errno));
+ goto store_next;
+ }
+ }
+
+ ostream = g_file_create(file, G_FILE_CREATE_PRIVATE, NULL, &gerror);
+ if (!ostream)
+ {
+ DEBUG ("GFileOutputStream creation failed: %s", gerror->message);
+ g_error_free (gerror);
+ goto store_next;
+ }
+
+ /* Write the cache */
+ if (!g_output_stream_write_all(G_OUTPUT_STREAM(ostream), contents, size, &bytes_written, NULL, &gerror))
+ {
+ DEBUG ("Writing file contents failed: %s", gerror->message);
+ g_error_free (gerror);
+ g_object_unref(ostream);
+ goto store_next;
+ }
+
+ g_object_unref(ostream);
+
+ query = sqlite3_mprintf ("REPLACE INTO tiles (filename, etag, size) VALUES (%Q, %Q, %d)",
+ filename,
+ champlain_tile_get_etag (tile),
+ size);
+ sqlite3_exec (priv->db, query, NULL, NULL, &error);
+ if (error != NULL)
+ {
+ DEBUG ("Saving Etag and size failed: %s", error);
+ sqlite3_free (error);
+ }
+ sqlite3_free (query);
+
+store_next:
+ if (CHAMPLAIN_IS_TILE_CACHE(next_source))
+ {
+ store_tile(CHAMPLAIN_TILE_CACHE(next_source), tile, contents, size);
+ }
+
+ g_free(filename);
+ g_free(path);
+ g_object_unref(file);
+}
+
+static void
+on_tile_filled (ChamplainTileCache *tile_cache, ChamplainTile *tile)
+{
+ g_return_if_fail(CHAMPLAIN_IS_FILE_CACHE (tile_cache));
+ g_return_if_fail(CHAMPLAIN_IS_TILE (tile));
+
+ ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE(tile_cache);
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
+ ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE(tile_cache);
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (file_cache);
+ int sql_rc = SQLITE_OK;
+ gchar *filename = NULL;
+
+ filename = get_filename (file_cache, tile);
+
+ DEBUG ("popularity of %s", filename);
+
+ sql_rc = sqlite3_bind_text (priv->stmt_update, 1, filename, -1, SQLITE_STATIC);
+ if (sql_rc != SQLITE_OK)
+ {
+ DEBUG ("Failed to set values to the popularity query of '%s', error: %s",
+ filename, sqlite3_errmsg (priv->db));
+ goto call_next;
+ }
+
+ sql_rc = sqlite3_step (priv->stmt_update);
+ if (sql_rc != SQLITE_DONE)
+ {
+ /* may not be present in this cache */
+ goto call_next;
+ }
+
+call_next:
+ if (CHAMPLAIN_IS_TILE_CACHE(next_source))
+ {
+ on_tile_filled(CHAMPLAIN_TILE_CACHE(next_source), tile);
+ }
+}
+
+static void
+clean (ChamplainTileCache *tile_cache)
+{
+ g_return_if_fail(CHAMPLAIN_IS_FILE_CACHE (tile_cache));
+
+ ChamplainFileCache *file_cache = CHAMPLAIN_FILE_CACHE(tile_cache);
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (file_cache);
+
+ g_return_if_fail(!champlain_tile_cache_get_persistent(tile_cache));
+
+ finalize_sql (file_cache);
+ delete_temp_cache(file_cache);
+
+ g_free(priv->real_cache_dir);
+ priv->real_cache_dir = NULL;
+
+ init_cache(file_cache);
+}
+
+static void
+delete_tile (ChamplainFileCache *file_cache, const gchar *filename)
+{
+ g_return_if_fail (CHAMPLAIN_IS_FILE_CACHE (file_cache));
+ gchar *query, *error = NULL;
+ GError *gerror = NULL;
+ GFile *file;
+
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (file_cache);
+
+ query = sqlite3_mprintf ("DELETE FROM tiles WHERE filename = %Q", filename);
+ sqlite3_exec (priv->db, query, NULL, NULL, &error);
+ if (error != NULL)
+ {
+ DEBUG ("Deleting tile from db failed: %s", error);
+ sqlite3_free (error);
+ }
+ sqlite3_free (query);
+
+ file = g_file_new_for_path (filename);
+ if (!g_file_delete (file, NULL, &gerror))
+ {
+ DEBUG ("Deleting tile from disk failed: %s", gerror->message);
+ g_error_free (gerror);
+ }
+ g_object_unref (file);
+}
+
+static gboolean
+purge_on_idle (gpointer data)
+{
+ champlain_file_cache_purge (CHAMPLAIN_FILE_CACHE (data));
+ return FALSE;
+}
+
+void
+champlain_file_cache_purge_on_idle (ChamplainFileCache *file_cache)
+{
+ g_return_if_fail (CHAMPLAIN_IS_FILE_CACHE (file_cache));
+ g_idle_add (purge_on_idle, file_cache);
+}
+
+void
+champlain_file_cache_purge (ChamplainFileCache *file_cache)
+{
+ g_return_if_fail (CHAMPLAIN_IS_FILE_CACHE (file_cache));
+
+ ChamplainFileCachePrivate *priv = GET_PRIVATE (file_cache);
+ gchar *query;
+ sqlite3_stmt *stmt;
+ int rc = 0;
+ guint current_size = 0;
+ guint highest_popularity = 0;
+ gchar *error;
+
+ query = "SELECT SUM (size) FROM tiles";
+ rc = sqlite3_prepare (priv->db, query, strlen (query), &stmt, NULL);
+ if (rc != SQLITE_OK)
+ {
+ DEBUG ("Can't compute cache size %s", sqlite3_errmsg (priv->db));
+ }
+
+ rc = sqlite3_step (stmt);
+ if (rc != SQLITE_ROW)
+ {
+ DEBUG ("Failed to count the total cache consumption %s",
+ sqlite3_errmsg (priv->db));
+ sqlite3_finalize (stmt);
+ return;
+ }
+
+ current_size = sqlite3_column_int (stmt, 0);
+ if (current_size < priv->size_limit)
+ {
+ DEBUG ("Cache doesn't need to be purged at %d bytes", current_size);
+ sqlite3_finalize (stmt);
+ return;
+ }
+
+ sqlite3_finalize (stmt);
+
+ /* Ok, delete the less popular tiles until size_limit reached */
+ query = "SELECT filename, size, popularity FROM tiles ORDER BY popularity";
+ rc = sqlite3_prepare (priv->db, query, strlen (query), &stmt, NULL);
+ if (rc != SQLITE_OK)
+ {
+ DEBUG ("Can't fetch tiles to delete: %s", sqlite3_errmsg(priv->db));
+ }
+
+ rc = sqlite3_step (stmt);
+ while (rc == SQLITE_ROW && current_size > priv->size_limit)
+ {
+ const char *filename = sqlite3_column_text (stmt, 0);
+ guint size;
+
+ filename = sqlite3_column_text (stmt, 0);
+ size = sqlite3_column_int (stmt, 1);
+ highest_popularity = sqlite3_column_int (stmt, 2);
+ DEBUG ("Deleting %s of size %d", filename, size);
+
+ delete_tile (file_cache, filename);
+
+ current_size -= size;
+
+ rc = sqlite3_step (stmt);
+ }
+ DEBUG ("Cache size is now %d", current_size);
+
+ sqlite3_finalize (stmt);
+
+ query = sqlite3_mprintf ("UPDATE tiles SET popularity = popularity - %d",
+ highest_popularity);
+ sqlite3_exec (priv->db, query, NULL, NULL, &error);
+ if (error != NULL)
+ {
+ DEBUG ("Updating popularity failed: %s", error);
+ sqlite3_free (error);
+ }
+ sqlite3_free (query);
+}
+
+static void
+delete_dir_recursive (GFile *parent)
+{
+ g_return_if_fail (parent);
+
+ GError *error = NULL;
+ GFileEnumerator *enumerator;
+ GFileInfo *info;
+ GFile *child;
+
+ enumerator = g_file_enumerate_children (parent, "*",
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL);
+
+ if (!enumerator)
+ {
+ DEBUG ("Failed to create file enumerator in delete_dir_recursive: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ info = g_file_enumerator_next_file (enumerator, NULL, NULL);
+ while (info && !error)
+ {
+ child = g_file_get_child (parent, g_file_info_get_name (info));
+
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+ delete_dir_recursive (child);
+
+ error = NULL;
+ if (!g_file_delete (child, NULL, &error))
+ {
+ DEBUG ("Deleting tile from disk failed: %s", error->message);
+ g_error_free (error);
+ }
+
+ g_object_unref (child);
+ g_object_unref (info);
+ info = g_file_enumerator_next_file (enumerator, NULL, NULL);
+ }
+
+ g_file_enumerator_close (enumerator, NULL, NULL);
+}
diff --git a/champlain/champlain-file-cache.h b/champlain/champlain-file-cache.h
new file mode 100644
index 0000000..a6a3d69
--- /dev/null
+++ b/champlain/champlain-file-cache.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2009 Pierre-Luc Beaudoin <pierre-luc pierlux com>
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if !defined (__CHAMPLAIN_CHAMPLAIN_H_INSIDE__) && !defined (CHAMPLAIN_COMPILATION)
+#error "Only <champlain/champlain.h> can be included directly."
+#endif
+
+#ifndef _CHAMPLAIN_FILE_CACHE_H_
+#define _CHAMPLAIN_FILE_CACHE_H_
+
+#include <glib-object.h>
+#include <champlain/champlain-tile-cache.h>
+
+G_BEGIN_DECLS
+
+#define CHAMPLAIN_TYPE_FILE_CACHE (champlain_file_cache_get_type ())
+#define CHAMPLAIN_FILE_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CHAMPLAIN_TYPE_FILE_CACHE, ChamplainFileCache))
+#define CHAMPLAIN_FILE_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CHAMPLAIN_TYPE_FILE_CACHE, ChamplainFileCacheClass))
+#define CHAMPLAIN_IS_FILE_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CHAMPLAIN_TYPE_FILE_CACHE))
+#define CHAMPLAIN_IS_FILE_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CHAMPLAIN_TYPE_FILE_CACHE))
+#define CHAMPLAIN_FILE_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CHAMPLAIN_TYPE_FILE_CACHE, ChamplainFileCacheClass))
+
+typedef struct _ChamplainFileCache ChamplainFileCache;
+typedef struct _ChamplainFileCacheClass ChamplainFileCacheClass;
+
+struct _ChamplainFileCache
+{
+ ChamplainTileCache parent_instance;
+};
+
+struct _ChamplainFileCacheClass
+{
+ ChamplainTileCacheClass parent_class;
+};
+
+GType champlain_file_cache_get_type (void);
+
+ChamplainFileCache* champlain_file_cache_new_full (guint size_limit,
+ const gchar *cache_dir, gboolean persistent);
+
+guint champlain_file_cache_get_size_limit (ChamplainFileCache *file_cache);
+void champlain_file_cache_set_size_limit (ChamplainFileCache *file_cache,
+ guint size_limit);
+
+const gchar * champlain_file_cache_get_cache_dir (ChamplainFileCache *file_cache);
+
+void champlain_file_cache_purge (ChamplainFileCache *file_cache);
+void champlain_file_cache_purge_on_idle (ChamplainFileCache *file_cache);
+
+G_END_DECLS
+
+#endif /* _CHAMPLAIN_FILE_CACHE_H_ */
diff --git a/champlain/champlain-map-data-source.c b/champlain/champlain-map-data-source.c
index 0b4fb7d..9e88335 100644
--- a/champlain/champlain-map-data-source.c
+++ b/champlain/champlain-map-data-source.c
@@ -32,7 +32,7 @@
#include "champlain-bounding-box.h"
#include "champlain-enum-types.h"
-G_DEFINE_TYPE (ChamplainMapDataSource, champlain_map_data_source, G_TYPE_OBJECT)
+G_DEFINE_TYPE (ChamplainMapDataSource, champlain_map_data_source, G_TYPE_INITIALLY_UNOWNED)
#define GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), CHAMPLAIN_TYPE_MAP_DATA_SOURCE, ChamplainMapDataSourcePrivate))
diff --git a/champlain/champlain-map-data-source.h b/champlain/champlain-map-data-source.h
index 12fd67b..6be4a5b 100644
--- a/champlain/champlain-map-data-source.h
+++ b/champlain/champlain-map-data-source.h
@@ -42,11 +42,11 @@ G_BEGIN_DECLS
(G_TYPE_INSTANCE_GET_CLASS ((obj), CHAMPLAIN_TYPE_MAP_DATA_SOURCE, ChamplainMapDataSourceClass))
typedef struct {
- GObject parent;
+ GInitiallyUnowned parent;
} ChamplainMapDataSource;
typedef struct {
- GObjectClass parent_class;
+ GInitiallyUnownedClass parent_class;
MemphisMap* (*get_map_data) (ChamplainMapDataSource *data_source);
} ChamplainMapDataSourceClass;
diff --git a/champlain/champlain-map-source-chain.c b/champlain/champlain-map-source-chain.c
new file mode 100644
index 0000000..e9df378
--- /dev/null
+++ b/champlain/champlain-map-source-chain.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "champlain-map-source-chain.h"
+#include "champlain-tile-cache.h"
+#include "champlain-tile-source.h"
+
+G_DEFINE_TYPE (ChamplainMapSourceChain, champlain_map_source_chain, CHAMPLAIN_TYPE_MAP_SOURCE);
+
+#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHAMPLAIN_TYPE_MAP_SOURCE_CHAIN, ChamplainMapSourceChainPrivate))
+
+typedef struct _ChamplainMapSourceChainPrivate ChamplainMapSourceChainPrivate;
+
+struct _ChamplainMapSourceChainPrivate
+{
+ ChamplainMapSource *stack_top;
+ gulong sig_handler_id;
+};
+
+static const gchar *get_id (ChamplainMapSource *map_source);
+static const gchar *get_name (ChamplainMapSource *map_source);
+static const gchar *get_license (ChamplainMapSource *map_source);
+static const gchar *get_license_uri (ChamplainMapSource *map_source);
+static guint get_min_zoom_level (ChamplainMapSource *map_source);
+static guint get_max_zoom_level (ChamplainMapSource *map_source);
+static guint get_tile_size (ChamplainMapSource *map_source);
+
+static void fill_tile (ChamplainMapSource *map_source, ChamplainTile *tile);
+
+static void
+champlain_map_source_chain_dispose (GObject *object)
+{
+ ChamplainMapSourceChain *source_chain = CHAMPLAIN_MAP_SOURCE_CHAIN(object);
+ ChamplainMapSourceChainPrivate *priv = GET_PRIVATE(object);
+
+ while (priv->stack_top)
+ champlain_map_source_chain_pop_map_source(source_chain);
+
+ G_OBJECT_CLASS (champlain_map_source_chain_parent_class)->dispose (object);
+}
+
+static void
+champlain_map_source_chain_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (champlain_map_source_chain_parent_class)->finalize (object);
+}
+
+static void
+champlain_map_source_chain_class_init (ChamplainMapSourceChainClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (ChamplainMapSourceChainPrivate));
+
+ object_class->finalize = champlain_map_source_chain_finalize;
+ object_class->dispose = champlain_map_source_chain_dispose;
+
+ ChamplainMapSourceClass *map_source_class = CHAMPLAIN_MAP_SOURCE_CLASS (klass);
+
+ map_source_class->get_id = get_id;
+ map_source_class->get_name = get_name;
+ map_source_class->get_license = get_license;
+ map_source_class->get_license_uri = get_license_uri;
+ map_source_class->get_min_zoom_level = get_min_zoom_level;
+ map_source_class->get_max_zoom_level = get_max_zoom_level;
+ map_source_class->get_tile_size = get_tile_size;
+
+ map_source_class->fill_tile = fill_tile;
+}
+
+static void
+champlain_map_source_chain_init (ChamplainMapSourceChain *source_chain)
+{
+ ChamplainMapSourceChainPrivate *priv = GET_PRIVATE(source_chain);
+ priv->stack_top = NULL;
+ priv->sig_handler_id = 0;
+}
+
+ChamplainMapSourceChain* champlain_map_source_chain_new (void)
+{
+ return g_object_new (CHAMPLAIN_TYPE_MAP_SOURCE_CHAIN, NULL);
+}
+
+static const gchar *
+get_id (ChamplainMapSource *map_source)
+{
+ ChamplainMapSourceChain *source_chain = CHAMPLAIN_MAP_SOURCE_CHAIN (map_source);
+ g_return_val_if_fail (source_chain, NULL);
+
+ ChamplainMapSourceChainPrivate *priv = GET_PRIVATE(source_chain);
+ g_return_val_if_fail (priv->stack_top, NULL);
+
+ return champlain_map_source_get_id(priv->stack_top);
+}
+
+static const gchar *
+get_name (ChamplainMapSource *map_source)
+{
+ ChamplainMapSourceChain *source_chain = CHAMPLAIN_MAP_SOURCE_CHAIN (map_source);
+ g_return_val_if_fail (source_chain, NULL);
+
+ ChamplainMapSourceChainPrivate *priv = GET_PRIVATE(source_chain);
+ g_return_val_if_fail (priv->stack_top, NULL);
+
+ return champlain_map_source_get_name(priv->stack_top);
+}
+
+static const gchar *
+get_license (ChamplainMapSource *map_source)
+{
+ ChamplainMapSourceChain *source_chain = CHAMPLAIN_MAP_SOURCE_CHAIN (map_source);
+ g_return_val_if_fail (source_chain, NULL);
+
+ ChamplainMapSourceChainPrivate *priv = GET_PRIVATE(source_chain);
+ g_return_val_if_fail (priv->stack_top, NULL);
+
+ return champlain_map_source_get_license(priv->stack_top);
+}
+
+static const gchar *
+get_license_uri (ChamplainMapSource *map_source)
+{
+ ChamplainMapSourceChain *source_chain = CHAMPLAIN_MAP_SOURCE_CHAIN (map_source);
+ g_return_val_if_fail (source_chain, NULL);
+
+ ChamplainMapSourceChainPrivate *priv = GET_PRIVATE(source_chain);
+ g_return_val_if_fail (priv->stack_top, NULL);
+
+ return champlain_map_source_get_license_uri(priv->stack_top);
+}
+
+static guint
+get_min_zoom_level (ChamplainMapSource *map_source)
+{
+ ChamplainMapSourceChain *source_chain = CHAMPLAIN_MAP_SOURCE_CHAIN (map_source);
+ g_return_val_if_fail (source_chain, 0);
+
+ ChamplainMapSourceChainPrivate *priv = GET_PRIVATE(source_chain);
+ g_return_val_if_fail (priv->stack_top, 0);
+
+ return champlain_map_source_get_min_zoom_level(priv->stack_top);
+}
+
+static guint
+get_max_zoom_level (ChamplainMapSource *map_source)
+{
+ ChamplainMapSourceChain *source_chain = CHAMPLAIN_MAP_SOURCE_CHAIN (map_source);
+ g_return_val_if_fail (source_chain, 0);
+
+ ChamplainMapSourceChainPrivate *priv = GET_PRIVATE(source_chain);
+ g_return_val_if_fail (priv->stack_top, 0);
+
+ return champlain_map_source_get_max_zoom_level(priv->stack_top);
+}
+
+static guint
+get_tile_size (ChamplainMapSource *map_source)
+{
+ ChamplainMapSourceChain *source_chain = CHAMPLAIN_MAP_SOURCE_CHAIN (map_source);
+ g_return_val_if_fail (source_chain, 0);
+
+ ChamplainMapSourceChainPrivate *priv = GET_PRIVATE(source_chain);
+ g_return_val_if_fail (priv->stack_top, 0);
+
+ return champlain_map_source_get_tile_size(priv->stack_top);
+}
+
+static void fill_tile (ChamplainMapSource *map_source,
+ ChamplainTile *tile)
+{
+ ChamplainMapSourceChain *source_chain = CHAMPLAIN_MAP_SOURCE_CHAIN (map_source);
+ g_return_if_fail (source_chain);
+
+ ChamplainMapSourceChainPrivate *priv = GET_PRIVATE(source_chain);
+ g_return_if_fail (priv->stack_top);
+
+ champlain_map_source_fill_tile(priv->stack_top, tile);
+}
+
+static void assign_cache_of_next_source_sequence(ChamplainMapSource *start_map_source, ChamplainTileCache *tile_cache)
+{
+ ChamplainMapSource *map_source = start_map_source;
+ ChamplainTileSource *tile_source;
+
+ do
+ {
+ map_source = champlain_map_source_get_next_source(map_source);
+ }
+ while (CHAMPLAIN_IS_TILE_CACHE(map_source));
+
+ tile_source = CHAMPLAIN_TILE_SOURCE(map_source);
+ while (tile_source)
+ {
+ champlain_tile_source_set_cache(tile_source, tile_cache);
+ map_source = champlain_map_source_get_next_source(map_source);
+ tile_source = CHAMPLAIN_TILE_SOURCE(map_source);
+ }
+}
+
+static
+void reload_tiles_cb(ChamplainMapSource *map_source, ChamplainMapSourceChain *source_chain)
+{
+ /* propagate the signal from the chain that is inside champlain_map_source_chain */
+ g_signal_emit_by_name (source_chain, "reload-tiles", NULL);
+}
+
+void champlain_map_source_chain_push_map_source(ChamplainMapSourceChain *source_chain, ChamplainMapSource *map_source)
+{
+ ChamplainMapSourceChainPrivate *priv = GET_PRIVATE(source_chain);
+ gboolean is_cache = FALSE;
+
+ if (CHAMPLAIN_IS_TILE_CACHE(map_source))
+ is_cache = TRUE;
+ else
+ g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE(map_source));
+
+ g_object_ref_sink(map_source);
+
+ if (!priv->stack_top)
+ {
+ /* tile source has to be last */
+ g_return_if_fail(!is_cache);
+ priv->stack_top = map_source;
+ }
+ else
+ {
+ if (g_signal_handler_is_connected (priv->stack_top, priv->sig_handler_id))
+ g_signal_handler_disconnect (priv->stack_top, priv->sig_handler_id);
+
+ champlain_map_source_set_next_source(map_source, priv->stack_top);
+ priv->stack_top = map_source;
+
+ if (is_cache)
+ {
+ ChamplainTileCache *tile_cache = CHAMPLAIN_TILE_CACHE(map_source);
+ assign_cache_of_next_source_sequence(priv->stack_top, tile_cache);
+ }
+ }
+
+ priv->sig_handler_id = g_signal_connect (priv->stack_top, "reload-tiles",
+ G_CALLBACK (reload_tiles_cb), source_chain);
+}
+
+void champlain_map_source_chain_pop_map_source(ChamplainMapSourceChain *source_chain)
+{
+ ChamplainMapSourceChainPrivate *priv = GET_PRIVATE(source_chain);
+ ChamplainMapSource *old_stack_top = priv->stack_top;
+
+ g_return_if_fail(priv->stack_top);
+
+ if (g_signal_handler_is_connected (priv->stack_top, priv->sig_handler_id))
+ g_signal_handler_disconnect (priv->stack_top, priv->sig_handler_id);
+
+ if (CHAMPLAIN_IS_TILE_CACHE(priv->stack_top))
+ {
+ ChamplainMapSource *map_source = champlain_map_source_get_next_source(priv->stack_top);
+ ChamplainTileCache *tile_cache = NULL;
+
+ if (CHAMPLAIN_IS_TILE_CACHE(map_source))
+ tile_cache = CHAMPLAIN_TILE_CACHE(map_source);
+
+ assign_cache_of_next_source_sequence(priv->stack_top, tile_cache);
+ }
+
+ priv->stack_top = champlain_map_source_get_next_source(priv->stack_top);
+ if (priv->stack_top)
+ {
+ priv->sig_handler_id = g_signal_connect (priv->stack_top, "reload-tiles",
+ G_CALLBACK (reload_tiles_cb), source_chain);
+ }
+
+ g_object_unref(old_stack_top);
+}
diff --git a/champlain/champlain-map-source-chain.h b/champlain/champlain-map-source-chain.h
new file mode 100644
index 0000000..e633070
--- /dev/null
+++ b/champlain/champlain-map-source-chain.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if !defined (__CHAMPLAIN_CHAMPLAIN_H_INSIDE__) && !defined (CHAMPLAIN_COMPILATION)
+#error "Only <champlain/champlain.h> can be included directly."
+#endif
+
+#ifndef _CHAMPLAIN_MAP_SOURCE_CHAIN_H_
+#define _CHAMPLAIN_MAP_SOURCE_CHAIN_H_
+
+#include <glib-object.h>
+
+#include "champlain-map-source.h"
+
+G_BEGIN_DECLS
+
+#define CHAMPLAIN_TYPE_MAP_SOURCE_CHAIN (champlain_map_source_chain_get_type ())
+#define CHAMPLAIN_MAP_SOURCE_CHAIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CHAMPLAIN_TYPE_MAP_SOURCE_CHAIN, ChamplainMapSourceChain))
+#define CHAMPLAIN_MAP_SOURCE_CHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CHAMPLAIN_TYPE_MAP_SOURCE_CHAIN, ChamplainMapSourceChainClass))
+#define CHAMPLAIN_IS_MAP_SOURCE_CHAIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CHAMPLAIN_TYPE_MAP_SOURCE_CHAIN))
+#define CHAMPLAIN_IS_MAP_SOURCE_CHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CHAMPLAIN_TYPE_MAP_SOURCE_CHAIN))
+#define CHAMPLAIN_MAP_SOURCE_CHAIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CHAMPLAIN_TYPE_MAP_SOURCE_CHAIN, ChamplainMapSourceChainClass))
+
+typedef struct _ChamplainMapSourceChain ChamplainMapSourceChain;
+typedef struct _ChamplainMapSourceChainClass ChamplainMapSourceChainClass;
+
+struct _ChamplainMapSourceChain
+{
+ ChamplainMapSource parent_instance;
+};
+
+struct _ChamplainMapSourceChainClass
+{
+ ChamplainMapSourceClass parent_class;
+};
+
+GType champlain_map_source_chain_get_type (void);
+
+ChamplainMapSourceChain* champlain_map_source_chain_new (void);
+
+void champlain_map_source_chain_push_map_source(ChamplainMapSourceChain *source_chain, ChamplainMapSource *map_source);
+void champlain_map_source_chain_pop_map_source(ChamplainMapSourceChain *source_chain);
+
+G_END_DECLS
+
+#endif /* _CHAMPLAIN_MAP_SOURCE_CHAIN_H_ */
diff --git a/champlain/champlain-map-source-desc.h b/champlain/champlain-map-source-desc.h
index 6b4d107..6c1fd61 100644
--- a/champlain/champlain-map-source-desc.h
+++ b/champlain/champlain-map-source-desc.h
@@ -24,7 +24,7 @@
#define CHAMPLAIN_MAP_SOURCE_DESC_H
#include <glib-object.h>
-#include "champlain-map-source.h"
+#include "champlain-tile-source.h"
G_BEGIN_DECLS
diff --git a/champlain/champlain-map-source-factory.c b/champlain/champlain-map-source-factory.c
index da8f828..90a7de3 100644
--- a/champlain/champlain-map-source-factory.c
+++ b/champlain/champlain-map-source-factory.c
@@ -39,13 +39,16 @@
#include "champlain-debug.h"
#include "champlain.h"
-#include "champlain-cache.h"
+#include "champlain-file-cache.h"
#include "champlain-defines.h"
#include "champlain-enum-types.h"
#include "champlain-map-source.h"
#include "champlain-marshal.h"
#include "champlain-private.h"
#include "champlain-zoom-level.h"
+#include "champlain-network-tile-source.h"
+#include "champlain-map-source-chain.h"
+#include "champlain-error-tile-source.h"
#include <glib.h>
#include <string.h>
@@ -354,7 +357,12 @@ ChamplainMapSource *
champlain_map_source_factory_create (ChamplainMapSourceFactory *factory,
const gchar *id)
{
+// ChamplainMapSource *map_source = NULL;
+// ChamplainMapSourceChain *source_chain;
+// ChamplainMapSource *source;
GSList *item;
+// guint tile_size;
+// gchar *cache_path;
item = factory->priv->registered_sources;
@@ -362,10 +370,28 @@ champlain_map_source_factory_create (ChamplainMapSourceFactory *factory,
{
ChamplainMapSourceDesc *desc = CHAMPLAIN_MAP_SOURCE_DESC (item->data);
if (strcmp (desc->id, id) == 0)
- return desc->constructor (desc, desc->data);
+ return desc->constructor (desc, desc->data); //map_source = desc->constructor (desc, desc->data);
item = g_slist_next (item);
}
- return NULL;
+
+// if (!map_source)
+ return NULL;
+
+/* source_chain = champlain_map_source_chain_new ();
+
+ tile_size = champlain_map_source_get_tile_size(map_source);
+ source = CHAMPLAIN_MAP_SOURCE(champlain_error_tile_source_new_full (tile_size));
+
+ champlain_map_source_chain_push_map_source(source_chain, source);
+ champlain_map_source_chain_push_map_source(source_chain, map_source);
+
+ cache_path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_cache_dir (), "champlain", NULL);
+ source = CHAMPLAIN_MAP_SOURCE(champlain_file_cache_new_full (100000000, cache_path, TRUE));
+ g_free(cache_path);
+
+ champlain_map_source_chain_push_map_source(source_chain, source);
+
+ return CHAMPLAIN_MAP_SOURCE(source_chain);*/
}
/**
@@ -402,7 +428,7 @@ static ChamplainMapSource *
champlain_map_source_new_generic (
ChamplainMapSourceDesc *desc, gpointer user_data)
{
- return CHAMPLAIN_MAP_SOURCE (champlain_network_map_source_new_full (
+ return CHAMPLAIN_MAP_SOURCE (champlain_network_tile_source_new_full (
desc->id,
desc->name,
desc->license,
@@ -431,12 +457,18 @@ champlain_map_source_new_memphis (ChamplainMapSourceDesc *desc,
desc->uri_format);
}
else if (g_strcmp0 (desc->id, CHAMPLAIN_MAP_SOURCE_MEMPHIS_NETWORK) == 0)
- {
map_data_source = CHAMPLAIN_MAP_DATA_SOURCE (champlain_network_map_data_source_new ());
- }
else
return NULL;
return CHAMPLAIN_MAP_SOURCE (champlain_memphis_map_source_new_full (
- desc, map_data_source));
+ desc->id,
+ desc->name,
+ desc->license,
+ desc->license_uri,
+ desc->min_zoom_level,
+ desc->max_zoom_level,
+ 256,
+ desc->projection,
+ map_data_source));
}
diff --git a/champlain/champlain-map-source.c b/champlain/champlain-map-source.c
index a42c33b..42e5689 100644
--- a/champlain/champlain-map-source.c
+++ b/champlain/champlain-map-source.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Pierre-Luc Beaudoin <pierre-luc pierlux com>
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,40 +16,13 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-/**
- * SECTION:champlain-map-source
- * @short_description: A base class for map sources
- *
- * #ChamplainTiles come from map sources which are represented by
- * #ChamplainMapSource. This is should be considered an abstract
- * type as it does nothing of interest.
- *
- * When loading new tiles, #ChamplainView calls #champlain_map_source_get_tile
- * on the current #ChamplainMapSource passing it a #ChamplainTile to be filled
- * with the image. #ChamplainMapSources should check with #ChamplainCache
- * if the image is already locally available with #champlain_cache_fill_tile.
- */
-
-#include "config.h"
-
-#define DEBUG_FLAG CHAMPLAIN_DEBUG_LOADING
-#include "champlain-debug.h"
-
-#include "champlain.h"
-#include "champlain-defines.h"
-#include "champlain-enum-types.h"
#include "champlain-map-source.h"
-#include "champlain-marshal.h"
-#include "champlain-private.h"
-#include "champlain-zoom-level.h"
-#include <glib.h>
-#include <glib-object.h>
#include <math.h>
-#include <string.h>
-void champlain_map_source_real_fill_tile (ChamplainMapSource *map_source,
- ChamplainTile *tile);
+G_DEFINE_TYPE (ChamplainMapSource, champlain_map_source, G_TYPE_INITIALLY_UNOWNED);
+
+#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHAMPLAIN_TYPE_MAP_SOURCE, ChamplainMapSourcePrivate))
enum
{
@@ -61,267 +34,117 @@ enum
enum
{
PROP_0,
- PROP_ID,
- PROP_NAME,
- PROP_LICENSE,
- PROP_LICENSE_URI,
- PROP_MAX_ZOOM_LEVEL,
- PROP_MIN_ZOOM_LEVEL,
- PROP_TILE_SIZE,
- PROP_MAP_PROJECTION,
+ PROP_NEXT_SOURCE,
};
static guint champlain_map_source_signals[LAST_SIGNAL] = { 0, };
-G_DEFINE_TYPE (ChamplainMapSource, champlain_map_source, G_TYPE_INITIALLY_UNOWNED);
-
-#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHAMPLAIN_TYPE_MAP_SOURCE, ChamplainMapSourcePrivate))
+typedef struct _ChamplainMapSourcePrivate ChamplainMapSourcePrivate;
struct _ChamplainMapSourcePrivate
{
- gchar *id;
- gchar *name;
- gchar *license;
- gchar *license_uri;
- guint max_zoom_level;
- guint min_zoom_level;
- guint tile_size;
- ChamplainMapProjection map_projection;
+ ChamplainMapSource *next_source;
+
+ gulong sig_handler_id;
};
-static void
-real_fill_tile (ChamplainMapSource *map_source,
- ChamplainTile *tile)
-{
- g_error ("Should not be reached");
-}
+static void reload_tiles_cb(ChamplainMapSource *orig, ChamplainMapSource *self);
static void
champlain_map_source_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE(object);
- ChamplainMapSourcePrivate *priv = map_source->priv;
+ ChamplainMapSourcePrivate *priv = GET_PRIVATE(object);
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_MAX_ZOOM_LEVEL:
- g_value_set_uint (value, priv->max_zoom_level);
- break;
- case PROP_MIN_ZOOM_LEVEL:
- g_value_set_uint (value, priv->min_zoom_level);
- break;
- case PROP_TILE_SIZE:
- g_value_set_uint (value, priv->tile_size);
- break;
- case PROP_MAP_PROJECTION:
- g_value_set_enum (value, priv->map_projection);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ case PROP_NEXT_SOURCE:
+ g_value_set_object (value, priv->next_source);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
}
static void
champlain_map_source_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE(object);
- ChamplainMapSourcePrivate *priv = map_source->priv;
switch(prop_id)
{
- case PROP_ID:
- champlain_map_source_set_id (map_source,
- g_value_get_string (value));
- case PROP_NAME:
- champlain_map_source_set_name (map_source,
- g_value_get_string (value));
- break;
- case PROP_LICENSE:
- priv->license = g_value_dup_string (value);
- break;
- case PROP_LICENSE_URI:
- priv->license_uri = g_value_dup_string (value);
- break;
- case PROP_MAX_ZOOM_LEVEL:
- priv->max_zoom_level = g_value_get_uint (value);
- break;
- case PROP_MIN_ZOOM_LEVEL:
- priv->min_zoom_level = g_value_get_uint (value);
- break;
- case PROP_TILE_SIZE:
- priv->tile_size = g_value_get_uint (value);
- break;
- case PROP_MAP_PROJECTION:
- priv->map_projection = g_value_get_enum (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ case PROP_NEXT_SOURCE:
+ champlain_map_source_set_next_source (map_source,
+ g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
}
static void
-champlain_map_source_finalize (GObject *object)
+champlain_map_source_dispose (GObject *object)
{
- ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE (object);
- ChamplainMapSourcePrivate *priv = map_source->priv;
+ ChamplainMapSourcePrivate *priv = GET_PRIVATE(object);
- g_free (priv->id);
- g_free (priv->name);
- g_free (priv->license);
- g_free (priv->license_uri);
+ if (priv->next_source)
+ {
+ g_object_unref (priv->next_source);
+
+ priv->next_source = NULL;
+ }
+
+ G_OBJECT_CLASS (champlain_map_source_parent_class)->dispose (object);
+}
+
+static void
+champlain_map_source_finalize (GObject *object)
+{
G_OBJECT_CLASS (champlain_map_source_parent_class)->finalize (object);
}
static void
+champlain_map_source_constructed (GObject *object)
+{
+ if (G_OBJECT_CLASS (champlain_map_source_parent_class)->constructed)
+ G_OBJECT_CLASS (champlain_map_source_parent_class)->constructed (object);
+}
+
+static void
champlain_map_source_class_init (ChamplainMapSourceClass *klass)
{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (klass, sizeof (ChamplainMapSourcePrivate));
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = champlain_map_source_finalize;
+ object_class->dispose = champlain_map_source_dispose;
object_class->get_property = champlain_map_source_get_property;
object_class->set_property = champlain_map_source_set_property;
+ object_class->constructed = champlain_map_source_constructed;
- klass->fill_tile = real_fill_tile;
-
- /**
- * ChamplainMapSource:id:
- *
- * The name of the map source
- *
- * Since: 0.4
- */
- pspec = g_param_spec_string ("id",
- "Id",
- "The id of the map source",
- "",
- (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- g_object_class_install_property (object_class, PROP_ID, pspec);
-
- /**
- * ChamplainMapSource:name:
- *
- * The name of the map source
- *
- * Since: 0.4
- */
- pspec = g_param_spec_string ("name",
- "Name",
- "The name of the map source",
- "",
- (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- g_object_class_install_property (object_class, PROP_NAME, pspec);
+ klass->get_id = NULL;
+ klass->get_name = NULL;
+ klass->get_license = NULL;
+ klass->get_license_uri = NULL;
+ klass->get_min_zoom_level = NULL;
+ klass->get_max_zoom_level = NULL;
+ klass->get_tile_size = NULL;
- /**
- * ChamplainMapSource:license:
- *
- * The usage license of the map source
- *
- * Since: 0.4
- */
- pspec = g_param_spec_string ("license",
- "License",
- "The usage license of the map source",
- "",
- (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- g_object_class_install_property (object_class, PROP_LICENSE, pspec);
+ klass->fill_tile = NULL;
- /**
- * ChamplainMapSource:license-uri:
- *
- * The usage license's uri for more information
- *
- * Since: 0.4
- */
- pspec = g_param_spec_string ("license-uri",
- "License-uri",
- "The usage license's uri for more information",
- "",
- (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- g_object_class_install_property (object_class, PROP_LICENSE_URI, pspec);
-
- /**
- * ChamplainMapSource:max-zoom-level:
- *
- * The maximum zoom level
- *
- * Since: 0.4
- */
- pspec = g_param_spec_uint ("max-zoom-level",
- "Maximum Zoom Level",
- "The maximum zoom level",
- 0,
- 50,
- 18,
- (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- g_object_class_install_property (object_class, PROP_MAX_ZOOM_LEVEL, pspec);
-
- /**
- * ChamplainMapSource:min-zoom-level:
- *
- * The minimum zoom level
- *
- * Since: 0.4
- */
- pspec = g_param_spec_uint ("min-zoom-level",
- "Minimum Zoom Level",
- "The minimum zoom level",
- 0,
- 50,
- 0,
- (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- g_object_class_install_property (object_class, PROP_MIN_ZOOM_LEVEL, pspec);
-
- /**
- * ChamplainMapSource:tile-size:
- *
- * The tile size of the map source
- *
- * Since: 0.4
- */
- pspec = g_param_spec_uint ("tile-size",
- "Tile Size",
- "The tile size",
- 0,
- 2048,
- 256,
- (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- g_object_class_install_property (object_class, PROP_TILE_SIZE, pspec);
-
- /**
- * ChamplainMapSource:projection
- *
- * The map projection of the map source
- *
- * Since: 0.4
- */
- pspec = g_param_spec_enum ("projection",
- "Projection",
- "The map projection",
- CHAMPLAIN_TYPE_MAP_PROJECTION,
- CHAMPLAIN_MAP_PROJECTION_MERCATOR,
- (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- g_object_class_install_property (object_class, PROP_MAP_PROJECTION, pspec);
+ pspec = g_param_spec_object ("next-source",
+ "Next Source",
+ "Next source in the loading chain",
+ CHAMPLAIN_TYPE_MAP_SOURCE,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_NEXT_SOURCE, pspec);
/**
* ChamplainMapSource::reload-tiles:
@@ -333,439 +156,203 @@ champlain_map_source_class_init (ChamplainMapSourceClass *klass)
* Since: 0.6
*/
champlain_map_source_signals[RELOAD_TILES] =
- g_signal_new ("reload-tiles", G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST, 0, NULL, NULL,
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
- 0, NULL);
+ g_signal_new ("reload-tiles", G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
+ 0, NULL);
}
static void
-champlain_map_source_init (ChamplainMapSource *champlainMapSource)
+champlain_map_source_init (ChamplainMapSource *map_source)
{
- ChamplainMapSourcePrivate *priv = GET_PRIVATE (champlainMapSource);
- champlainMapSource->priv = priv;
+ ChamplainMapSourcePrivate *priv = GET_PRIVATE(map_source);
+ priv->next_source = NULL;
+ priv->sig_handler_id = 0;
}
-/**
- * champlain_map_source_get_max_zoom_level:
- * @map_source: a #ChamplainMapSource
- *
- * Returns: the maximum zoom level this map source supports
- *
- * Since: 0.4
- */
-gint
-champlain_map_source_get_max_zoom_level (ChamplainMapSource *map_source)
+ChamplainMapSource *
+champlain_map_source_get_next_source (ChamplainMapSource *map_source)
{
- g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), NULL);
- ChamplainMapSourcePrivate *priv = map_source->priv;
- return priv->max_zoom_level;
+ ChamplainMapSourcePrivate *priv = GET_PRIVATE(map_source);
+ return priv->next_source;
}
-/**
- * champlain_map_source_get_min_zoom_level:
- * @map_source: a #ChamplainMapSource
- *
- * Returns: the miminum zoom level this map source supports
- *
- * Since: 0.4
- */
-gint
-champlain_map_source_get_min_zoom_level (ChamplainMapSource *map_source)
+static
+void reload_tiles_cb(ChamplainMapSource *orig, ChamplainMapSource *self)
{
- g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
-
- ChamplainMapSourcePrivate *priv = map_source->priv;
- return priv->min_zoom_level;
+ /* propagate the signal up the chain */
+ g_signal_emit_by_name (self, "reload-tiles", NULL);
}
-/**
- * champlain_map_source_get_tile_size:
- * @map_source: a #ChamplainMapSource
- *
- * Returns: the tile's size (width and height) in pixels for this map source
- *
- * Since: 0.4
- */
-guint
-champlain_map_source_get_tile_size (ChamplainMapSource *map_source)
+void
+champlain_map_source_set_next_source (ChamplainMapSource *map_source,
+ ChamplainMapSource *next_source)
{
- g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
+ g_return_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source));
- ChamplainMapSourcePrivate *priv = map_source->priv;
- return priv->tile_size;
-}
+ ChamplainMapSourcePrivate *priv = GET_PRIVATE(map_source);
-/**
- * champlain_map_source_get_x:
- * @map_source: a #ChamplainMapSource
- * @zoom_level: the zoom level
- * @longitude: a longitude
- *
- * Returns: the x position on the map using this map source's projection.
- * (0, 0) is located at the top left.
- *
- * Since: 0.4
- */
-guint
-champlain_map_source_get_x (ChamplainMapSource *map_source,
- gint zoom_level,
- gdouble longitude)
-{
- g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
+ if (priv->next_source != NULL)
+ {
+ if (g_signal_handler_is_connected (priv->next_source, priv->sig_handler_id))
+ g_signal_handler_disconnect (priv->next_source, priv->sig_handler_id);
- ChamplainMapSourcePrivate *priv = map_source->priv;
- // FIXME: support other projections
- return ((longitude + 180.0) / 360.0 * pow(2.0, zoom_level)) * priv->tile_size;
-}
+ g_object_unref(priv->next_source);
+ }
-/**
- * champlain_map_source_get_y:
- * @map_source: a #ChamplainMapSource
- * @zoom_level: the zoom level
- * @latitude: a latitude
- *
- * Returns: the y position on the map using this map source's projection.
- * (0, 0) is located at the top left.
- *
- * Since: 0.4
- */
-guint
-champlain_map_source_get_y (ChamplainMapSource *map_source,
- gint zoom_level,
- gdouble latitude)
-{
- g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
+ if (next_source)
+ {
+ g_return_if_fail (CHAMPLAIN_IS_MAP_SOURCE (next_source));
- ChamplainMapSourcePrivate *priv = map_source->priv;
- // FIXME: support other projections
- return ((1.0 - log (tan (latitude * M_PI / 180.0) + 1.0 /
- cos (latitude * M_PI / 180.0)) /
- M_PI) / 2.0 * pow (2.0, zoom_level)) * priv->tile_size;
-}
+ g_object_ref_sink(next_source);
-/**
- * champlain_map_source_get_row_count:
- * @map_source: a #ChamplainMapSource
- * @zoom_level: the zoom level
- *
- * Returns: the number of tiles in a row at this zoom level for this map source.
- *
- * Since: 0.4
- */
-guint
-champlain_map_source_get_row_count (ChamplainMapSource *map_source,
- gint zoom_level)
-{
- g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
+ priv->sig_handler_id = g_signal_connect (next_source, "reload-tiles",
+ G_CALLBACK (reload_tiles_cb), map_source);
+ }
- //ChamplainMapSourcePrivate *priv = map_source->priv;
- // FIXME: support other projections
- return pow (2, zoom_level);
+ priv->next_source = next_source;
+
+ g_object_notify (G_OBJECT (map_source), "next-source");
}
-/**
- * champlain_map_source_get_column_count:
- * @map_source: a #ChamplainMapSource
- * @zoom_level: the zoom level
- *
- * Returns: the number of tiles in a column at this zoom level for this map
- * source.
- *
- * Since: 0.4
- */
-guint
-champlain_map_source_get_column_count (ChamplainMapSource *map_source,
- gint zoom_level)
+const gchar *
+champlain_map_source_get_id (ChamplainMapSource *map_source)
{
- g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), NULL);
- //ChamplainMapSourcePrivate *priv = map_source->priv;
- // FIXME: support other projections
- return pow (2, zoom_level);
+ return CHAMPLAIN_MAP_SOURCE_GET_CLASS (map_source)->get_id (map_source);
}
-/**
- * champlain_map_source_fill_tile:
- * @map_source: a #ChamplainMapSource
- * @tile: A #ChamplainTile
- *
- * Fills the tile with image data (either from cache, network or rendered
- * locally).
- *
- * Since: 0.4
- */
-void
-champlain_map_source_fill_tile (ChamplainMapSource *map_source,
- ChamplainTile *tile)
+const gchar *
+champlain_map_source_get_name (ChamplainMapSource *map_source)
{
- g_return_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source));
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), NULL);
- CHAMPLAIN_MAP_SOURCE_GET_CLASS (map_source)->fill_tile (map_source, tile);
+ return CHAMPLAIN_MAP_SOURCE_GET_CLASS (map_source)->get_name (map_source);
}
-/**
- * champlain_map_source_get_longitude:
- * @map_source: a #ChamplainMapSource
- * @zoom_level: the zoom level
- * @x: a x position
- *
- * Returns: the longitude corresponding to this x position in the map source's
- * projection.
- *
- * Since: 0.4
- */
-gdouble
-champlain_map_source_get_longitude (ChamplainMapSource *map_source,
- gint zoom_level,
- guint x)
+const gchar *
+champlain_map_source_get_license (ChamplainMapSource *map_source)
{
- g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
- //ChamplainMapSourcePrivate *priv = map_source->priv;
- // FIXME: support other projections
- gdouble dx = (float)x / champlain_map_source_get_tile_size (map_source);
- return dx / pow (2.0, zoom_level) * 360.0 - 180;
-}
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), NULL);
-/**
- * champlain_map_source_get_latitude:
- * @map_source: a #ChamplainMapSource
- * @zoom_level: the zoom level
- * @y: a y position
- *
- * Returns: the latitude corresponding to this y position in the map source's
- * projection.
- *
- * Since: 0.4
- */
-gdouble
-champlain_map_source_get_latitude (ChamplainMapSource *map_source,
- gint zoom_level,
- guint y)
-{
- g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
- //ChamplainMapSourcePrivate *priv = map_source->priv;
- // FIXME: support other projections
- gdouble dy = (float)y / champlain_map_source_get_tile_size (map_source);
- double n = M_PI - 2.0 * M_PI * dy / pow (2.0, zoom_level);
- return 180.0 / M_PI * atan (0.5 * (exp (n) - exp (-n)));
+ return CHAMPLAIN_MAP_SOURCE_GET_CLASS (map_source)->get_license (map_source);
}
-/**
- * champlain_map_source_get_name:
- * @map_source: a #ChamplainMapSource
- *
- * Returns: the map source's name.
- *
- * Since: 0.4
- */
const gchar *
-champlain_map_source_get_name (ChamplainMapSource *map_source)
+champlain_map_source_get_license_uri (ChamplainMapSource *map_source)
{
- g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), NULL);
- ChamplainMapSourcePrivate *priv = map_source->priv;
- return priv->name;
+ return CHAMPLAIN_MAP_SOURCE_GET_CLASS (map_source)->get_license_uri (map_source);
}
-/**
- * champlain_map_source_set_name:
- * @map_source: a #ChamplainMapSource
- * @name: a name
- *
- * Sets the map source's name.
- *
- * Since: 0.4
- */
-void
-champlain_map_source_set_name (ChamplainMapSource *map_source,
- const gchar *name)
+guint
+champlain_map_source_get_min_zoom_level (ChamplainMapSource *map_source)
{
- g_return_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source));
-
- ChamplainMapSourcePrivate *priv = map_source->priv;
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
- g_free (priv->name);
- priv->name = g_strdup (name);
- g_object_notify (G_OBJECT (map_source), "name");
+ return CHAMPLAIN_MAP_SOURCE_GET_CLASS (map_source)->get_min_zoom_level (map_source);
}
-/**
- * champlain_map_source_get_license:
- * @map_source: a #ChamplainMapSource
- *
- * Returns: the map source's license.
- *
- * Since: 0.4
- */
-const gchar *
-champlain_map_source_get_license (ChamplainMapSource *map_source)
+guint
+champlain_map_source_get_max_zoom_level (ChamplainMapSource *map_source)
{
g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
- ChamplainMapSourcePrivate *priv = map_source->priv;
- return priv->license;
+ return CHAMPLAIN_MAP_SOURCE_GET_CLASS (map_source)->get_max_zoom_level (map_source);
}
-/**
- * champlain_map_source_set_license:
- * @map_source: a #ChamplainMapSource
- * @license: the licence
- *
- * Sets the map source's license.
- *
- * Since: 0.4
- */
-void
-champlain_map_source_set_license (ChamplainMapSource *map_source,
- const gchar *license)
+guint
+champlain_map_source_get_tile_size (ChamplainMapSource *map_source)
{
- g_return_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source));
-
- ChamplainMapSourcePrivate *priv = map_source->priv;
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
- g_free (priv->license);
- priv->license = g_strdup (license);
- g_object_notify (G_OBJECT (map_source), "license");
+ return CHAMPLAIN_MAP_SOURCE_GET_CLASS (map_source)->get_tile_size (map_source);
}
-/**
- * champlain_map_source_get_license_uri:
- * @map_source: a #ChamplainMapSource
- *
- * Returns: the map source's license URI.
- *
- * Since: 0.4
- */
-const gchar *
-champlain_map_source_get_license_uri (ChamplainMapSource *map_source)
+guint
+champlain_map_source_get_x (ChamplainMapSource *map_source,
+ guint zoom_level,
+ gdouble longitude)
{
g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
- ChamplainMapSourcePrivate *priv = map_source->priv;
-
- return priv->license_uri;
+ // FIXME: support other projections
+ return ((longitude + 180.0) / 360.0 * pow(2.0, zoom_level)) * champlain_map_source_get_tile_size (map_source);
}
-/**
- * champlain_map_source_set_license_uri:
- * @map_source: a #ChamplainMapSource
- * @license_uri: the licence URI
- *
- * Sets the map source's license URI.
- *
- * Since: 0.4
- */
-void
-champlain_map_source_set_license_uri (ChamplainMapSource *map_source,
- const gchar *license_uri)
+guint
+champlain_map_source_get_y (ChamplainMapSource *map_source,
+ guint zoom_level,
+ gdouble latitude)
{
- g_return_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source));
-
- ChamplainMapSourcePrivate *priv = map_source->priv;
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
- g_free (priv->license_uri);
- priv->license = g_strdup (license_uri);
- g_object_notify (G_OBJECT (map_source), "license-uri");
+ // FIXME: support other projections
+ return ((1.0 - log (tan (latitude * M_PI / 180.0) + 1.0 /
+ cos (latitude * M_PI / 180.0)) /
+ M_PI) / 2.0 * pow (2.0, zoom_level)) * champlain_map_source_get_tile_size (map_source);
}
-/**
- * champlain_map_source_get_projection:
- * @map_source: a #ChamplainMapSource
- *
- * Returns: the map source's projection.
- *
- * Since: 0.4
- */
-ChamplainMapProjection
-champlain_map_source_get_projection (ChamplainMapSource *map_source)
+gdouble
+champlain_map_source_get_longitude (ChamplainMapSource *map_source,
+ guint zoom_level,
+ guint x)
{
- ChamplainMapSourcePrivate *priv = map_source->priv;
-
- return priv->map_projection;
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
+ //ChamplainMapSourcePrivate *priv = map_source->priv;
+ // FIXME: support other projections
+ gdouble dx = (float)x / champlain_map_source_get_tile_size (map_source);
+ return dx / pow (2.0, zoom_level) * 360.0 - 180;
}
-/**
- * champlain_map_source_set_projection:
- * @map_source: a #ChamplainMapSource
- * @projection: a #ChamplainMapProjection
- *
- * Sets the map source's projection.
- *
- * Since: 0.4
- */
-void
-champlain_map_source_set_projection (ChamplainMapSource *map_source,
- ChamplainMapProjection projection)
+gdouble
+champlain_map_source_get_latitude (ChamplainMapSource *map_source,
+ guint zoom_level,
+ guint y)
{
- g_return_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source));
-
- ChamplainMapSourcePrivate *priv = map_source->priv;
-
- priv->map_projection = projection;
- g_object_notify (G_OBJECT (map_source), "projection");
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
+ //ChamplainMapSourcePrivate *priv = map_source->priv;
+ // FIXME: support other projections
+ gdouble dy = (float)y / champlain_map_source_get_tile_size (map_source);
+ gdouble n = M_PI - 2.0 * M_PI * dy / pow (2.0, zoom_level);
+ return 180.0 / M_PI * atan (0.5 * (exp (n) - exp (-n)));
}
-/**
- * champlain_map_source_get_id:
- * @map_source: a #ChamplainMapSource
- *
- * Returns: the map source's id.
- *
- * Since: 0.4
- */
-const gchar *
-champlain_map_source_get_id (ChamplainMapSource *map_source)
+guint
+champlain_map_source_get_row_count (ChamplainMapSource *map_source,
+ guint zoom_level)
{
g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
- ChamplainMapSourcePrivate *priv = map_source->priv;
- return priv->id;
+ //ChamplainMapSourcePrivate *priv = map_source->priv;
+ // FIXME: support other projections
+ return pow (2, zoom_level);
}
-/**
- * champlain_map_source_set_id:
- * @map_source: a #ChamplainMapSource
- * @id: a id
- *
- * Sets the map source's id.
- *
- * Since: 0.4
- */
-void
-champlain_map_source_set_id (ChamplainMapSource *map_source,
- const gchar *id)
+guint
+champlain_map_source_get_column_count (ChamplainMapSource *map_source,
+ guint zoom_level)
{
- g_return_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source));
-
- ChamplainMapSourcePrivate *priv = map_source->priv;
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
- g_free (priv->id);
- priv->id = g_strdup (id);
- g_object_notify (G_OBJECT (map_source), "id");
+ //ChamplainMapSourcePrivate *priv = map_source->priv;
+ // FIXME: support other projections
+ return pow (2, zoom_level);
}
-#define EARTH_RADIUS 6378137 /* meters, Equatorial radius */
+#define EARTH_RADIUS 6378137.0 /* meters, Equatorial radius */
-/**
- * champlain_map_source_get_meters_per_pixel:
- * @map_source: a #ChamplainMapSource
- * @zoom_level: the zoom level
- * @latitude: a latitude
- * @longitude: a longitude
- *
- * Returns: the meters per pixel at the position on the map using this map source's projection.
- *
- * Since: 0.4.3
- */
-gfloat
+gdouble
champlain_map_source_get_meters_per_pixel (ChamplainMapSource *map_source,
- gint zoom_level,
+ guint zoom_level,
gdouble latitude,
gdouble longitude)
{
- g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0);
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source), 0.0);
/* Width is in pixels. (1 px)
m/px = radius_at_latitude / width_in_pixels
@@ -773,61 +360,17 @@ champlain_map_source_get_meters_per_pixel (ChamplainMapSource *map_source,
radius_at_latitude = 2Ï? * k * sin (Ï?/2-θ)
*/
- ChamplainMapSourcePrivate *priv = map_source->priv;
+ gdouble tile_size = champlain_map_source_get_tile_size (map_source);
// FIXME: support other projections
- return 2 * M_PI * EARTH_RADIUS * sin (M_PI/2 - M_PI / 180 * latitude) /
- (priv->tile_size * champlain_map_source_get_row_count (map_source, zoom_level));
+ return 2.0 * M_PI * EARTH_RADIUS * sin (M_PI/2.0 - M_PI / 180.0 * latitude) /
+ (tile_size * champlain_map_source_get_row_count (map_source, zoom_level));
}
-/* protected function */
-static ClutterActor *error_actor = NULL;
-
void
-create_error_tile (ChamplainTile* tile)
+champlain_map_source_fill_tile (ChamplainMapSource *map_source,
+ ChamplainTile *tile)
{
- ClutterActor *clone;
-
- if (!error_actor)
- {
- guint size;
- ClutterActor *actor;
- cairo_t *cr;
- cairo_pattern_t *pat;
- ClutterActor *stage;
-
- size = champlain_tile_get_size (tile);
- actor = clutter_cairo_texture_new (size, size);
- cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (actor));
- stage = clutter_stage_get_default ();
-
- /* draw a linear gray to white pattern */
- pat = cairo_pattern_create_linear (size / 2.0, 0.0, size, size / 2.0);
- cairo_pattern_add_color_stop_rgb (pat, 0, 0.686, 0.686, 0.686);
- cairo_pattern_add_color_stop_rgb (pat, 1, 0.925, 0.925, 0.925);
- cairo_set_source (cr, pat);
- cairo_rectangle (cr, 0, 0, size, size);
- cairo_fill (cr);
-
- cairo_pattern_destroy (pat);
-
- /* draw the red cross */
- cairo_set_source_rgb (cr, 0.424, 0.078, 0.078);
- cairo_set_line_width (cr, 14.0);
- cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
- cairo_move_to (cr, 24, 24);
- cairo_line_to (cr, 50, 50);
- cairo_move_to (cr, 50, 24);
- cairo_line_to (cr, 24, 50);
- cairo_stroke (cr);
-
- cairo_destroy (cr);
-
- clutter_actor_show (actor);
- clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor);
- error_actor = actor;
- }
+ g_return_if_fail (CHAMPLAIN_IS_MAP_SOURCE (map_source));
- clone = clutter_clone_new (error_actor);
- champlain_tile_set_content (tile, clone, TRUE);
- champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
+ CHAMPLAIN_MAP_SOURCE_GET_CLASS (map_source)->fill_tile (map_source, tile);
}
diff --git a/champlain/champlain-map-source.h b/champlain/champlain-map-source.h
index a543b5c..7436b33 100644
--- a/champlain/champlain-map-source.h
+++ b/champlain/champlain-map-source.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2009 Pierre-Luc Beaudoin <pierre-luc pierlux com>
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -20,105 +20,84 @@
#error "Only <champlain/champlain.h> can be included directly."
#endif
-#ifndef CHAMPLAIN_MAP_SOURCE_H
-#define CHAMPLAIN_MAP_SOURCE_H
+#ifndef _CHAMPLAIN_MAP_SOURCE_H_
+#define _CHAMPLAIN_MAP_SOURCE_H_
#include <champlain/champlain-defines.h>
#include <champlain/champlain-tile.h>
#include <champlain/champlain-zoom-level.h>
-#include <glib-object.h>
-
G_BEGIN_DECLS
-#define CHAMPLAIN_TYPE_MAP_SOURCE (champlain_map_source_get_type())
-#define CHAMPLAIN_MAP_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), CHAMPLAIN_TYPE_MAP_SOURCE, ChamplainMapSource))
-#define CHAMPLAIN_MAP_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CHAMPLAIN_TYPE_MAP_SOURCE, ChamplainMapSourceClass))
-#define CHAMPLAIN_IS_MAP_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), CHAMPLAIN_TYPE_MAP_SOURCE))
-#define CHAMPLAIN_IS_MAP_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), CHAMPLAIN_TYPE_MAP_SOURCE))
-#define CHAMPLAIN_MAP_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), CHAMPLAIN_TYPE_MAP_SOURCE, ChamplainMapSourceClass))
+#define CHAMPLAIN_TYPE_MAP_SOURCE (champlain_map_source_get_type ())
+#define CHAMPLAIN_MAP_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CHAMPLAIN_TYPE_MAP_SOURCE, ChamplainMapSource))
+#define CHAMPLAIN_MAP_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CHAMPLAIN_TYPE_MAP_SOURCE, ChamplainMapSourceClass))
+#define CHAMPLAIN_IS_MAP_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CHAMPLAIN_TYPE_MAP_SOURCE))
+#define CHAMPLAIN_IS_MAP_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CHAMPLAIN_TYPE_MAP_SOURCE))
+#define CHAMPLAIN_MAP_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CHAMPLAIN_TYPE_MAP_SOURCE, ChamplainMapSourceClass))
-typedef struct _ChamplainMapSource ChamplainMapSource;
typedef struct _ChamplainMapSourceClass ChamplainMapSourceClass;
-typedef struct _ChamplainMapSourcePrivate ChamplainMapSourcePrivate;
-
-typedef enum
-{
- CHAMPLAIN_MAP_PROJECTION_MERCATOR
-} ChamplainMapProjection;
struct _ChamplainMapSource
{
- GInitiallyUnowned parent;
- ChamplainMapSourcePrivate *priv;
+ GInitiallyUnowned parent_instance;
};
struct _ChamplainMapSourceClass
{
GInitiallyUnownedClass parent_class;
+ const gchar * (*get_id) (ChamplainMapSource *map_source);
+ const gchar * (*get_name) (ChamplainMapSource *map_source);
+ const gchar * (*get_license) (ChamplainMapSource *map_source);
+ const gchar * (*get_license_uri) (ChamplainMapSource *map_source);
+ guint (*get_min_zoom_level) (ChamplainMapSource *map_source);
+ guint (*get_max_zoom_level) (ChamplainMapSource *map_source);
+ guint (*get_tile_size) (ChamplainMapSource *map_source);
+
void (*fill_tile) (ChamplainMapSource *map_source,
- ChamplainTile *tile);
+ ChamplainTile *tile);
};
GType champlain_map_source_get_type (void);
-gint champlain_map_source_get_min_zoom_level (ChamplainMapSource *map_source);
-
-gint champlain_map_source_get_max_zoom_level (ChamplainMapSource *map_source);
+ChamplainMapSource *champlain_map_source_get_next_source (ChamplainMapSource *map_source);
+void champlain_map_source_set_next_source (ChamplainMapSource *map_source,
+ ChamplainMapSource *next_source);
+const gchar * champlain_map_source_get_id (ChamplainMapSource *map_source);
+const gchar * champlain_map_source_get_name (ChamplainMapSource *map_source);
+const gchar * champlain_map_source_get_license (ChamplainMapSource *map_source);
+const gchar * champlain_map_source_get_license_uri (ChamplainMapSource *map_source);
+guint champlain_map_source_get_min_zoom_level (ChamplainMapSource *map_source);
+guint champlain_map_source_get_max_zoom_level (ChamplainMapSource *map_source);
guint champlain_map_source_get_tile_size (ChamplainMapSource *map_source);
guint champlain_map_source_get_x (ChamplainMapSource *map_source,
- gint zoom_level,
- gdouble longitude);
-
+ guint zoom_level,
+ gdouble longitude);
guint champlain_map_source_get_y (ChamplainMapSource *map_source,
- gint zoom_level,
- gdouble latitude);
-
+ guint zoom_level,
+ gdouble latitude);
gdouble champlain_map_source_get_longitude (ChamplainMapSource *map_source,
- gint zoom_level,
+ guint zoom_level,
guint x);
-
gdouble champlain_map_source_get_latitude (ChamplainMapSource *map_source,
- gint zoom_level,
+ guint zoom_level,
guint y);
-
guint champlain_map_source_get_row_count (ChamplainMapSource *map_source,
- gint zoom_level);
-
+ guint zoom_level);
guint champlain_map_source_get_column_count (ChamplainMapSource *map_source,
- gint zoom_level);
-
-void champlain_map_source_fill_tile (ChamplainMapSource *map_source,
- ChamplainTile *tile);
-
-void champlain_map_source_set_id (ChamplainMapSource *map_source,
- const gchar *id);
-const gchar * champlain_map_source_get_id (ChamplainMapSource *map_source);
-
-void champlain_map_source_set_name (ChamplainMapSource *map_source,
- const gchar *name);
-const gchar * champlain_map_source_get_name (ChamplainMapSource *map_source);
-
-void champlain_map_source_set_license (ChamplainMapSource *map_source,
- const gchar *license);
-const gchar * champlain_map_source_get_license (ChamplainMapSource *map_source);
-
-void champlain_map_source_set_license_uri (ChamplainMapSource *map_source,
- const gchar *license_uri);
-const gchar * champlain_map_source_get_license_uri (ChamplainMapSource *map_source);
-
-void champlain_map_source_set_projection (ChamplainMapSource *map_source,
- ChamplainMapProjection projection);
-ChamplainMapProjection champlain_map_source_get_projection (ChamplainMapSource *map_source);
-
-gfloat champlain_map_source_get_meters_per_pixel (ChamplainMapSource *map_source,
- gint zoom_level,
+ guint zoom_level);
+gdouble champlain_map_source_get_meters_per_pixel (ChamplainMapSource *map_source,
+ guint zoom_level,
gdouble latitude,
gdouble longitude);
+void champlain_map_source_fill_tile (ChamplainMapSource *map_source,
+ ChamplainTile *tile);
+
G_END_DECLS
-#endif
+#endif /* _CHAMPLAIN_MAP_SOURCE_H_ */
+
diff --git a/champlain/champlain-memphis-map-source.c b/champlain/champlain-memphis-map-source.c
index 73673a7..a72a669 100644
--- a/champlain/champlain-memphis-map-source.c
+++ b/champlain/champlain-memphis-map-source.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Simon Wenner <simon wenner ch>
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -45,18 +46,18 @@
#define DEBUG_FLAG CHAMPLAIN_DEBUG_MEMPHIS
#include "champlain-debug.h"
-#include "champlain-cache.h"
+#include "champlain-tile-cache.h"
#include "champlain-defines.h"
#include "champlain-enum-types.h"
#include "champlain-private.h"
+#include <gdk/gdk.h>
+
#include <errno.h>
#include <string.h>
/* Tuning parameters */
#define MAX_THREADS 4
-#define DEFAULT_TILE_SIZE 256 // FIXME: switching between map sources
- // with different tile size crashes champlain.
const gchar default_rules[] =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
@@ -69,39 +70,46 @@ const gchar default_rules[] =
enum
{
PROP_0,
- PROP_MAP_DATA_SOURCE,
- PROP_SESSION_ID,
- PROP_PERSISTENT_CACHE
+ PROP_MAP_DATA_SOURCE
};
-G_DEFINE_TYPE (ChamplainMemphisMapSource, champlain_memphis_map_source, CHAMPLAIN_TYPE_MAP_SOURCE)
+G_DEFINE_TYPE (ChamplainMemphisMapSource, champlain_memphis_map_source, CHAMPLAIN_TYPE_TILE_SOURCE)
#define GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), CHAMPLAIN_TYPE_MEMPHIS_MAP_SOURCE, ChamplainMemphisMapSourcePrivate))
typedef struct _ChamplainMemphisMapSourcePrivate ChamplainMemphisMapSourcePrivate;
-struct _ChamplainMemphisMapSourcePrivate {
+struct _ChamplainMemphisMapSourcePrivate
+{
ChamplainMapDataSource *map_data_source;
- gchar *session_id;
MemphisRuleSet *rules;
MemphisRenderer *renderer;
GThreadPool *thpool;
gboolean no_map_data;
- gboolean persistent_cache;
};
-typedef struct _TileData TileData;
+typedef struct _TileLoadedData TileLoadedData;
-struct _TileData {
+struct _TileLoadedData
+{
+ ChamplainMapSource *map_source;
ChamplainTile *tile;
cairo_surface_t *cst;
- gchar *session_id;
};
/* lock to protect the renderer state while rendering */
GStaticRWLock MemphisLock = G_STATIC_RW_LOCK_INIT;
+static void fill_tile (ChamplainMapSource *map_source, ChamplainTile *tile);
+
+static void reload_tiles (ChamplainMemphisMapSource *self);
+static void memphis_worker_thread (gpointer data, gpointer user_data);
+static void map_data_changed_cb (ChamplainMapDataSource *map_data_source,
+ GParamSpec *gobject,
+ ChamplainMemphisMapSource *map_source);
+void argb_to_rgba(guchar *data, guint size);
+
static void
champlain_memphis_map_source_get_property (GObject *object,
guint property_id,
@@ -113,17 +121,11 @@ champlain_memphis_map_source_get_property (GObject *object,
switch (property_id)
{
- case PROP_MAP_DATA_SOURCE:
- g_value_set_object (value, priv->map_data_source);
- break;
- case PROP_SESSION_ID:
- g_value_set_string (value, priv->session_id);
- break;
- case PROP_PERSISTENT_CACHE:
- g_value_set_boolean (value, priv->persistent_cache);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ case PROP_MAP_DATA_SOURCE:
+ g_value_set_object (value, priv->map_data_source);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
@@ -134,30 +136,22 @@ champlain_memphis_map_source_set_property (GObject *object,
GParamSpec *pspec)
{
ChamplainMemphisMapSource *self = CHAMPLAIN_MEMPHIS_MAP_SOURCE (object);
- ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE (self);
switch (property_id)
{
- case PROP_MAP_DATA_SOURCE:
- champlain_memphis_map_source_set_map_data_source (self,
- g_value_get_object (value));
- break;
- case PROP_SESSION_ID:
- champlain_memphis_map_source_set_session_id (self,
- g_value_get_string (value));
- break;
- case PROP_PERSISTENT_CACHE:
- priv->persistent_cache = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ case PROP_MAP_DATA_SOURCE:
+ champlain_memphis_map_source_set_map_data_source (self,
+ g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
champlain_memphis_map_source_dispose (GObject *object)
{
- ChamplainMemphisMapSource *self = (ChamplainMemphisMapSource *) object;
+ ChamplainMemphisMapSource *self = CHAMPLAIN_MEMPHIS_MAP_SOURCE(object);
ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE(self);
if (priv->thpool)
@@ -187,21 +181,120 @@ champlain_memphis_map_source_dispose (GObject *object)
static void
champlain_memphis_map_source_finalize (GObject *object)
{
- ChamplainMemphisMapSource *self = (ChamplainMemphisMapSource *) object;
+ G_OBJECT_CLASS (champlain_memphis_map_source_parent_class)->finalize (object);
+}
+
+static void
+champlain_memphis_map_source_constructed (GObject *object)
+{
+ ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE(object);
+ ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE(object);
+
+ memphis_renderer_set_resolution (priv->renderer, champlain_map_source_get_tile_size(map_source));
+
+ G_OBJECT_CLASS (champlain_memphis_map_source_parent_class)->constructed (object);
+}
+
+static void
+champlain_memphis_map_source_class_init (ChamplainMemphisMapSourceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ ChamplainMapSourceClass *map_source_class = CHAMPLAIN_MAP_SOURCE_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (ChamplainMemphisMapSourcePrivate));
+
+ object_class->get_property = champlain_memphis_map_source_get_property;
+ object_class->set_property = champlain_memphis_map_source_set_property;
+ object_class->dispose = champlain_memphis_map_source_dispose;
+ object_class->finalize = champlain_memphis_map_source_finalize;
+ object_class->constructed = champlain_memphis_map_source_constructed;
+
+ map_source_class->fill_tile = fill_tile;
+
+ /**
+ * ChamplainMemphisMapSource:map-data-source:
+ *
+ * The data source of the renderer
+ *
+ * Since: 0.6
+ */
+ g_object_class_install_property (object_class,
+ PROP_MAP_DATA_SOURCE,
+ g_param_spec_object ("map-data-source",
+ "Map data source",
+ "The data source of the renderer",
+ CHAMPLAIN_TYPE_MAP_DATA_SOURCE,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+}
+
+static void
+champlain_memphis_map_source_init (ChamplainMemphisMapSource *self)
+{
ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE(self);
- g_free (priv->session_id);
+ priv->map_data_source = NULL;
+ priv->rules = NULL;
+ priv->renderer = NULL;
+ priv->no_map_data = TRUE;
- G_OBJECT_CLASS (champlain_memphis_map_source_parent_class)->finalize (object);
+ priv->rules = memphis_rule_set_new ();
+ memphis_rule_set_load_from_data (priv->rules, default_rules,
+ strlen (default_rules));
+
+ priv->renderer = memphis_renderer_new_full (priv->rules, memphis_map_new ());
+
+ priv->thpool = g_thread_pool_new (memphis_worker_thread, self,
+ MAX_THREADS, FALSE, NULL);
+}
+
+/**
+ * champlain_memphis_map_source_new_full:
+ * @id: the map source's id
+ * @name: the map source's name
+ * @license: the map source's license
+ * @license_uri: the map source's license URI
+ * @min_zoom: the map source's minimum zoom level
+ * @max_zoom: the map source's maximum zoom level
+ * @tile_size: the map source's tile size (in pixels)
+ * @projection: the map source's projection
+ * @map_data_source: a #ChamplainMapDataSource
+ *
+ * Returns: a new ChamplainMemphisMapSource.
+ *
+ * Since: 0.6
+ */
+ChamplainMemphisMapSource* champlain_memphis_map_source_new_full (const gchar *id,
+ const gchar *name,
+ const gchar *license,
+ const gchar *license_uri,
+ guint min_zoom_level,
+ guint max_zoom_level,
+ guint tile_size,
+ ChamplainMapProjection projection,
+ ChamplainMapDataSource *map_data_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_DATA_SOURCE (map_data_source), NULL);
+
+ return g_object_new (CHAMPLAIN_TYPE_MEMPHIS_MAP_SOURCE,
+ "id", id,
+ "name", name,
+ "license", license,
+ "license-uri", license_uri,
+ "min-zoom-level", min_zoom_level,
+ "max-zoom-level", max_zoom_level,
+ "tile-size", tile_size,
+ "projection", projection,
+ "map-data-source", map_data_source,
+ NULL);
}
static void
map_data_changed_cb (ChamplainMapDataSource *map_data_source,
- GParamSpec *gobject,
- ChamplainMemphisMapSource *map_source)
+ GParamSpec *gobject,
+ ChamplainMemphisMapSource *map_source)
{
g_assert (CHAMPLAIN_IS_MAP_DATA_SOURCE (map_data_source) &&
- CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (map_source));
+ CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (map_source));
MemphisMap *map;
ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE(map_source);
@@ -218,9 +311,7 @@ map_data_changed_cb (ChamplainMapDataSource *map_data_source,
priv->no_map_data = TRUE;
}
else
- {
- priv->no_map_data = FALSE;
- }
+ priv->no_map_data = FALSE;
DEBUG ("DataSource has been changed!");
@@ -228,118 +319,88 @@ map_data_changed_cb (ChamplainMapDataSource *map_data_source,
memphis_renderer_set_map (priv->renderer, map);
g_static_rw_lock_writer_unlock (&MemphisLock);
- if (!priv->persistent_cache)
- champlain_memphis_map_source_delete_session_cache (map_source);
+ reload_tiles (map_source);
}
-static void
-fill_tile (ChamplainMapSource *map_source, ChamplainTile *tile)
+/*
+Transform ARGB (Cairo) to RGBA (GdkPixbuf). RGBA is actualy reversed in
+memory, so the transformation is ARGB -> ABGR (i.e. swapping B and R)
+*/
+void argb_to_rgba(guchar *data, guint size)
{
- ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE(map_source);
- ChamplainCache* cache = champlain_cache_dup_default ();
- guint size;
- GError *error = NULL;
- gchar *filename;
- gboolean in_cache = FALSE;
-
- size = champlain_map_source_get_tile_size (map_source);
- champlain_tile_set_size (tile, size);
-
- filename = champlain_cache_get_filename (cache, map_source, tile,
- priv->session_id);
- champlain_tile_set_filename (tile, filename);
-
- in_cache = champlain_cache_fill_tile (cache, tile);
-
- /* check for cached version */
- if (in_cache == TRUE)
- {
- DEBUG ("Tile was cached (%u, %u, %u)", champlain_tile_get_x (tile),
- champlain_tile_get_y (tile),
- champlain_tile_get_zoom_level (tile));
- champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
- }
- else if (priv->no_map_data)
- {
- DEBUG ("No tile data (%u, %u, %u)",
- champlain_tile_get_x (tile),
- champlain_tile_get_y (tile),
- champlain_tile_get_zoom_level (tile));
-
- create_error_tile (tile);
- }
- else
- {
- DEBUG ("Render tile (%u, %u, %u)", champlain_tile_get_x (tile),
- champlain_tile_get_y (tile),
- champlain_tile_get_zoom_level (tile));
- champlain_tile_set_state (tile, CHAMPLAIN_STATE_LOADING);
-
- /* So we don't loose a tile if it is in the thread pool queue for a long time */
- tile = g_object_ref (tile);
-
- g_thread_pool_push (priv->thpool, tile, &error);
- if (error)
- {
- g_error ("Thread pool error: %s", error->message);
- g_error_free (error);
- }
- }
- g_object_unref (cache);
+ guint32 *ptr;
+ guint32 *endptr = (guint32 *)data + size / 4;
+ for (ptr = (guint32 *)data; ptr < endptr; ptr++)
+ *ptr = (*ptr & 0xFF00FF00) ^ ((*ptr & 0xFF0000) >> 16) ^ ((*ptr & 0xFF) << 16);
}
static gboolean
-set_tile_content (gpointer data)
+tile_loaded_cb (gpointer data)
{
- TileData *tdata = (TileData *) data;
+ TileLoadedData *tdata = (TileLoadedData *) data;
+ ChamplainMapSource *map_source = tdata->map_source;
ChamplainTile *tile = tdata->tile;
cairo_surface_t *cst = tdata->cst;
- gchar *session = tdata->session_id;
+ ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE(map_source);
+ ChamplainTileCache *tile_cache = champlain_tile_source_get_cache(tile_source);
cairo_t *cr_clutter;
ClutterActor *actor;
guint size;
- ChamplainCache *cache = champlain_cache_dup_default ();
+ GError *error = NULL;
- /* update the cache */
- champlain_cache_update_tile_with_session (cache, tile, 20, session);
+ g_free (tdata);
- g_object_unref (cache);
+ // FIXME - once memphis detects when tile cannot be rendered, call fill_tile
+ // on next_source here and return
- /* draw the clutter texture */
size = champlain_tile_get_size (tile);
+
+ /* draw the clutter texture */
actor = clutter_cairo_texture_new (size, size);
cr_clutter = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (actor));
cairo_set_source_surface (cr_clutter, cst, 0, 0);
cairo_paint (cr_clutter);
cairo_destroy (cr_clutter);
- cairo_surface_destroy (cst);
- champlain_tile_set_content (tile, actor, TRUE);
-
- champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
- g_object_unref (tile);
-
- g_free (tdata);
- return FALSE;
-}
-
-static gboolean
-delete_session_cache (gpointer data)
-{
- ChamplainMemphisMapSource *self = CHAMPLAIN_MEMPHIS_MAP_SOURCE (data);
- ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE(self);
- ChamplainCache* cache = champlain_cache_dup_default ();
+ /* update the cache */
+ if (tile_cache)
+ {
+ GdkPixbuf * pixbuf;
+ gchar *buffer;
+ gsize buffer_size;
+
+ /* modify directly the buffer of cairo surface - we don't use it any more
+ and we close the surface anyway */
+ argb_to_rgba(cairo_image_surface_get_data(cst),
+ cairo_image_surface_get_stride(cst) * cairo_image_surface_get_height(cst));
+
+ pixbuf = gdk_pixbuf_new_from_data(cairo_image_surface_get_data(cst),
+ GDK_COLORSPACE_RGB,
+ TRUE,
+ 8,
+ size,
+ size,
+ cairo_image_surface_get_stride(cst),
+ NULL,
+ NULL);
+
+ if (gdk_pixbuf_save_to_buffer(pixbuf, &buffer, &buffer_size, "png", &error, NULL))
+ {
+ champlain_tile_cache_store_tile(tile_cache, tile, buffer, buffer_size);
+ }
- champlain_cache_delete_session (cache, CHAMPLAIN_MAP_SOURCE (self),
- priv->session_id);
+ g_free(buffer);
+ g_object_unref(pixbuf);
+ }
- DEBUG ("Delete '%s' session cache", priv->session_id);
+ cairo_surface_destroy (cst);
- g_object_unref (cache);
+ champlain_tile_set_content (tile, actor, TRUE);
+ champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
- g_signal_emit_by_name (CHAMPLAIN_MAP_SOURCE (self),
- "reload-tiles", NULL);
+ g_object_unref (tile);
+ g_object_unref (map_source);
return FALSE;
}
@@ -347,13 +408,12 @@ delete_session_cache (gpointer data)
static void
memphis_worker_thread (gpointer data, gpointer user_data)
{
- ChamplainTile *tile = CHAMPLAIN_TILE (data);
- ChamplainMemphisMapSource *map_source = CHAMPLAIN_MEMPHIS_MAP_SOURCE (user_data);
- ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE(map_source);
+ ChamplainTile *tile = (ChamplainTile *)data;
+ ChamplainMapSource *map_source = (ChamplainMapSource *)user_data;
cairo_t *cr;
cairo_surface_t *cst;
guint x, y, z, size;
- TileData *tdata;
+ TileLoadedData *loaded_data;
x = champlain_tile_get_x (tile);
y = champlain_tile_get_y (tile);
@@ -366,177 +426,82 @@ memphis_worker_thread (gpointer data, gpointer user_data)
DEBUG ("Draw Tile (%d, %d, %d)", x, y, z);
+ // FIXME - memphis should support multithreaded access to utilize multiple CPUs
g_static_rw_lock_reader_lock (&MemphisLock);
- memphis_renderer_draw_tile (priv->renderer, cr, x, y, z);
+ // FIXME - memphis needs to indicate if it cannot render the tile so we can
+ // load the tile from the next map source
+ memphis_renderer_draw_tile (GET_PRIVATE(map_source)->renderer, cr, x, y, z);
g_static_rw_lock_reader_unlock (&MemphisLock);
- cairo_destroy (cr);
-
- const gchar *filename = champlain_tile_get_filename (tile);
- /* Create, if needed, the cache's dirs */
- char *path = g_path_get_dirname (filename);
- if (g_mkdir_with_parents (path, 0700) == -1)
- {
- if (errno != EEXIST)
- {
- g_warning ("Unable to create the image cache path '%s': %s",
- path, g_strerror (errno));
- }
- }
- g_free (path);
-
- /* Write png image for caching */
- if (cairo_surface_write_to_png (cst, filename) != CAIRO_STATUS_SUCCESS)
- {
- g_warning ("Unable to write image '%s' to the cache", filename);
- }
+ cairo_destroy (cr);
/* Write the tile content and cache entry */
- tdata = g_new (TileData, 1);
- tdata->tile = tile;
- tdata->cst = cst;
- tdata->session_id = priv->session_id;
+ loaded_data = g_new (TileLoadedData, 1);
+ loaded_data->map_source = map_source;
+ loaded_data->tile = tile;
+ loaded_data->cst = cst;
- clutter_threads_add_idle_full (G_PRIORITY_DEFAULT, set_tile_content,
- tdata, NULL);
+ clutter_threads_add_idle_full (G_PRIORITY_DEFAULT, tile_loaded_cb,
+ loaded_data, NULL);
}
static void
-champlain_memphis_map_source_class_init (ChamplainMemphisMapSourceClass *klass)
+fill_tile (ChamplainMapSource *map_source, ChamplainTile *tile)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (ChamplainMemphisMapSourcePrivate));
+ g_return_if_fail (CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (map_source));
- object_class->get_property = champlain_memphis_map_source_get_property;
- object_class->set_property = champlain_memphis_map_source_set_property;
- object_class->dispose = champlain_memphis_map_source_dispose;
- object_class->finalize = champlain_memphis_map_source_finalize;
+ ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE(map_source);
- ChamplainMapSourceClass *map_source_class = CHAMPLAIN_MAP_SOURCE_CLASS (klass);
- map_source_class->fill_tile = fill_tile;
+ DEBUG ("Render tile (%u, %u, %u)", champlain_tile_get_x (tile),
+ champlain_tile_get_y (tile),
+ champlain_tile_get_zoom_level (tile));
- /**
- * ChamplainMemphisMapSource:map-data-source:
- *
- * The data source of the renderer
- *
- * Since: 0.6
- */
- g_object_class_install_property (object_class,
- PROP_MAP_DATA_SOURCE,
- g_param_spec_object ("map-data-source",
- "Map data source",
- "The data source of the renderer",
- CHAMPLAIN_TYPE_MAP_DATA_SOURCE,
- G_PARAM_READWRITE));
+ if (priv->no_map_data)
+ {
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
- /**
- * ChamplainMemphisMapSource:session:
- *
- * The session id of the tile cache
- *
- * Since: 0.6
- */
- g_object_class_install_property (object_class,
- PROP_SESSION_ID,
- g_param_spec_string ("session-id",
- "Cache session id",
- "The session id of the cache",
- "default",
- G_PARAM_READWRITE));
+ if (CHAMPLAIN_IS_MAP_SOURCE(next_source))
+ champlain_map_source_fill_tile(next_source, tile);
+ }
+ else
+ {
+ GError *error = NULL;
+ guint size;
- /**
- * ChamplainMemphisMapSource:persistent-cache:
- *
- * If the session cache should be deleted if data or rules are changed.
- * If enabled the client has to manage the cache explicitly with
- * champlain_memphis_map_source_delete_session_cache().
- *
- * Since: 0.6
- */
- g_object_class_install_property (object_class,
- PROP_PERSISTENT_CACHE,
- g_param_spec_boolean ("persistent-cache",
- "Persistent cache",
- "If the cache is persistent",
- FALSE,
- G_PARAM_READWRITE));
-}
+ size = champlain_map_source_get_tile_size (map_source);
+ champlain_tile_set_size (tile, size);
-static void
-champlain_memphis_map_source_init (ChamplainMemphisMapSource *self)
-{
- ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE(self);
+ g_object_ref (tile);
+ g_object_ref (map_source);
- priv->map_data_source = NULL;
- priv->rules = NULL;
- priv->renderer = NULL;
- priv->thpool = NULL;
- priv->session_id = g_strdup ("default");
- priv->no_map_data = TRUE;
- priv->persistent_cache = FALSE;
+ g_thread_pool_push (priv->thpool, tile, &error);
+ if (error)
+ {
+ g_error ("Thread pool error: %s", error->message);
+ g_error_free (error);
+ g_object_unref(map_source);
+ g_object_unref(tile);
+ }
+ }
}
-/**
- * champlain_memphis_map_source_new_full:
- * @desc: a #ChamplainMapSourceDesc
- * @map_data_source: a #ChamplainMapDataSource
- *
- * Returns: a new ChamplainMemphisMapSource.
- *
- * Since: 0.6
- */
-ChamplainMemphisMapSource *
-champlain_memphis_map_source_new_full (ChamplainMapSourceDesc *desc,
- ChamplainMapDataSource *map_data_source)
+static void
+reload_tiles (ChamplainMemphisMapSource *self)
{
- g_return_val_if_fail (CHAMPLAIN_IS_MAP_DATA_SOURCE (map_data_source) &&
- CHAMPLAIN_MAP_SOURCE_DESC (desc), NULL);
-
- ChamplainMemphisMapSource *source;
- ChamplainMemphisMapSourcePrivate *priv;
- MemphisMap *map;
-
- source = g_object_new (CHAMPLAIN_TYPE_MEMPHIS_MAP_SOURCE,
- "id", desc->id,
- "name", desc->name,
- "license", desc->license,
- "license-uri", desc->license_uri,
- "projection", desc->projection,
- "min-zoom-level", desc->min_zoom_level,
- "max-zoom-level", desc->max_zoom_level,
- "tile-size", DEFAULT_TILE_SIZE,
- NULL);
-
- priv = GET_PRIVATE(source);
- priv->map_data_source = g_object_ref (map_data_source);
+ g_return_if_fail (CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (self));
- g_signal_connect (priv->map_data_source, "notify::state",
- G_CALLBACK (map_data_changed_cb), source);
+ ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE(self);
+ ChamplainTileCache *tile_cache = champlain_tile_source_get_cache(tile_source);
- priv->rules = memphis_rule_set_new ();
- map = champlain_map_data_source_get_map_data (priv->map_data_source);
- if (map == NULL)
+ if (tile_cache && !champlain_tile_cache_get_persistent(tile_cache))
{
- map = memphis_map_new ();
- priv->no_map_data = TRUE;
- }
- else
- {
- priv->no_map_data = FALSE;
- }
-
- priv->renderer = memphis_renderer_new_full (priv->rules, map);
- memphis_renderer_set_resolution (priv->renderer, DEFAULT_TILE_SIZE);
-
- memphis_rule_set_load_from_data (priv->rules, default_rules,
- strlen (default_rules));
+ DEBUG ("Clean temporary cache");
- priv->thpool = g_thread_pool_new (memphis_worker_thread, source,
- MAX_THREADS, FALSE, NULL);
+ champlain_tile_cache_clean (tile_cache);
+ }
- return source;
+ g_signal_emit_by_name (CHAMPLAIN_MAP_SOURCE (self),
+ "reload-tiles", NULL);
}
/**
@@ -550,8 +515,8 @@ champlain_memphis_map_source_new_full (ChamplainMapSourceDesc *desc,
*/
void
champlain_memphis_map_source_load_rules (
- ChamplainMemphisMapSource *self,
- const gchar *rules_path)
+ ChamplainMemphisMapSource *self,
+ const gchar *rules_path)
{
g_return_if_fail (CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (self));
@@ -569,11 +534,10 @@ champlain_memphis_map_source_load_rules (
memphis_rule_set_load_from_file (priv->rules, rules_path);
else
memphis_rule_set_load_from_data (priv->rules, default_rules,
- strlen (default_rules));
+ strlen (default_rules));
g_static_rw_lock_writer_unlock (&MemphisLock);
- if (!priv->persistent_cache)
- champlain_memphis_map_source_delete_session_cache (self);
+ reload_tiles (self);
}
/**
@@ -587,17 +551,31 @@ champlain_memphis_map_source_load_rules (
*/
void
champlain_memphis_map_source_set_map_data_source (
- ChamplainMemphisMapSource *self,
- ChamplainMapDataSource *map_data_source)
+ ChamplainMemphisMapSource *self,
+ ChamplainMapDataSource *map_data_source)
{
g_return_if_fail (CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (self) &&
- CHAMPLAIN_IS_MAP_DATA_SOURCE (map_data_source));
+ CHAMPLAIN_IS_MAP_DATA_SOURCE (map_data_source));
ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE (self);
MemphisMap *map;
- priv->map_data_source = map_data_source;
+ if (priv->map_data_source)
+ g_object_unref (priv->map_data_source);
+
+ priv->map_data_source = g_object_ref_sink(map_data_source);
+
+ g_signal_connect (priv->map_data_source, "notify::state",
+ G_CALLBACK (map_data_changed_cb), self);
+
map = champlain_map_data_source_get_map_data (priv->map_data_source);
+ if (map == NULL)
+ {
+ map = memphis_map_new ();
+ priv->no_map_data = TRUE;
+ }
+ else
+ priv->no_map_data = FALSE;
g_static_rw_lock_writer_lock (&MemphisLock);
memphis_renderer_set_map (priv->renderer, map);
@@ -614,7 +592,7 @@ champlain_memphis_map_source_set_map_data_source (
*/
ChamplainMapDataSource *
champlain_memphis_map_source_get_map_data_source (
- ChamplainMemphisMapSource *self)
+ ChamplainMemphisMapSource *self)
{
g_return_val_if_fail (CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (self), NULL);
@@ -623,64 +601,6 @@ champlain_memphis_map_source_get_map_data_source (
}
/**
- * champlain_memphis_map_source_delete_session_cache:
- * @map_source: a #ChamplainMemphisMapSource
- *
- * Deletes all cached tiles of the current session.
- *
- * Since: 0.6
- */
-void
-champlain_memphis_map_source_delete_session_cache (ChamplainMemphisMapSource *self)
-{
- g_return_if_fail (CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (self));
-
- clutter_threads_add_idle_full (G_PRIORITY_DEFAULT, delete_session_cache,
- self, NULL);
-}
-
-/**
- * champlain_memphis_map_source_set_session_id:
- * @map_source: a #ChamplainMemphisMapSource
- * @session_id: a session id string
- *
- * Sets the session id of the cache.
- *
- * Since: 0.6
- */
-void
-champlain_memphis_map_source_set_session_id (ChamplainMemphisMapSource *self,
- const gchar *session_id)
-{
- g_return_if_fail (CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (self)
- && session_id != NULL);
-
- ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE (self);
-
- if (priv->session_id)
- g_free (priv->session_id);
-
- priv->session_id = g_strdup (session_id);
-}
-
-/**
- * champlain_memphis_map_source_get_session_id:
- * @map_source: a #ChamplainMemphisMapSource
- *
- * Returns the session id string.
- *
- * Since: 0.6
- */
-const gchar *
-champlain_memphis_map_source_get_session_id (ChamplainMemphisMapSource *self)
-{
- g_return_val_if_fail (CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (self), NULL);
-
- ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE (self);
- return priv->session_id;
-}
-
-/**
* champlain_memphis_map_source_get_background_color:
* @map_source: a #ChamplainMemphisMapSource
*
@@ -690,7 +610,7 @@ champlain_memphis_map_source_get_session_id (ChamplainMemphisMapSource *self)
* Since: 0.6
*/
ClutterColor * champlain_memphis_map_source_get_background_color (
- ChamplainMemphisMapSource *self)
+ ChamplainMemphisMapSource *self)
{
g_return_val_if_fail (CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (self), NULL);
@@ -720,8 +640,8 @@ ClutterColor * champlain_memphis_map_source_get_background_color (
*/
void
champlain_memphis_map_source_set_background_color (
- ChamplainMemphisMapSource *self,
- const ClutterColor *color)
+ ChamplainMemphisMapSource *self,
+ const ClutterColor *color)
{
g_return_if_fail (CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (self));
@@ -729,11 +649,10 @@ champlain_memphis_map_source_set_background_color (
g_static_rw_lock_writer_lock (&MemphisLock);
memphis_rule_set_set_bg_color (priv->rules, color->red,
- color->green, color->blue, color->alpha);
+ color->green, color->blue, color->alpha);
g_static_rw_lock_writer_unlock (&MemphisLock);
- if (!priv->persistent_cache)
- champlain_memphis_map_source_delete_session_cache (self);
+ reload_tiles (self);
}
/**
@@ -748,10 +667,10 @@ champlain_memphis_map_source_set_background_color (
*/
void
champlain_memphis_map_source_set_rule (ChamplainMemphisMapSource *self,
- MemphisRule *rule)
+ MemphisRule *rule)
{
g_return_if_fail (CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (self) &&
- MEMPHIS_RULE (rule));
+ MEMPHIS_RULE (rule));
ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE (self);
@@ -759,8 +678,7 @@ champlain_memphis_map_source_set_rule (ChamplainMemphisMapSource *self,
memphis_rule_set_set_rule (priv->rules, rule);
g_static_rw_lock_writer_unlock (&MemphisLock);
- if (!priv->persistent_cache)
- champlain_memphis_map_source_delete_session_cache (self);
+ reload_tiles (self);
}
/**
@@ -774,10 +692,10 @@ champlain_memphis_map_source_set_rule (ChamplainMemphisMapSource *self,
*/
MemphisRule *
champlain_memphis_map_source_get_rule (ChamplainMemphisMapSource *self,
- const gchar *id)
+ const gchar *id)
{
g_return_val_if_fail (CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (self) &&
- id != NULL, NULL);
+ id != NULL, NULL);
ChamplainMemphisMapSourcePrivate *priv = GET_PRIVATE (self);
MemphisRule *rule;
@@ -825,8 +743,8 @@ champlain_memphis_map_source_get_rule_ids (ChamplainMemphisMapSource *self)
* Since: 0.6
*/
void champlain_memphis_map_source_remove_rule (
- ChamplainMemphisMapSource *self,
- const gchar *id)
+ ChamplainMemphisMapSource *self,
+ const gchar *id)
{
g_return_if_fail (CHAMPLAIN_IS_MEMPHIS_MAP_SOURCE (self));
@@ -836,6 +754,5 @@ void champlain_memphis_map_source_remove_rule (
memphis_rule_set_remove_rule (priv->rules, id);
g_static_rw_lock_writer_unlock (&MemphisLock);
- if (!priv->persistent_cache)
- champlain_memphis_map_source_delete_session_cache (self);
+ reload_tiles (self);
}
diff --git a/champlain/champlain-memphis-map-source.h b/champlain/champlain-memphis-map-source.h
index e49e45c..403bfa6 100644
--- a/champlain/champlain-memphis-map-source.h
+++ b/champlain/champlain-memphis-map-source.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Simon Wenner <simon wenner ch>
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,9 +20,8 @@
#ifndef _CHAMPLAIN_MEMPHIS_MAP_SOURCE
#define _CHAMPLAIN_MEMPHIS_MAP_SOURCE
+#include <champlain/champlain-tile-source.h>
#include <champlain/champlain-map-data-source.h>
-#include <champlain/champlain-map-source.h>
-#include <champlain/champlain-map-source-desc.h>
#include <memphis/memphis.h>
#include <glib-object.h>
@@ -46,17 +46,23 @@ G_BEGIN_DECLS
(G_TYPE_INSTANCE_GET_CLASS ((obj), CHAMPLAIN_TYPE_MEMPHIS_MAP_SOURCE, ChamplainMemphisMapSourceClass))
typedef struct {
- ChamplainMapSource parent;
+ ChamplainTileSource parent;
} ChamplainMemphisMapSource;
typedef struct {
- ChamplainMapSourceClass parent_class;
+ ChamplainTileSourceClass parent_class;
} ChamplainMemphisMapSourceClass;
GType champlain_memphis_map_source_get_type (void);
-ChamplainMemphisMapSource * champlain_memphis_map_source_new_full (
- ChamplainMapSourceDesc *desc,
+ChamplainMemphisMapSource* champlain_memphis_map_source_new_full (const gchar *id,
+ const gchar *name,
+ const gchar *license,
+ const gchar *license_uri,
+ guint min_zoom,
+ guint max_zoom,
+ guint tile_size,
+ ChamplainMapProjection projection,
ChamplainMapDataSource *map_data_source);
void champlain_memphis_map_source_load_rules (
@@ -70,15 +76,6 @@ void champlain_memphis_map_source_set_map_data_source (
ChamplainMapDataSource * champlain_memphis_map_source_get_map_data_source (
ChamplainMemphisMapSource *map_source);
-void champlain_memphis_map_source_delete_session_cache (
- ChamplainMemphisMapSource *map_source);
-
-void champlain_memphis_map_source_set_session_id (
- ChamplainMemphisMapSource *map_source,
- const gchar *session_id);
-const gchar * champlain_memphis_map_source_get_session_id (
- ChamplainMemphisMapSource *map_source);
-
ClutterColor * champlain_memphis_map_source_get_background_color (
ChamplainMemphisMapSource *map_source);
diff --git a/champlain/champlain-network-tile-source.c b/champlain/champlain-network-tile-source.c
new file mode 100644
index 0000000..f26a854
--- /dev/null
+++ b/champlain/champlain-network-tile-source.c
@@ -0,0 +1,570 @@
+/*
+ * Copyright (C) 2008-2009 Pierre-Luc Beaudoin <pierre-luc pierlux com>
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include "champlain-network-tile-source.h"
+
+#define DEBUG_FLAG CHAMPLAIN_DEBUG_LOADING
+#include "champlain-debug.h"
+
+#include "champlain.h"
+#include "champlain-defines.h"
+#include "champlain-enum-types.h"
+#include "champlain-map-source.h"
+#include "champlain-marshal.h"
+#include "champlain-private.h"
+#include "champlain-zoom-level.h"
+
+#include <errno.h>
+#include <gdk/gdk.h>
+#include <gio/gio.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib-object.h>
+#ifdef HAVE_LIBSOUP_GNOME
+#include <libsoup/soup-gnome.h>
+#else
+#include <libsoup/soup.h>
+#endif
+#include <math.h>
+#include <sys/stat.h>
+#include <string.h>
+
+enum
+{
+ PROP_0,
+ PROP_URI_FORMAT,
+ PROP_OFFLINE,
+ PROP_PROXY_URI
+};
+
+G_DEFINE_TYPE (ChamplainNetworkTileSource, champlain_network_tile_source, CHAMPLAIN_TYPE_TILE_SOURCE);
+
+#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHAMPLAIN_TYPE_NETWORK_TILE_SOURCE, ChamplainNetworkTileSourcePrivate))
+
+typedef struct _ChamplainNetworkTileSourcePrivate ChamplainNetworkTileSourcePrivate;
+
+struct _ChamplainNetworkTileSourcePrivate
+{
+ gboolean offline;
+ gchar *uri_format;
+ gchar *proxy_uri;
+ SoupSession * soup_session;
+};
+
+typedef struct
+{
+ ChamplainMapSource *map_source;
+ ChamplainTile *tile;
+} TileLoadedCallbackData;
+
+static void fill_tile (ChamplainMapSource *map_source,
+ ChamplainTile *tile);
+
+static gchar *
+get_tile_uri (ChamplainNetworkTileSource *source,
+ gint x,
+ gint y,
+ gint z);
+
+static void
+champlain_network_tile_source_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ChamplainNetworkTileSourcePrivate *priv = GET_PRIVATE(object);
+
+ switch(prop_id)
+ {
+ case PROP_URI_FORMAT:
+ g_value_set_string (value, priv->uri_format);
+ break;
+ case PROP_OFFLINE:
+ g_value_set_boolean (value, priv->offline);
+ break;
+ case PROP_PROXY_URI:
+ g_value_set_string (value, priv->proxy_uri);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+champlain_network_tile_source_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ChamplainNetworkTileSource *tile_source = CHAMPLAIN_NETWORK_TILE_SOURCE(object);
+
+ switch(prop_id)
+ {
+ case PROP_URI_FORMAT:
+ champlain_network_tile_source_set_uri_format(tile_source, g_value_get_string (value));
+ break;
+ case PROP_OFFLINE:
+ champlain_network_tile_source_set_offline(tile_source, g_value_get_boolean (value));
+ break;
+ case PROP_PROXY_URI:
+ champlain_network_tile_source_set_proxy_uri(tile_source, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+champlain_network_tile_source_dispose (GObject *object)
+{
+ ChamplainNetworkTileSourcePrivate *priv = GET_PRIVATE(object);
+
+ if (priv->soup_session)
+ soup_session_abort (priv->soup_session);
+
+ G_OBJECT_CLASS (champlain_network_tile_source_parent_class)->dispose (object);
+}
+
+static void
+champlain_network_tile_source_finalize (GObject *object)
+{
+ ChamplainNetworkTileSourcePrivate *priv = GET_PRIVATE(object);
+
+ g_free (priv->uri_format);
+ g_free (priv->proxy_uri);
+
+ G_OBJECT_CLASS (champlain_network_tile_source_parent_class)->finalize (object);
+}
+
+static void
+champlain_network_tile_source_constructed (GObject *object)
+{
+ G_OBJECT_CLASS (champlain_network_tile_source_parent_class)->constructed (object);
+}
+
+static void
+champlain_network_tile_source_class_init (ChamplainNetworkTileSourceClass *klass)
+{
+ ChamplainMapSourceClass *map_source_class = CHAMPLAIN_MAP_SOURCE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GParamSpec *pspec;
+
+ g_type_class_add_private (klass, sizeof (ChamplainNetworkTileSourcePrivate));
+
+ object_class->finalize = champlain_network_tile_source_finalize;
+ object_class->dispose = champlain_network_tile_source_dispose;
+ object_class->get_property = champlain_network_tile_source_get_property;
+ object_class->set_property = champlain_network_tile_source_set_property;
+ object_class->constructed = champlain_network_tile_source_constructed;
+
+ map_source_class->fill_tile = fill_tile;
+
+ pspec = g_param_spec_string ("uri-format",
+ "URI Format",
+ "The URI format",
+ "",
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class, PROP_URI_FORMAT, pspec);
+
+ pspec = g_param_spec_boolean ("offline",
+ "Offline",
+ "Offline",
+ FALSE,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_OFFLINE, pspec);
+
+ pspec = g_param_spec_string ("proxy-uri",
+ "Proxy URI",
+ "The proxy URI to use to access network",
+ "",
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_PROXY_URI, pspec);
+}
+
+static void
+champlain_network_tile_source_init (ChamplainNetworkTileSource *tile_source)
+{
+ ChamplainNetworkTileSourcePrivate *priv = GET_PRIVATE (tile_source);
+
+ priv->proxy_uri = NULL;
+ priv->uri_format = NULL;
+ priv->offline = FALSE;
+
+ priv->soup_session = soup_session_async_new_with_options (
+ "proxy-uri", NULL,
+#ifdef HAVE_LIBSOUP_GNOME
+ SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_GNOME,
+#endif
+ NULL);
+ g_object_set (G_OBJECT (priv->soup_session),
+ "user-agent", "libchamplain/" CHAMPLAIN_VERSION_S,
+ "max-conns-per-host", 2, NULL); // This is as required by OSM
+
+}
+
+ChamplainNetworkTileSource*
+champlain_network_tile_source_new_full (const gchar *id,
+ const gchar *name,
+ const gchar *license,
+ const gchar *license_uri,
+ guint min_zoom,
+ guint max_zoom,
+ guint tile_size,
+ ChamplainMapProjection projection,
+ const gchar *uri_format)
+{
+ ChamplainNetworkTileSource * source;
+ source = g_object_new (CHAMPLAIN_TYPE_NETWORK_TILE_SOURCE, "id", id,
+ "name", name, "license", license, "license-uri", license_uri,
+ "min-zoom-level", min_zoom, "max-zoom-level", max_zoom,
+ "tile-size", tile_size, "projection", projection,
+ "uri-format", uri_format, NULL);
+ return source;
+}
+
+const gchar *
+champlain_network_tile_source_get_uri_format (ChamplainNetworkTileSource *tile_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_NETWORK_TILE_SOURCE (tile_source), NULL);
+
+ ChamplainNetworkTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+ return priv->uri_format;
+}
+
+void
+champlain_network_tile_source_set_uri_format (ChamplainNetworkTileSource *tile_source,
+ const gchar *uri_format)
+{
+ g_return_if_fail (CHAMPLAIN_IS_NETWORK_TILE_SOURCE (tile_source));
+
+ ChamplainNetworkTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+
+ g_free (priv->uri_format);
+ priv->uri_format = g_strdup (uri_format);
+
+ g_object_notify (G_OBJECT (tile_source), "uri-format");
+}
+
+const gchar *
+champlain_network_tile_source_get_proxy_uri (ChamplainNetworkTileSource *tile_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_NETWORK_TILE_SOURCE (tile_source), NULL);
+
+ ChamplainNetworkTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+ return priv->proxy_uri;
+}
+
+void
+champlain_network_tile_source_set_proxy_uri (ChamplainNetworkTileSource *tile_source,
+ const gchar *proxy_uri)
+{
+ g_return_if_fail (CHAMPLAIN_IS_NETWORK_TILE_SOURCE (tile_source));
+
+ ChamplainNetworkTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+ SoupURI *uri = NULL;
+
+ g_free (priv->proxy_uri);
+ priv->proxy_uri = g_strdup (proxy_uri);
+
+ if (priv->proxy_uri)
+ uri = soup_uri_new (priv->proxy_uri);
+
+ if (priv->soup_session)
+ g_object_set (G_OBJECT (priv->soup_session),
+ "proxy-uri", uri,
+ NULL);
+
+ if (uri)
+ g_object_unref (uri);
+
+ g_object_notify (G_OBJECT (tile_source), "proxy-uri");
+}
+
+gboolean
+champlain_network_tile_source_get_offline (ChamplainNetworkTileSource *tile_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_NETWORK_TILE_SOURCE (tile_source), FALSE);
+
+ ChamplainNetworkTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+ return priv->offline;
+}
+
+void
+champlain_network_tile_source_set_offline (ChamplainNetworkTileSource *tile_source,
+ gboolean offline)
+{
+ g_return_if_fail (CHAMPLAIN_IS_NETWORK_TILE_SOURCE (tile_source));
+
+ ChamplainNetworkTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+
+ priv->offline = offline;
+
+ g_object_notify (G_OBJECT (tile_source), "offline");
+}
+
+#define SIZE 8
+static gchar *
+get_tile_uri (ChamplainNetworkTileSource *source,
+ gint x,
+ gint y,
+ gint z)
+{
+ ChamplainNetworkTileSourcePrivate *priv = GET_PRIVATE(source);
+
+ gchar **tokens;
+ gchar *token;
+ GString *ret;
+ gint i = 0;
+
+ tokens = g_strsplit (priv->uri_format, "#", 20);
+ token = tokens[i];
+ ret = g_string_sized_new (strlen (priv->uri_format));
+
+ while (token != NULL)
+ {
+ gint number = G_MAXINT;
+ gchar value[SIZE];
+
+ if (strcmp (token, "X") == 0)
+ number = x;
+ if (strcmp (token, "Y") == 0)
+ number = y;
+ if (strcmp (token, "Z") == 0)
+ number = z;
+
+ if (number != G_MAXINT)
+ {
+ g_snprintf (value, SIZE, "%d", number);
+ g_string_append (ret, value);
+ }
+ else
+ g_string_append (ret, token);
+
+ token = tokens[++i];
+ }
+
+ token = ret->str;
+ g_string_free (ret, FALSE);
+ g_strfreev (tokens);
+
+ return token;
+}
+
+static void
+tile_loaded_cb (SoupSession *session,
+ SoupMessage *msg,
+ gpointer user_data)
+{
+ TileLoadedCallbackData *callback_data = (TileLoadedCallbackData *)user_data;
+ ChamplainMapSource *map_source = callback_data->map_source;
+ ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE(map_source);
+ ChamplainTileCache *tile_cache = champlain_tile_source_get_cache(tile_source);
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
+ ChamplainTile *tile = callback_data->tile;
+ GdkPixbufLoader* loader;
+ GError *error = NULL;
+ ClutterActor *actor;
+ const gchar *etag;
+
+ g_free(user_data);
+
+ DEBUG ("Got reply %d", msg->status_code);
+
+ if (msg->status_code == SOUP_STATUS_CANCELLED)
+ {
+ DEBUG ("Download of tile %d, %d got cancelled",
+ champlain_tile_get_x (tile), champlain_tile_get_y (tile));
+ //champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
+
+ g_object_unref (tile);
+ g_object_unref (map_source);
+ return;
+ }
+
+ if (msg->status_code == SOUP_STATUS_NOT_MODIFIED)
+ {
+ if (tile_cache)
+ champlain_tile_cache_refresh_tile_time(tile_cache, tile);
+ goto finish;
+ }
+
+ if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ {
+ DEBUG ("Unable to download tile %d, %d: %s",
+ champlain_tile_get_x (tile),
+ champlain_tile_get_y (tile),
+ soup_status_get_phrase (msg->status_code));
+
+ goto load_next;
+ }
+
+ /* Load the data from the http response */
+ loader = gdk_pixbuf_loader_new();
+ if (!gdk_pixbuf_loader_write (loader,
+ (const guchar *) msg->response_body->data,
+ msg->response_body->length,
+ &error))
+ {
+ if (error)
+ {
+ g_warning ("Unable to load the pixbuf: %s", error->message);
+ g_error_free (error);
+ }
+
+ goto load_next_cleanup;
+ }
+
+ gdk_pixbuf_loader_close (loader, &error);
+ if (error)
+ {
+ g_warning ("Unable to close the pixbuf loader: %s", error->message);
+ g_error_free (error);
+ goto load_next_cleanup;
+ }
+
+ /* Verify if the server sent an etag and save it */
+ etag = soup_message_headers_get (msg->response_headers, "ETag");
+ DEBUG ("Received ETag %s", etag);
+
+ if (etag != NULL)
+ champlain_tile_set_etag (tile, etag);
+
+ if (tile_cache)
+ champlain_tile_cache_store_tile (tile_cache, tile, msg->response_body->data, msg->response_body->length);
+
+ /* Load the image into clutter */
+ GdkPixbuf* pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ actor = clutter_texture_new ();
+ if (!clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (actor),
+ gdk_pixbuf_get_pixels (pixbuf),
+ gdk_pixbuf_get_has_alpha (pixbuf),
+ gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf),
+ gdk_pixbuf_get_rowstride (pixbuf),
+ gdk_pixbuf_get_bits_per_sample (pixbuf) *
+ gdk_pixbuf_get_n_channels (pixbuf) / 8,
+ 0, &error))
+ {
+ if (error)
+ {
+ g_warning ("Unable to transfer to clutter: %s", error->message);
+ g_error_free (error);
+ }
+
+ g_object_unref (actor);
+ goto load_next_cleanup;
+ }
+
+ champlain_tile_set_content (tile, actor, TRUE);
+ champlain_tile_set_size (tile, champlain_map_source_get_tile_size (map_source));
+
+ goto finish;
+
+load_next_cleanup:
+ g_object_unref (loader);
+
+load_next:
+ if (next_source)
+ {
+ champlain_map_source_fill_tile(next_source, tile);
+ }
+ g_object_unref (tile);
+ g_object_unref (map_source);
+ return;
+
+finish:
+ champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
+ g_object_unref (tile);
+ g_object_unref (map_source);
+}
+
+static void
+fill_tile (ChamplainMapSource *map_source,
+ ChamplainTile *tile)
+{
+ g_return_if_fail (CHAMPLAIN_IS_NETWORK_TILE_SOURCE (map_source));
+ g_return_if_fail (CHAMPLAIN_IS_TILE (tile));
+
+ ChamplainNetworkTileSource *tile_source = CHAMPLAIN_NETWORK_TILE_SOURCE (map_source);
+ ChamplainNetworkTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+
+ if (!priv->offline)
+ {
+ TileLoadedCallbackData *callback_data;
+ SoupMessage *msg;
+ gchar *uri;
+
+ uri = get_tile_uri (tile_source,
+ champlain_tile_get_x (tile),
+ champlain_tile_get_y (tile),
+ champlain_tile_get_zoom_level (tile));
+
+ msg = soup_message_new (SOUP_METHOD_GET, uri);
+
+ if (champlain_tile_get_content (tile))
+ {
+ /* validate tile */
+
+ const gchar *etag = champlain_tile_get_etag (tile);
+ gchar *date = champlain_tile_get_modified_time_string (tile);
+
+ /* If an etag is available, only use it.
+ * OSM servers seems to send now as the modified time for all tiles
+ * Omarender servers set the modified time correctly
+ */
+ if (etag)
+ {
+ DEBUG("If-None-Match: %s", etag);
+ soup_message_headers_append (msg->request_headers,
+ "If-None-Match", etag);
+ }
+ else if (date)
+ {
+ DEBUG("If-Modified-Since %s", date);
+ soup_message_headers_append (msg->request_headers,
+ "If-Modified-Since", date);
+ }
+
+ g_free (date);
+ }
+
+ callback_data = g_new(TileLoadedCallbackData, 1);
+ callback_data->tile = tile;
+ callback_data->map_source = map_source;
+
+ /* Ref the tile as it may be freeing during the loading
+ * Unref when the loading is done.
+ */
+ g_object_ref (tile);
+ g_object_ref (map_source);
+
+ soup_session_queue_message (priv->soup_session, msg,
+ tile_loaded_cb,
+ callback_data);
+ }
+ else
+ {
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
+
+ if (CHAMPLAIN_IS_MAP_SOURCE(next_source))
+ champlain_map_source_fill_tile(next_source, tile);
+ }
+}
diff --git a/champlain/champlain-network-tile-source.h b/champlain/champlain-network-tile-source.h
new file mode 100644
index 0000000..bd7ba63
--- /dev/null
+++ b/champlain/champlain-network-tile-source.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2008-2009 Pierre-Luc Beaudoin <pierre-luc pierlux com>
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if !defined (__CHAMPLAIN_CHAMPLAIN_H_INSIDE__) && !defined (CHAMPLAIN_COMPILATION)
+#error "Only <champlain/champlain.h> can be included directly."
+#endif
+
+#ifndef _CHAMPLAIN_NETWORK_TILE_SOURCE_H_
+#define _CHAMPLAIN_NETWORK_TILE_SOURCE_H_
+
+#include <champlain/champlain-defines.h>
+#include <champlain/champlain-tile-source.h>
+
+G_BEGIN_DECLS
+
+#define CHAMPLAIN_TYPE_NETWORK_TILE_SOURCE (champlain_network_tile_source_get_type ())
+#define CHAMPLAIN_NETWORK_TILE_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CHAMPLAIN_TYPE_NETWORK_TILE_SOURCE, ChamplainNetworkTileSource))
+#define CHAMPLAIN_NETWORK_TILE_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CHAMPLAIN_TYPE_NETWORK_TILE_SOURCE, ChamplainNetworkTileSourceClass))
+#define CHAMPLAIN_IS_NETWORK_TILE_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CHAMPLAIN_TYPE_NETWORK_TILE_SOURCE))
+#define CHAMPLAIN_IS_NETWORK_TILE_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CHAMPLAIN_TYPE_NETWORK_TILE_SOURCE))
+#define CHAMPLAIN_NETWORK_TILE_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CHAMPLAIN_TYPE_NETWORK_TILE_SOURCE, ChamplainNetworkTileSourceClass))
+
+typedef struct _ChamplainNetworkTileSource ChamplainNetworkTileSource;
+typedef struct _ChamplainNetworkTileSourceClass ChamplainNetworkTileSourceClass;
+
+struct _ChamplainNetworkTileSource
+{
+ ChamplainTileSource parent_instance;
+};
+
+struct _ChamplainNetworkTileSourceClass
+{
+ ChamplainTileSourceClass parent_class;
+};
+
+GType champlain_network_tile_source_get_type (void);
+
+ChamplainNetworkTileSource* champlain_network_tile_source_new_full (const gchar *id,
+ const gchar *name,
+ const gchar *license,
+ const gchar *license_uri,
+ guint min_zoom,
+ guint max_zoom,
+ guint tile_size,
+ ChamplainMapProjection projection,
+ const gchar *uri_format);
+
+const gchar * champlain_network_tile_source_get_uri_format (ChamplainNetworkTileSource *source);
+void champlain_network_tile_source_set_uri_format (ChamplainNetworkTileSource *source,
+ const gchar *uri_format);
+
+gboolean champlain_network_tile_source_get_offline (ChamplainNetworkTileSource *source);
+void champlain_network_tile_source_set_offline (ChamplainNetworkTileSource *source,
+ gboolean offline);
+
+const gchar * champlain_network_tile_source_get_proxy_uri (ChamplainNetworkTileSource *source);
+void champlain_network_tile_source_set_proxy_uri (ChamplainNetworkTileSource *source,
+ const gchar *proxy_uri);
+
+G_END_DECLS
+
+#endif /* _CHAMPLAIN_NETWORK_TILE_SOURCE_H_ */
diff --git a/champlain/champlain-private.h b/champlain/champlain-private.h
index e42993e..7455fe7 100644
--- a/champlain/champlain-private.h
+++ b/champlain/champlain-private.h
@@ -21,7 +21,6 @@
#include <glib.h>
#include <clutter/clutter.h>
-#include "champlain-tile.h"
typedef struct _Map Map;
@@ -60,6 +59,4 @@ typedef struct
gint height;
} ChamplainRectangle;
-void create_error_tile (ChamplainTile* tile);
-
#endif
diff --git a/champlain/champlain-tile-cache.c b/champlain/champlain-tile-cache.c
new file mode 100644
index 0000000..5d5e43b
--- /dev/null
+++ b/champlain/champlain-tile-cache.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "champlain-tile-cache.h"
+
+G_DEFINE_TYPE (ChamplainTileCache, champlain_tile_cache, CHAMPLAIN_TYPE_MAP_SOURCE);
+
+#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHAMPLAIN_TYPE_TILE_CACHE, ChamplainTileCachePrivate))
+
+enum
+{
+ PROP_0,
+ PROP_PERSISTENT_CACHE
+};
+
+typedef struct _ChamplainTileCachePrivate ChamplainTileCachePrivate;
+
+struct _ChamplainTileCachePrivate
+{
+ gboolean persistent;
+};
+
+static const gchar *get_id (ChamplainMapSource *map_source);
+static const gchar *get_name (ChamplainMapSource *map_source);
+static const gchar *get_license (ChamplainMapSource *map_source);
+static const gchar *get_license_uri (ChamplainMapSource *map_source);
+static guint get_min_zoom_level (ChamplainMapSource *map_source);
+static guint get_max_zoom_level (ChamplainMapSource *map_source);
+static guint get_tile_size (ChamplainMapSource *map_source);
+
+static void
+champlain_tile_cache_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ChamplainTileCache *tile_cache = CHAMPLAIN_TILE_CACHE (object);
+
+ switch (property_id)
+ {
+ case PROP_PERSISTENT_CACHE:
+ g_value_set_boolean (value, champlain_tile_cache_get_persistent (tile_cache));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+champlain_tile_cache_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ChamplainTileCachePrivate *priv = GET_PRIVATE (object);
+
+ switch (property_id)
+ {
+ case PROP_PERSISTENT_CACHE:
+ priv->persistent = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+champlain_tile_cache_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (champlain_tile_cache_parent_class)->dispose (object);
+}
+
+static void
+champlain_tile_cache_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (champlain_tile_cache_parent_class)->finalize (object);
+}
+
+static void
+champlain_tile_cache_constructed (GObject *object)
+{
+ G_OBJECT_CLASS (champlain_tile_cache_parent_class)->constructed (object);
+}
+
+static void
+champlain_tile_cache_class_init (ChamplainTileCacheClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ ChamplainMapSourceClass *map_source_class = CHAMPLAIN_MAP_SOURCE_CLASS (klass);
+ ChamplainTileCacheClass *tile_cache_class = CHAMPLAIN_TILE_CACHE_CLASS (klass);
+ GParamSpec *pspec;
+
+ g_type_class_add_private (klass, sizeof (ChamplainTileCachePrivate));
+
+ object_class->finalize = champlain_tile_cache_finalize;
+ object_class->dispose = champlain_tile_cache_dispose;
+ object_class->get_property = champlain_tile_cache_get_property;
+ object_class->set_property = champlain_tile_cache_set_property;
+ object_class->constructed = champlain_tile_cache_constructed;
+
+ map_source_class->get_id = get_id;
+ map_source_class->get_name = get_name;
+ map_source_class->get_license = get_license;
+ map_source_class->get_license_uri = get_license_uri;
+ map_source_class->get_min_zoom_level = get_min_zoom_level;
+ map_source_class->get_max_zoom_level = get_max_zoom_level;
+ map_source_class->get_tile_size = get_tile_size;
+
+ map_source_class->fill_tile = NULL;
+
+ tile_cache_class->refresh_tile_time = NULL;
+ tile_cache_class->on_tile_filled = NULL;
+ tile_cache_class->store_tile = NULL;
+ tile_cache_class->clean = NULL;
+
+ pspec = g_param_spec_boolean ("persistent-cache",
+ "Persistent Cache",
+ "Specifies whether the cache is persistent",
+ FALSE,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_PERSISTENT_CACHE, pspec);
+}
+
+static void
+champlain_tile_cache_init (ChamplainTileCache *tile_cache)
+{
+ ChamplainTileCachePrivate *priv = GET_PRIVATE (tile_cache);
+
+ priv->persistent = FALSE;
+}
+
+gboolean
+champlain_tile_cache_get_persistent (ChamplainTileCache *tile_cache)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_CACHE (tile_cache), FALSE);
+
+ ChamplainTileCachePrivate *priv = GET_PRIVATE(tile_cache);
+ return priv->persistent;
+}
+
+void
+champlain_tile_cache_store_tile (ChamplainTileCache *tile_cache,
+ ChamplainTile *tile,
+ const gchar *contents,
+ gsize size)
+{
+ g_return_if_fail (CHAMPLAIN_IS_TILE_CACHE (tile_cache));
+
+ return CHAMPLAIN_TILE_CACHE_GET_CLASS (tile_cache)->store_tile (tile_cache, tile, contents, size);
+}
+
+void
+champlain_tile_cache_refresh_tile_time (ChamplainTileCache *tile_cache, ChamplainTile *tile)
+{
+ g_return_if_fail (CHAMPLAIN_IS_TILE_CACHE (tile_cache));
+
+ return CHAMPLAIN_TILE_CACHE_GET_CLASS (tile_cache)->refresh_tile_time (tile_cache, tile);
+}
+
+void
+champlain_tile_cache_on_tile_filled (ChamplainTileCache *tile_cache, ChamplainTile *tile)
+{
+ g_return_if_fail (CHAMPLAIN_IS_TILE_CACHE (tile_cache));
+
+ return CHAMPLAIN_TILE_CACHE_GET_CLASS (tile_cache)->on_tile_filled (tile_cache, tile);
+}
+
+void
+champlain_tile_cache_clean (ChamplainTileCache *tile_cache)
+{
+ g_return_if_fail (CHAMPLAIN_IS_TILE_CACHE (tile_cache));
+
+ return CHAMPLAIN_TILE_CACHE_GET_CLASS (tile_cache)->clean (tile_cache);
+}
+
+static const gchar *
+get_id (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_CACHE (map_source), NULL);
+
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
+
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (next_source), NULL);
+
+ return champlain_map_source_get_id(next_source);
+}
+
+static const gchar *
+get_name (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_CACHE (map_source), NULL);
+
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
+
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (next_source), NULL);
+
+ return champlain_map_source_get_name(next_source);
+}
+
+static const gchar *
+get_license (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_CACHE (map_source), NULL);
+
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
+
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (next_source), NULL);
+
+ return champlain_map_source_get_license(next_source);
+}
+
+static const gchar *
+get_license_uri (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_CACHE (map_source), NULL);
+
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
+
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (next_source), NULL);
+
+ return champlain_map_source_get_license_uri(next_source);
+}
+
+static guint
+get_min_zoom_level (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_CACHE (map_source), 0);
+
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
+
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (next_source), 0);
+
+ return champlain_map_source_get_min_zoom_level(next_source);
+}
+
+static guint
+get_max_zoom_level (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_CACHE (map_source), 0);
+
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
+
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (next_source), 0);
+
+ return champlain_map_source_get_max_zoom_level(next_source);
+}
+
+static guint
+get_tile_size (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_CACHE (map_source), 0);
+
+ ChamplainMapSource *next_source = champlain_map_source_get_next_source(map_source);
+
+ g_return_val_if_fail (CHAMPLAIN_IS_MAP_SOURCE (next_source), 0);
+
+ return champlain_map_source_get_tile_size(next_source);
+}
diff --git a/champlain/champlain-tile-cache.h b/champlain/champlain-tile-cache.h
new file mode 100644
index 0000000..de2530c
--- /dev/null
+++ b/champlain/champlain-tile-cache.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if !defined (__CHAMPLAIN_CHAMPLAIN_H_INSIDE__) && !defined (CHAMPLAIN_COMPILATION)
+#error "Only <champlain/champlain.h> can be included directly."
+#endif
+
+#ifndef _CHAMPLAIN_TILE_CACHE_H_
+#define _CHAMPLAIN_TILE_CACHE_H_
+
+#include <champlain/champlain-defines.h>
+#include <champlain/champlain-map-source.h>
+
+G_BEGIN_DECLS
+
+#define CHAMPLAIN_TYPE_TILE_CACHE (champlain_tile_cache_get_type ())
+#define CHAMPLAIN_TILE_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CHAMPLAIN_TYPE_TILE_CACHE, ChamplainTileCache))
+#define CHAMPLAIN_TILE_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CHAMPLAIN_TYPE_TILE_CACHE, ChamplainTileCacheClass))
+#define CHAMPLAIN_IS_TILE_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CHAMPLAIN_TYPE_TILE_CACHE))
+#define CHAMPLAIN_IS_TILE_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CHAMPLAIN_TYPE_TILE_CACHE))
+#define CHAMPLAIN_TILE_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CHAMPLAIN_TYPE_TILE_CACHE, ChamplainTileCacheClass))
+
+typedef struct _ChamplainTileCache ChamplainTileCache;
+typedef struct _ChamplainTileCacheClass ChamplainTileCacheClass;
+
+struct _ChamplainTileCache
+{
+ ChamplainMapSource parent_instance;
+};
+
+struct _ChamplainTileCacheClass
+{
+ ChamplainMapSourceClass parent_class;
+
+ void (*store_tile) (ChamplainTileCache *tile_cache,
+ ChamplainTile *tile,
+ const gchar *contents,
+ gsize size);
+ void (*refresh_tile_time) (ChamplainTileCache *tile_cache, ChamplainTile *tile);
+ void (*on_tile_filled) (ChamplainTileCache *tile_cache, ChamplainTile *tile);
+ void (*clean) (ChamplainTileCache *tile_cache);
+};
+
+GType champlain_tile_cache_get_type (void);
+
+gboolean champlain_tile_cache_get_persistent (ChamplainTileCache *tile_cache);
+
+void champlain_tile_cache_store_tile (ChamplainTileCache *tile_cache,
+ ChamplainTile *tile,
+ const gchar *contents,
+ gsize size);
+void champlain_tile_cache_refresh_tile_time (ChamplainTileCache *tile_cache, ChamplainTile *tile);
+void champlain_tile_cache_on_tile_filled (ChamplainTileCache *tile_cache, ChamplainTile *tile);
+void champlain_tile_cache_clean (ChamplainTileCache *tile_cache);
+
+G_END_DECLS
+
+#endif /* _CHAMPLAIN_TILE_CACHE_H_ */
+
diff --git a/champlain/champlain-tile-source.c b/champlain/champlain-tile-source.c
new file mode 100644
index 0000000..7a04dce
--- /dev/null
+++ b/champlain/champlain-tile-source.c
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) 2008-2009 Pierre-Luc Beaudoin <pierre-luc pierlux com>
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "champlain-tile-source.h"
+#include "champlain-enum-types.h"
+
+G_DEFINE_TYPE (ChamplainTileSource, champlain_tile_source, CHAMPLAIN_TYPE_MAP_SOURCE);
+
+#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHAMPLAIN_TYPE_TILE_SOURCE, ChamplainTileSourcePrivate))
+
+enum
+{
+ PROP_0,
+ PROP_ID,
+ PROP_NAME,
+ PROP_LICENSE,
+ PROP_LICENSE_URI,
+ PROP_MIN_ZOOM_LEVEL,
+ PROP_MAX_ZOOM_LEVEL,
+ PROP_TILE_SIZE,
+ PROP_MAP_PROJECTION,
+ PROP_CACHE
+};
+
+typedef struct _ChamplainTileSourcePrivate ChamplainTileSourcePrivate;
+
+struct _ChamplainTileSourcePrivate
+{
+ gchar *id;
+ gchar *name;
+ gchar *license;
+ gchar *license_uri;
+ guint min_zoom_level;
+ guint max_zoom_level;
+ guint tile_size;
+ ChamplainMapProjection map_projection;
+ ChamplainTileCache *cache;
+};
+
+static const gchar *get_id (ChamplainMapSource *map_source);
+static const gchar *get_name (ChamplainMapSource *map_source);
+static const gchar *get_license (ChamplainMapSource *map_source);
+static const gchar *get_license_uri (ChamplainMapSource *map_source);
+static guint get_min_zoom_level (ChamplainMapSource *map_source);
+static guint get_max_zoom_level (ChamplainMapSource *map_source);
+static guint get_tile_size (ChamplainMapSource *map_source);
+
+static void
+champlain_tile_source_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(object);
+
+ 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_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_MAP_PROJECTION:
+ g_value_set_enum (value, priv->map_projection);
+ break;
+ case PROP_CACHE:
+ g_value_set_object (value, priv->cache);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+champlain_tile_source_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ChamplainTileSource *tile_source = CHAMPLAIN_TILE_SOURCE(object);
+
+ switch(prop_id)
+ {
+ case PROP_ID:
+ champlain_tile_source_set_id (tile_source,
+ g_value_get_string (value));
+ case PROP_NAME:
+ champlain_tile_source_set_name (tile_source,
+ g_value_get_string (value));
+ break;
+ case PROP_LICENSE:
+ champlain_tile_source_set_license (tile_source,
+ g_value_get_string (value));
+ break;
+ case PROP_LICENSE_URI:
+ champlain_tile_source_set_license_uri (tile_source,
+ g_value_get_string (value));
+ break;
+ case PROP_MIN_ZOOM_LEVEL:
+ champlain_tile_source_set_min_zoom_level (tile_source,
+ g_value_get_uint (value));
+ break;
+ case PROP_MAX_ZOOM_LEVEL:
+ champlain_tile_source_set_max_zoom_level (tile_source,
+ g_value_get_uint (value));
+ break;
+ case PROP_TILE_SIZE:
+ champlain_tile_source_set_tile_size (tile_source,
+ g_value_get_uint (value));
+ break;
+ case PROP_MAP_PROJECTION:
+ champlain_tile_source_set_projection (tile_source,
+ g_value_get_enum (value));
+ break;
+ case PROP_CACHE:
+ champlain_tile_source_set_cache (tile_source,
+ g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+champlain_tile_source_dispose (GObject *object)
+{
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(object);
+
+ if (priv->cache)
+ {
+ g_object_unref (priv->cache);
+
+ priv->cache = NULL;
+ }
+
+ G_OBJECT_CLASS (champlain_tile_source_parent_class)->dispose (object);
+}
+
+static void
+champlain_tile_source_finalize (GObject *object)
+{
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(object);
+
+ g_free (priv->id);
+ g_free (priv->name);
+ g_free (priv->license);
+ g_free (priv->license_uri);
+
+ G_OBJECT_CLASS (champlain_tile_source_parent_class)->finalize (object);
+}
+
+static void
+champlain_tile_source_constructed (GObject *object)
+{
+ G_OBJECT_CLASS (champlain_tile_source_parent_class)->constructed (object);
+}
+
+static void
+champlain_tile_source_class_init (ChamplainTileSourceClass *klass)
+{
+ ChamplainMapSourceClass *map_source_class = CHAMPLAIN_MAP_SOURCE_CLASS (klass);
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ GParamSpec *pspec;
+
+ g_type_class_add_private (klass, sizeof (ChamplainTileSourcePrivate));
+
+ object_class->finalize = champlain_tile_source_finalize;
+ object_class->dispose = champlain_tile_source_dispose;
+ object_class->get_property = champlain_tile_source_get_property;
+ object_class->set_property = champlain_tile_source_set_property;
+ object_class->constructed = champlain_tile_source_constructed;
+
+ map_source_class->get_id = get_id;
+ map_source_class->get_name = get_name;
+ map_source_class->get_license = get_license;
+ map_source_class->get_license_uri = get_license_uri;
+ map_source_class->get_min_zoom_level = get_min_zoom_level;
+ map_source_class->get_max_zoom_level = get_max_zoom_level;
+ map_source_class->get_tile_size = get_tile_size;
+
+ map_source_class->fill_tile = NULL;
+
+ pspec = g_param_spec_string ("id",
+ "Id",
+ "The id of the tile source",
+ "",
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class, PROP_ID, pspec);
+
+ pspec = g_param_spec_string ("name",
+ "Name",
+ "The name of the tile source",
+ "",
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class, PROP_NAME, pspec);
+
+ pspec = g_param_spec_string ("license",
+ "License",
+ "The usage license of the tile source",
+ "",
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class, PROP_LICENSE, pspec);
+
+ pspec = g_param_spec_string ("license-uri",
+ "License-uri",
+ "The usage license's uri for more information",
+ "",
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class, PROP_LICENSE_URI, pspec);
+
+ pspec = g_param_spec_uint ("min-zoom-level",
+ "Minimum Zoom Level",
+ "The minimum zoom level",
+ 0,
+ 50,
+ 0,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class, PROP_MIN_ZOOM_LEVEL, pspec);
+
+ pspec = g_param_spec_uint ("max-zoom-level",
+ "Maximum Zoom Level",
+ "The maximum zoom level",
+ 0,
+ 50,
+ 18,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class, PROP_MAX_ZOOM_LEVEL, pspec);
+
+ pspec = g_param_spec_uint ("tile-size",
+ "Tile Size",
+ "The tile size",
+ 0,
+ 2048,
+ 256,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class, PROP_TILE_SIZE, pspec);
+
+ pspec = g_param_spec_enum ("projection",
+ "Projection",
+ "The map projection",
+ CHAMPLAIN_TYPE_MAP_PROJECTION,
+ CHAMPLAIN_MAP_PROJECTION_MERCATOR,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class, PROP_MAP_PROJECTION, pspec);
+
+ pspec = g_param_spec_object ("cache",
+ "Cache",
+ "Cache used for tile sorage",
+ CHAMPLAIN_TYPE_TILE_CACHE,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_CACHE, pspec);
+}
+
+static void
+champlain_tile_source_init (ChamplainTileSource *tile_source)
+{
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+ priv->cache = NULL;
+ priv->id = NULL;
+ priv->name = NULL;
+ priv->license = NULL;
+ priv->license_uri = NULL;
+ priv->min_zoom_level = 0;
+ priv->max_zoom_level = 0;
+ priv->tile_size = 0;
+ priv->map_projection = CHAMPLAIN_MAP_PROJECTION_MERCATOR;
+}
+
+ChamplainMapProjection
+champlain_tile_source_get_projection (ChamplainTileSource *tile_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_SOURCE (tile_source), 0);
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+ return priv->map_projection;
+}
+
+ChamplainTileCache *
+champlain_tile_source_get_cache (ChamplainTileSource *tile_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_SOURCE (tile_source), NULL);
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+ return priv->cache;
+}
+
+void
+champlain_tile_source_set_projection (ChamplainTileSource *tile_source,
+ ChamplainMapProjection projection)
+{
+ g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE (tile_source));
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+
+ priv->map_projection = projection;
+ g_object_notify (G_OBJECT (tile_source), "projection");
+}
+
+void
+champlain_tile_source_set_cache (ChamplainTileSource *tile_source,
+ ChamplainTileCache *cache)
+{
+ g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE (tile_source));
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+
+ if (priv->cache != NULL)
+ g_object_unref(priv->cache);
+
+ if (cache)
+ {
+ g_return_if_fail (CHAMPLAIN_IS_TILE_CACHE (cache));
+
+ g_object_ref_sink(cache);
+ }
+
+ priv->cache = cache;
+
+ g_object_notify (G_OBJECT (tile_source), "cache");
+}
+
+static const gchar *
+get_id (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_SOURCE (map_source), NULL);
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(map_source);
+ return priv->id;
+}
+
+static const gchar *
+get_name (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_SOURCE (map_source), NULL);
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(map_source);
+ return priv->name;
+}
+
+static const gchar *
+get_license (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_SOURCE (map_source), NULL);
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(map_source);
+ return priv->license;
+}
+
+static const gchar *
+get_license_uri (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_SOURCE (map_source), NULL);
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(map_source);
+ return priv->license_uri;
+}
+
+static guint
+get_min_zoom_level (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_SOURCE (map_source), 0);
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(map_source);
+ return priv->min_zoom_level;
+}
+
+static guint
+get_max_zoom_level (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_SOURCE (map_source), 0);
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(map_source);
+ return priv->max_zoom_level;
+}
+
+static guint
+get_tile_size (ChamplainMapSource *map_source)
+{
+ g_return_val_if_fail (CHAMPLAIN_IS_TILE_SOURCE (map_source), 0);
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(map_source);
+ return priv->tile_size;
+}
+
+void
+champlain_tile_source_set_id (ChamplainTileSource *tile_source,
+ const gchar *id)
+{
+ g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE (tile_source));
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+
+ g_free (priv->id);
+ priv->id = g_strdup (id);
+
+ g_object_notify (G_OBJECT (tile_source), "id");
+}
+
+void
+champlain_tile_source_set_name (ChamplainTileSource *tile_source,
+ const gchar *name)
+{
+ g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE (tile_source));
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+
+ g_free (priv->name);
+ priv->name = g_strdup (name);
+
+ g_object_notify (G_OBJECT (tile_source), "name");
+}
+
+void
+champlain_tile_source_set_license (ChamplainTileSource *tile_source,
+ const gchar *license)
+{
+ g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE (tile_source));
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+
+ g_free (priv->license);
+ priv->license = g_strdup (license);
+
+ g_object_notify (G_OBJECT (tile_source), "license");
+}
+
+void
+champlain_tile_source_set_license_uri (ChamplainTileSource *tile_source,
+ const gchar *license_uri)
+{
+ g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE (tile_source));
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+
+ g_free (priv->license_uri);
+ priv->license_uri = g_strdup (license_uri);
+
+ g_object_notify (G_OBJECT (tile_source), "license-uri");
+}
+
+void
+champlain_tile_source_set_min_zoom_level (ChamplainTileSource *tile_source,
+ guint zoom_level)
+{
+ g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE (tile_source));
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+
+ priv->min_zoom_level = zoom_level;
+
+ g_object_notify (G_OBJECT (tile_source), "min-zoom-level");
+}
+
+void
+champlain_tile_source_set_max_zoom_level (ChamplainTileSource *tile_source,
+ guint zoom_level)
+{
+ g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE (tile_source));
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+
+ priv->max_zoom_level = zoom_level;
+
+ g_object_notify (G_OBJECT (tile_source), "max-zoom-level");
+}
+
+void
+champlain_tile_source_set_tile_size (ChamplainTileSource *tile_source,
+ guint tile_size)
+{
+ g_return_if_fail (CHAMPLAIN_IS_TILE_SOURCE (tile_source));
+
+ ChamplainTileSourcePrivate *priv = GET_PRIVATE(tile_source);
+
+ priv->tile_size = tile_size;
+
+ g_object_notify (G_OBJECT (tile_source), "tile-size");
+}
diff --git a/champlain/champlain-tile-source.h b/champlain/champlain-tile-source.h
new file mode 100644
index 0000000..7e6fcc2
--- /dev/null
+++ b/champlain/champlain-tile-source.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2008-2009 Pierre-Luc Beaudoin <pierre-luc pierlux com>
+ * Copyright (C) 2010 Jiri Techet <techet gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if !defined (__CHAMPLAIN_CHAMPLAIN_H_INSIDE__) && !defined (CHAMPLAIN_COMPILATION)
+#error "Only <champlain/champlain.h> can be included directly."
+#endif
+
+#ifndef _CHAMPLAIN_TILE_SOURCE_H_
+#define _CHAMPLAIN_TILE_SOURCE_H_
+
+#include <champlain/champlain-defines.h>
+#include <champlain/champlain-map-source.h>
+#include <champlain/champlain-tile-cache.h>
+
+G_BEGIN_DECLS
+
+#define CHAMPLAIN_TYPE_TILE_SOURCE (champlain_tile_source_get_type ())
+#define CHAMPLAIN_TILE_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CHAMPLAIN_TYPE_TILE_SOURCE, ChamplainTileSource))
+#define CHAMPLAIN_TILE_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CHAMPLAIN_TYPE_TILE_SOURCE, ChamplainTileSourceClass))
+#define CHAMPLAIN_IS_TILE_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CHAMPLAIN_TYPE_TILE_SOURCE))
+#define CHAMPLAIN_IS_TILE_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CHAMPLAIN_TYPE_TILE_SOURCE))
+#define CHAMPLAIN_TILE_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CHAMPLAIN_TYPE_TILE_SOURCE, ChamplainTileSourceClass))
+
+typedef struct _ChamplainTileSource ChamplainTileSource;
+typedef struct _ChamplainTileSourceClass ChamplainTileSourceClass;
+
+typedef enum
+{
+ CHAMPLAIN_MAP_PROJECTION_MERCATOR
+} ChamplainMapProjection;
+
+struct _ChamplainTileSource
+{
+ ChamplainMapSource parent_instance;
+};
+
+struct _ChamplainTileSourceClass
+{
+ ChamplainMapSourceClass parent_class;
+};
+
+GType champlain_tile_source_get_type (void);
+
+ChamplainMapProjection champlain_tile_source_get_projection (ChamplainTileSource *tile_source);
+void champlain_tile_source_set_projection (ChamplainTileSource *tile_source,
+ ChamplainMapProjection projection);
+
+ChamplainTileCache *champlain_tile_source_get_cache (ChamplainTileSource *tile_source);
+void champlain_tile_source_set_cache (ChamplainTileSource *tile_source,
+ ChamplainTileCache *cache);
+
+void champlain_tile_source_set_id (ChamplainTileSource *tile_source,
+ const gchar *id);
+void champlain_tile_source_set_name (ChamplainTileSource *tile_source,
+ const gchar *name);
+void champlain_tile_source_set_license (ChamplainTileSource *tile_source,
+ const gchar *license);
+void champlain_tile_source_set_license_uri (ChamplainTileSource *tile_source,
+ const gchar *license_uri);
+
+void champlain_tile_source_set_min_zoom_level (ChamplainTileSource *tile_source,
+ guint zoom_level);
+void champlain_tile_source_set_max_zoom_level (ChamplainTileSource *tile_source,
+ guint zoom_level);
+void champlain_tile_source_set_tile_size (ChamplainTileSource *tile_source,
+ guint zoom_level);
+
+G_END_DECLS
+
+#endif /* _CHAMPLAIN_TILE_SOURCE_H_ */
diff --git a/champlain/champlain-tile.c b/champlain/champlain-tile.c
index faad92d..4227373 100644
--- a/champlain/champlain-tile.c
+++ b/champlain/champlain-tile.c
@@ -47,8 +47,6 @@ enum
PROP_Y,
PROP_ZOOM_LEVEL,
PROP_SIZE,
- PROP_URI,
- PROP_FILENAME,
PROP_STATE,
PROP_ACTOR,
PROP_CONTENT,
@@ -61,9 +59,7 @@ struct _ChamplainTilePrivate {
gint size; /* The tile's width and height (only support square tiles */
gint zoom_level; /* The tile's zoom level */
- gchar *uri; /* The URI where to find the tile */
ChamplainState state; /* The tile state: loading, validation, done */
- gchar *filename; /* The tile's cache filename */
ClutterActor *actor; /* An actor grouping all content actors */
ClutterActor *content_actor; /* The actual tile actor */
@@ -95,12 +91,6 @@ champlain_tile_get_property (GObject *object,
case PROP_STATE:
g_value_set_enum (value, champlain_tile_get_state (self));
break;
- case PROP_URI:
- g_value_set_string (value, champlain_tile_get_uri (self));
- break;
- case PROP_FILENAME:
- g_value_set_string (value, champlain_tile_get_filename (self));
- break;
case PROP_ACTOR:
g_value_set_object (value, champlain_tile_get_actor (self));
break;
@@ -139,12 +129,6 @@ champlain_tile_set_property (GObject *object,
case PROP_STATE:
champlain_tile_set_state (self, g_value_get_enum (value));
break;
- case PROP_URI:
- champlain_tile_set_uri (self, g_value_get_string (value));
- break;
- case PROP_FILENAME:
- champlain_tile_set_filename (self, g_value_get_string (value));
- break;
case PROP_CONTENT:
champlain_tile_set_content (self, g_value_get_object (value), FALSE);
break;
@@ -176,13 +160,13 @@ champlain_tile_dispose (GObject *object)
G_OBJECT_CLASS (champlain_tile_parent_class)->dispose (object);
}
+
+
static void
champlain_tile_finalize (GObject *object)
{
ChamplainTilePrivate *priv = CHAMPLAIN_TILE (object)->priv;
- g_free (priv->uri);
- g_free (priv->filename);
g_free (priv->modified_time);
g_free (priv->etag);
@@ -286,36 +270,6 @@ champlain_tile_class_init (ChamplainTileClass *klass)
G_PARAM_READWRITE));
/**
- * ChamplainTile:uri:
- *
- * The remote uri of the tile
- *
- * Since: 0.4
- */
- g_object_class_install_property (object_class,
- PROP_URI,
- g_param_spec_string ("uri",
- "URI",
- "The URI of the tile",
- "",
- G_PARAM_READWRITE));
-
- /**
- * ChamplainTile:filename:
- *
- * The local path of the cached tile
- *
- * Since: 0.4
- */
- g_object_class_install_property (object_class,
- PROP_FILENAME,
- g_param_spec_string ("filename",
- "Filename",
- "The filename of the tile",
- "",
- G_PARAM_READWRITE));
-
- /**
* ChamplainTile:actor:
*
* The #ClutterActor where the tile content is rendered. Should never change
@@ -377,8 +331,6 @@ champlain_tile_init (ChamplainTile *self)
priv->y = 0;
priv->zoom_level = 0;
priv->size = 0;
- priv->uri = NULL;
- priv->filename = NULL;
priv->modified_time = NULL;
priv->etag = NULL;
@@ -482,38 +434,6 @@ champlain_tile_get_state (ChamplainTile *self)
}
/**
- * champlain_tile_get_uri:
- * @self: the #ChamplainTile
- *
- * Returns: the tile's remote uri
- *
- * Since: 0.4
- */
-G_CONST_RETURN gchar *
-champlain_tile_get_uri (ChamplainTile *self)
-{
- g_return_val_if_fail (CHAMPLAIN_TILE (self), NULL);
-
- return self->priv->uri;
-}
-
-/**
- * champlain_tile_get_filename:
- * @self: the #ChamplainTile
- *
- * Returns: the tile's local filename
- *
- * Since: 0.4
- */
-G_CONST_RETURN gchar *
-champlain_tile_get_filename (ChamplainTile *self)
-{
- g_return_val_if_fail (CHAMPLAIN_TILE (self), NULL);
-
- return self->priv->filename;
-}
-
-/**
* champlain_tile_get_actor:
* @self: the #ChamplainTile
*
@@ -652,54 +572,6 @@ champlain_tile_new_full (gint x,
}
/**
- * champlain_tile_set_uri:
- * @self: the #ChamplainTile
- * @uri: the uri
- *
- * Sets the tile's uri
- *
- * Since: 0.4
- */
-void
-champlain_tile_set_uri (ChamplainTile *self,
- const gchar *uri)
-{
- g_return_if_fail (CHAMPLAIN_TILE (self));
- g_return_if_fail (uri != NULL);
-
- ChamplainTilePrivate *priv = self->priv;
-
- g_free (priv->uri);
- priv->uri = g_strdup (uri);
-
- g_object_notify (G_OBJECT (self), "uri");
-}
-
-/**
- * champlain_tile_set_filename:
- * @self: the #ChamplainTile
- * @filename: a local path to an image
- *
- * Sets the tile's filename
- *
- * Since: 0.4
- */
-void
-champlain_tile_set_filename (ChamplainTile *self,
- const gchar *filename)
-{
- g_return_if_fail (CHAMPLAIN_TILE (self));
- g_return_if_fail (filename != NULL);
-
- ChamplainTilePrivate *priv = self->priv;
-
- g_free (priv->filename);
- priv->filename = g_strdup (filename);
-
- g_object_notify (G_OBJECT (self), "filename");
-}
-
-/**
* champlain_tile_get_modified_time:
* @self: the #ChamplainTile
*
diff --git a/champlain/champlain-tile.h b/champlain/champlain-tile.h
index 0ed5941..8451f64 100644
--- a/champlain/champlain-tile.h
+++ b/champlain/champlain-tile.h
@@ -71,8 +71,6 @@ gint champlain_tile_get_y (ChamplainTile *self);
gint champlain_tile_get_zoom_level (ChamplainTile *self);
guint champlain_tile_get_size (ChamplainTile *self);
ChamplainState champlain_tile_get_state (ChamplainTile *self);
-G_CONST_RETURN gchar * champlain_tile_get_uri (ChamplainTile *self);
-G_CONST_RETURN gchar * champlain_tile_get_filename (ChamplainTile *self);
ClutterActor * champlain_tile_get_actor (ChamplainTile *self);
ClutterActor * champlain_tile_get_content (ChamplainTile *self);
const GTimeVal * champlain_tile_get_modified_time (ChamplainTile *self);
@@ -88,10 +86,6 @@ void champlain_tile_set_size (ChamplainTile *self,
guint size);
void champlain_tile_set_state (ChamplainTile *self,
ChamplainState state);
-void champlain_tile_set_uri (ChamplainTile *self,
- const gchar *uri);
-void champlain_tile_set_filename (ChamplainTile *self,
- const gchar *filename);
void champlain_tile_set_content (ChamplainTile *self,
ClutterActor* actor,
gboolean fade_in);
diff --git a/champlain/champlain-view.c b/champlain/champlain-view.c
index 7b949dc..29f7b10 100644
--- a/champlain/champlain-view.c
+++ b/champlain/champlain-view.c
@@ -610,7 +610,7 @@ champlain_view_get_property (GObject *object,
CLAMP (priv->longitude, CHAMPLAIN_MIN_LONG, CHAMPLAIN_MAX_LONG));
break;
case PROP_LATITUDE:
- g_value_set_double (value,
+ g_value_set_double (value,
CLAMP (priv->latitude, CHAMPLAIN_MIN_LAT, CHAMPLAIN_MAX_LAT));
break;
case PROP_ZOOM_LEVEL:
@@ -1286,13 +1286,35 @@ static void
champlain_view_init (ChamplainView *view)
{
ChamplainViewPrivate *priv = GET_PRIVATE (view);
+ ChamplainMapSourceChain *source_chain;
+ ChamplainMapSource *source;
+ ChamplainMapSource *src;
+ guint tile_size;
+ gchar *cache_path;
champlain_debug_set_flags (g_getenv ("CHAMPLAIN_DEBUG"));
view->priv = priv;
priv->factory = champlain_map_source_factory_dup_default ();
- priv->map_source = champlain_map_source_factory_create (priv->factory, CHAMPLAIN_MAP_SOURCE_OSM_MAPNIK);
+ source = champlain_map_source_factory_create (priv->factory, CHAMPLAIN_MAP_SOURCE_OSM_MAPNIK);
+
+ source_chain = champlain_map_source_chain_new ();
+
+ tile_size = champlain_map_source_get_tile_size(source);
+ src = CHAMPLAIN_MAP_SOURCE(champlain_error_tile_source_new_full (tile_size));
+
+ champlain_map_source_chain_push_map_source(source_chain, src);
+ champlain_map_source_chain_push_map_source(source_chain, source);
+
+ cache_path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_cache_dir (), "champlain", NULL);
+ src = CHAMPLAIN_MAP_SOURCE(champlain_file_cache_new_full (100000000, cache_path, TRUE));
+ g_free(cache_path);
+
+ champlain_map_source_chain_push_map_source(source_chain, src);
+
+ priv->map_source = CHAMPLAIN_MAP_SOURCE(source_chain);
+
priv->zoom_level = 0;
priv->min_zoom_level = champlain_map_source_get_min_zoom_level (priv->map_source);
priv->max_zoom_level = champlain_map_source_get_max_zoom_level (priv->map_source);
@@ -2304,6 +2326,7 @@ view_load_visible_tiles (ChamplainView *view)
champlain_tile_get_actor (tile), NULL);
champlain_zoom_level_add_tile (level, tile);
+ champlain_tile_set_state (tile, CHAMPLAIN_STATE_LOADING);
champlain_map_source_fill_tile (priv->map_source, tile);
g_object_unref (tile);
@@ -2405,8 +2428,7 @@ view_reload_tiles_cb (ChamplainMapSource *map_source,
if (tile == NULL)
continue;
- if (champlain_tile_get_state (tile) != CHAMPLAIN_STATE_LOADING &&
- champlain_tile_get_state (tile) != CHAMPLAIN_STATE_VALIDATING_CACHE)
+ if (champlain_tile_get_state (tile) != CHAMPLAIN_STATE_LOADING)
champlain_map_source_fill_tile (priv->map_source, tile);
}
view_update_state (view);
@@ -2435,8 +2457,7 @@ view_update_state (ChamplainView *view)
if (tile == NULL)
continue;
- if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_LOADING ||
- champlain_tile_get_state (tile) == CHAMPLAIN_STATE_VALIDATING_CACHE)
+ if (champlain_tile_get_state (tile) == CHAMPLAIN_STATE_LOADING)
new_state = CHAMPLAIN_STATE_LOADING;
}
diff --git a/champlain/champlain.h b/champlain/champlain.h
index 9ae37e1..43fd5ba 100644
--- a/champlain/champlain.h
+++ b/champlain/champlain.h
@@ -29,7 +29,6 @@
#include <glib.h>
#include "champlain/champlain-defines.h"
-#include "champlain/champlain-cache.h"
#include "champlain/champlain-layer.h"
#include "champlain/champlain-selection-layer.h"
#include "champlain/champlain-base-marker.h"
@@ -38,8 +37,13 @@
#include "champlain/champlain-enum-types.h"
#include "champlain/champlain-point.h"
#include "champlain/champlain-map-source.h"
+#include "champlain/champlain-map-source-chain.h"
+#include "champlain/champlain-tile-source.h"
+#include "champlain/champlain-tile-cache.h"
+#include "champlain/champlain-network-tile-source.h"
+#include "champlain/champlain-file-cache.h"
+#include "champlain/champlain-error-tile-source.h"
#include "champlain/champlain-map-source-factory.h"
-#include "champlain/champlain-network-map-source.h"
#include "champlain/champlain-version.h"
#include "champlain/champlain-memphis-map-source.h"
#include "champlain/champlain-map-data-source.h"
diff --git a/demos/launcher-gtk.c b/demos/launcher-gtk.c
index 23cdf1f..20b561e 100644
--- a/demos/launcher-gtk.c
+++ b/demos/launcher-gtk.c
@@ -75,6 +75,11 @@ map_source_changed (GtkWidget *widget,
ChamplainMapSource *source;
GtkTreeIter iter;
GtkTreeModel *model;
+ ChamplainMapSourceChain *source_chain;
+ ChamplainMapSource *src;
+ guint tile_size;
+ gchar *cache_path;
+
if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter))
return;
@@ -86,13 +91,22 @@ map_source_changed (GtkWidget *widget,
ChamplainMapSourceFactory *factory = champlain_map_source_factory_dup_default ();
source = champlain_map_source_factory_create (factory, id);
- if (source != NULL)
- {
- g_object_set (G_OBJECT (view), "map-source", source, NULL);
- g_object_unref (factory);
- }
+ source_chain = champlain_map_source_chain_new ();
+
+ tile_size = champlain_map_source_get_tile_size(source);
+ src = CHAMPLAIN_MAP_SOURCE(champlain_error_tile_source_new_full (tile_size));
- g_object_unref (source);
+ champlain_map_source_chain_push_map_source(source_chain, src);
+ champlain_map_source_chain_push_map_source(source_chain, source);
+
+ cache_path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_cache_dir (), "champlain", NULL);
+ src = CHAMPLAIN_MAP_SOURCE(champlain_file_cache_new_full (100000000, cache_path, TRUE));
+ g_free(cache_path);
+
+ champlain_map_source_chain_push_map_source(source_chain, src);
+
+ g_object_set (G_OBJECT (view), "map-source", source_chain, NULL);
+ g_object_unref (factory);
}
static void
diff --git a/demos/local-rendering.c b/demos/local-rendering.c
index e4333cc..c2d4034 100644
--- a/demos/local-rendering.c
+++ b/demos/local-rendering.c
@@ -42,6 +42,8 @@ static GtkWidget *bordercolor, *bordersize, *borderminz, *bordermaxz;
static GtkWidget *textcolor, *textsize, *textminz, *textmaxz;
static MemphisRule *current_rule = NULL;
+static ChamplainMapSource *tile_source = NULL;
+
/*
* Terminate the main loop.
*/
@@ -52,7 +54,7 @@ on_destroy (GtkWidget *widget, gpointer data)
}
static void color_gdk_to_clutter (const GdkColor *gdk_color,
- ClutterColor *clutter_color)
+ ClutterColor *clutter_color)
{
clutter_color->red = CLAMP (((gdk_color->red / 65535.0) * 255), 0, 255);
clutter_color->green = CLAMP (((gdk_color->green / 65535.0) * 255), 0, 255);
@@ -61,7 +63,7 @@ static void color_gdk_to_clutter (const GdkColor *gdk_color,
}
static void color_clutter_to_gdk (const ClutterColor *clutter_color,
- GdkColor *gdk_color)
+ GdkColor *gdk_color)
{
gdk_color->red = ((guint16) clutter_color->red) << 8;
gdk_color->green = ((guint16) clutter_color->green) << 8;
@@ -70,8 +72,8 @@ static void color_clutter_to_gdk (const ClutterColor *clutter_color,
static void
data_source_state_changed (ChamplainView *view,
- GParamSpec *gobject,
- GtkImage *image)
+ GParamSpec *gobject,
+ GtkImage *image)
{
ChamplainState state;
@@ -94,8 +96,8 @@ load_local_map_data (ChamplainMapSource *source)
ChamplainLocalMapDataSource *map_data_source;
map_data_source = CHAMPLAIN_LOCAL_MAP_DATA_SOURCE (
- champlain_memphis_map_source_get_map_data_source (
- CHAMPLAIN_MEMPHIS_MAP_SOURCE (source)));
+ champlain_memphis_map_source_get_map_data_source (
+ CHAMPLAIN_MEMPHIS_MAP_SOURCE (source)));
champlain_local_map_data_source_load_map_data (map_data_source,
maps[map_index]);
@@ -108,11 +110,11 @@ load_network_map_data (ChamplainMapSource *source, ChamplainView *view)
gdouble lat, lon;
map_data_source = CHAMPLAIN_NETWORK_MAP_DATA_SOURCE (
- champlain_memphis_map_source_get_map_data_source (
- CHAMPLAIN_MEMPHIS_MAP_SOURCE (source)));
+ champlain_memphis_map_source_get_map_data_source (
+ CHAMPLAIN_MEMPHIS_MAP_SOURCE (source)));
g_signal_connect (map_data_source, "notify::state", G_CALLBACK (data_source_state_changed),
- map_data_state_img);
+ map_data_state_img);
g_object_get (G_OBJECT (view), "latitude", &lat, "longitude", &lon, NULL);
@@ -123,19 +125,17 @@ load_network_map_data (ChamplainMapSource *source, ChamplainView *view)
static void
load_rules_into_gui (ChamplainView *view)
{
- ChamplainMapSource *source;
GList* ids, *ptr;
GtkTreeModel *store;
GtkTreeIter iter;
GdkColor gdk_color;
ClutterColor *clutter_color;
- g_object_get (G_OBJECT (view), "map-source", &source, NULL);
ids = champlain_memphis_map_source_get_rule_ids (
- CHAMPLAIN_MEMPHIS_MAP_SOURCE (source));
+ CHAMPLAIN_MEMPHIS_MAP_SOURCE(tile_source));
clutter_color = champlain_memphis_map_source_get_background_color (
- CHAMPLAIN_MEMPHIS_MAP_SOURCE (source));
+ CHAMPLAIN_MEMPHIS_MAP_SOURCE(tile_source));
color_clutter_to_gdk (clutter_color, &gdk_color);
clutter_color_free (clutter_color);
@@ -274,7 +274,7 @@ gtk_memphis_prop_new (gint type, MemphisRuleAttr *attr)
static void
create_rule_edit_window (MemphisRule *rule, gchar* id,
- ChamplainMemphisMapSource *source)
+ ChamplainMemphisMapSource *source)
{
GtkWidget *label, *table, *props, *button;
@@ -284,11 +284,11 @@ create_rule_edit_window (MemphisRule *rule, gchar* id,
gtk_container_set_border_width (GTK_CONTAINER (rule_edit_window), 10);
gtk_window_set_title (GTK_WINDOW (rule_edit_window), id);
gtk_window_set_position (GTK_WINDOW (rule_edit_window),
- GTK_WIN_POS_CENTER_ON_PARENT);
+ GTK_WIN_POS_CENTER_ON_PARENT);
gtk_window_set_transient_for (GTK_WINDOW (rule_edit_window),
- GTK_WINDOW (window));
+ GTK_WINDOW (window));
g_signal_connect (G_OBJECT (rule_edit_window), "destroy",
- G_CALLBACK (rule_window_close_cb), NULL);
+ G_CALLBACK (rule_window_close_cb), NULL);
table = gtk_table_new (6, 2, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 8);
@@ -340,10 +340,10 @@ create_rule_edit_window (MemphisRule *rule, gchar* id,
button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (rule_window_close_cb), NULL);
+ G_CALLBACK (rule_window_close_cb), NULL);
button = gtk_button_new_from_stock (GTK_STOCK_APPLY);
g_signal_connect (G_OBJECT (button), "clicked",
- G_CALLBACK (rule_apply_cb), source);
+ G_CALLBACK (rule_apply_cb), source);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
GtkWidget *mainbox = gtk_vbox_new (FALSE, 0);
@@ -357,13 +357,11 @@ create_rule_edit_window (MemphisRule *rule, gchar* id,
static void
zoom_to_map_data (GtkWidget *widget, ChamplainView *view)
{
- ChamplainMemphisMapSource *source;
ChamplainMapDataSource *data_source;
ChamplainBoundingBox *bbox;
gdouble lat, lon;
- g_object_get (G_OBJECT (view), "map-source", &source, NULL);
- data_source = champlain_memphis_map_source_get_map_data_source (source);
+ data_source = champlain_memphis_map_source_get_map_data_source (CHAMPLAIN_MEMPHIS_MAP_SOURCE(tile_source));
g_object_get (G_OBJECT (data_source), "bounding-box", &bbox, NULL);
champlain_bounding_box_get_center (bbox, &lat, &lon);
@@ -375,16 +373,14 @@ static void
request_osm_data_cb (GtkWidget *widget, ChamplainView *view)
{
gdouble lat, lon;
- ChamplainMapSource *source;
g_object_get (G_OBJECT (view), "latitude", &lat, "longitude", &lon, NULL);
- g_object_get (G_OBJECT (view), "map-source", &source, NULL);
- if (g_strcmp0 (champlain_map_source_get_id (source), "memphis-network") == 0)
+ if (g_strcmp0 (champlain_map_source_get_id (tile_source), "memphis-network") == 0)
{
ChamplainNetworkMapDataSource *data_source =
- CHAMPLAIN_NETWORK_MAP_DATA_SOURCE (
+ CHAMPLAIN_NETWORK_MAP_DATA_SOURCE (
champlain_memphis_map_source_get_map_data_source (
- CHAMPLAIN_MEMPHIS_MAP_SOURCE(source)));
+ CHAMPLAIN_MEMPHIS_MAP_SOURCE(tile_source)));
champlain_network_map_data_source_load_map_data (data_source,
lon - 0.008, lat - 0.008, lon + 0.008, lat + 0.008);
@@ -395,18 +391,16 @@ void
bg_color_set_cb (GtkColorButton *widget, ChamplainView *view)
{
GdkColor gdk_color;
- ChamplainMapSource *source;
gtk_color_button_get_color (widget, &gdk_color);
- g_object_get (G_OBJECT (view), "map-source", &source, NULL);
- if (strncmp (champlain_map_source_get_id (source), "memphis", 7) == 0)
+ if (strncmp (champlain_map_source_get_id (tile_source), "memphis", 7) == 0)
{
ClutterColor clutter_color;
color_gdk_to_clutter (&gdk_color, &clutter_color);
champlain_memphis_map_source_set_background_color (
- CHAMPLAIN_MEMPHIS_MAP_SOURCE (source), &clutter_color);
+ CHAMPLAIN_MEMPHIS_MAP_SOURCE (tile_source), &clutter_color);
}
}
@@ -431,10 +425,15 @@ map_source_changed (GtkWidget *widget, ChamplainView *view)
if (source != NULL)
{
+ ChamplainMapSourceChain *source_chain;
+ ChamplainMapSource *src;
+ guint tile_size;
+ gchar *cache_path;
+
if (g_strcmp0 (id, "memphis-local") == 0)
{
champlain_memphis_map_source_load_rules (
- CHAMPLAIN_MEMPHIS_MAP_SOURCE (source), rules[rules_index]);
+ CHAMPLAIN_MEMPHIS_MAP_SOURCE (source), rules[rules_index]);
load_local_map_data (source);
gtk_widget_hide_all (memphis_box);
gtk_widget_set_no_show_all (memphis_box, FALSE);
@@ -445,7 +444,7 @@ map_source_changed (GtkWidget *widget, ChamplainView *view)
else if (g_strcmp0 (id, "memphis-network") == 0)
{
champlain_memphis_map_source_load_rules (
- CHAMPLAIN_MEMPHIS_MAP_SOURCE (source), rules[rules_index]);
+ CHAMPLAIN_MEMPHIS_MAP_SOURCE (source), rules[rules_index]);
load_network_map_data (source, view);
gtk_widget_hide_all (memphis_box);
gtk_widget_set_no_show_all (memphis_box, FALSE);
@@ -459,8 +458,23 @@ map_source_changed (GtkWidget *widget, ChamplainView *view)
gtk_widget_set_no_show_all (memphis_box, TRUE);
}
- g_object_set (G_OBJECT (view), "map-source", source, NULL);
- g_object_unref (source);
+ tile_source = CHAMPLAIN_MAP_SOURCE(source);
+
+ source_chain = champlain_map_source_chain_new ();
+
+ tile_size = champlain_map_source_get_tile_size(tile_source);
+ src = CHAMPLAIN_MAP_SOURCE(champlain_error_tile_source_new_full (tile_size));
+
+ champlain_map_source_chain_push_map_source(source_chain, src);
+ champlain_map_source_chain_push_map_source(source_chain, tile_source);
+
+ cache_path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_cache_dir (), "champlain", NULL);
+ src = CHAMPLAIN_MAP_SOURCE(champlain_file_cache_new_full (100000000, cache_path, FALSE));
+ g_free(cache_path);
+
+ champlain_map_source_chain_push_map_source(source_chain, src);
+
+ g_object_set (G_OBJECT (view), "map-source", source_chain, NULL);
if (strncmp (id, "memphis", 7) == 0)
load_rules_into_gui (view);
}
@@ -472,7 +486,6 @@ static void
map_data_changed (GtkWidget *widget, ChamplainView *view)
{
gint index;
- ChamplainMapSource *source;
GtkTreeIter iter;
GtkTreeModel *model;
@@ -481,19 +494,17 @@ map_data_changed (GtkWidget *widget, ChamplainView *view)
model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
gtk_tree_model_get (model, &iter, 1, &index, -1);
-
+
map_index = index;
- g_object_get (G_OBJECT (view), "map-source", &source, NULL);
- if (g_strcmp0 (champlain_map_source_get_id (source), "memphis-local") == 0)
- load_local_map_data (source);
+ if (g_strcmp0 (champlain_map_source_get_id (tile_source), "memphis-local") == 0)
+ load_local_map_data (tile_source);
}
static void
rules_changed (GtkWidget *widget, ChamplainView *view)
{
gchar* file;
- ChamplainMapSource *source;
GtkTreeIter iter;
GtkTreeModel *model;
@@ -503,12 +514,11 @@ rules_changed (GtkWidget *widget, ChamplainView *view)
model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
gtk_tree_model_get (model, &iter, 0, &file, -1);
- g_object_get (G_OBJECT (view), "map-source", &source, NULL);
- if (strncmp (champlain_map_source_get_id (source), "memphis", 7) == 0)
+ if (strncmp (champlain_map_source_get_id (tile_source), "memphis", 7) == 0)
{
champlain_memphis_map_source_load_rules (
- CHAMPLAIN_MEMPHIS_MAP_SOURCE (source),
- file);
+ CHAMPLAIN_MEMPHIS_MAP_SOURCE (tile_source),
+ file);
load_rules_into_gui (view);
}
}
@@ -556,25 +566,25 @@ build_source_combo_box (GtkComboBox *box)
GtkCellRenderer *cell;
store = gtk_tree_store_new (N_COLS, G_TYPE_STRING, /* id */
- G_TYPE_STRING, /* name */
- -1);
+ G_TYPE_STRING, /* name */
+ -1);
factory = champlain_map_source_factory_dup_default ();
sources = champlain_map_source_factory_dup_list (factory);
iter = sources;
while (iter != NULL)
- {
- ChamplainMapSourceDesc *desc;
+ {
+ ChamplainMapSourceDesc *desc;
- desc = (ChamplainMapSourceDesc*) iter->data;
+ desc = (ChamplainMapSourceDesc*) iter->data;
- gtk_tree_store_append (store, &parent, NULL);
- gtk_tree_store_set (store, &parent, COL_ID, desc->id,
- COL_NAME, desc->name, -1);
+ gtk_tree_store_append (store, &parent, NULL);
+ gtk_tree_store_set (store, &parent, COL_ID, desc->id,
+ COL_NAME, desc->name, -1);
- iter = g_slist_next (iter);
- }
+ iter = g_slist_next (iter);
+ }
g_slist_free (sources);
g_object_unref (factory);
@@ -584,7 +594,7 @@ build_source_combo_box (GtkComboBox *box)
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);
+ "text", COL_NAME, NULL);
}
static void
@@ -595,22 +605,22 @@ build_data_combo_box (GtkComboBox *box)
GtkCellRenderer *cell;
store = gtk_tree_store_new (2, G_TYPE_STRING, /* file name */
- G_TYPE_INT, /* index */ -1);
+ G_TYPE_INT, /* index */ -1);
gtk_tree_store_append (store, &parent, NULL);
gtk_tree_store_set (store, &parent, 0, maps[0],
- 1, 0, -1);
+ 1, 0, -1);
gtk_tree_store_append (store, &parent, NULL);
gtk_tree_store_set (store, &parent, 0, maps[1],
- 1, 1, -1);
+ 1, 1, -1);
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", 0, NULL);
+ "text", 0, NULL);
}
static void
@@ -632,41 +642,40 @@ build_rules_combo_box (GtkComboBox *box)
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", 0, NULL);
+ "text", 0, NULL);
}
void list_item_selected_cb (GtkTreeView *tree_view,
- GtkTreePath *path,
- GtkTreeViewColumn *column,
- ChamplainView *view)
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ ChamplainView *view)
{
GtkTreeIter iter;
GtkTreeModel *model;
char *id;
GtkTreeSelection *selection = gtk_tree_view_get_selection (tree_view);
- ChamplainMemphisMapSource *source;
MemphisRule *rule;
if (rule_edit_window != NULL)
return;
- if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
- gtk_tree_model_get (model, &iter, 0, &id, -1);
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter, 0, &id, -1);
- g_object_get (G_OBJECT (view), "map-source", &source, NULL);
- rule = champlain_memphis_map_source_get_rule (source, id);
+ rule = champlain_memphis_map_source_get_rule (CHAMPLAIN_MEMPHIS_MAP_SOURCE(tile_source), id);
- if (rule != NULL)
- create_rule_edit_window (rule, id, source);
+ if (rule != NULL)
+ create_rule_edit_window (rule, id, CHAMPLAIN_MEMPHIS_MAP_SOURCE(tile_source));
- g_free (id);
- }
+ g_free (id);
+ }
}
static gboolean
delete_window (GtkWidget *widget,
- GdkEvent *event,
- gpointer user_data)
+ GdkEvent *event,
+ gpointer user_data)
{
gtk_main_quit ();
}
@@ -695,7 +704,7 @@ main (int argc,
* stop the main GTK loop
*/
g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (on_destroy),
- NULL);
+ NULL);
hbox = gtk_hbox_new (FALSE, 10);
menubox = gtk_vbox_new (FALSE, 10);
@@ -710,7 +719,7 @@ main (int argc,
view = gtk_champlain_embed_get_view (GTK_CHAMPLAIN_EMBED (widget));
g_object_set (G_OBJECT (view), "scroll-mode", CHAMPLAIN_SCROLL_MODE_KINETIC,
- "zoom-level", 9, NULL);
+ "zoom-level", 9, NULL);
gtk_widget_set_size_request (widget, 640, 480);
@@ -726,10 +735,10 @@ main (int argc,
button = gtk_spin_button_new_with_range(0, 20, 1);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (button),
- champlain_view_get_zoom_level (view));
+ champlain_view_get_zoom_level (view));
g_signal_connect (button, "changed", G_CALLBACK (zoom_changed), view);
g_signal_connect (view, "notify::zoom-level", G_CALLBACK (map_zoom_changed),
- button);
+ button);
gtk_container_add (GTK_CONTAINER (bbox), button);
gtk_box_pack_start (GTK_BOX (menubox), bbox, FALSE, FALSE, 0);
@@ -782,7 +791,7 @@ main (int argc,
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label), "Background color");
gtk_box_pack_start (GTK_BOX (bbox), label, FALSE, FALSE, 0);
-
+
bg_button = gtk_color_button_new ();
gtk_color_button_set_title (GTK_COLOR_BUTTON (bg_button), "Background");
g_signal_connect (bg_button, "color-set", G_CALLBACK (bg_color_set_cb), view);
@@ -818,7 +827,7 @@ main (int argc,
scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled), tree_view);
gtk_box_pack_start (GTK_BOX (memphis_box), scrolled, TRUE, TRUE, 0);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]