2 * Copyright (C) 2006, 2007 John Costigan.
4 * POI and GPS-Info code originally written by Cezary Jackiewicz.
6 * Default map data provided by http://www.openstreetmap.org/
8 * This file is part of Maemo Mapper.
10 * Maemo Mapper is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
15 * Maemo Mapper is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with Maemo Mapper. If not, see <http://www.gnu.org/licenses/>.
33 #include <glib/gstdio.h>
39 # include <hildon/hildon-help.h>
40 # include <hildon/hildon-note.h>
41 # include <hildon/hildon-file-chooser-dialog.h>
42 # include <hildon/hildon-number-editor.h>
43 # include <hildon/hildon-banner.h>
45 # include <osso-helplib.h>
46 # include <hildon-widgets/hildon-note.h>
47 # include <hildon-widgets/hildon-file-chooser-dialog.h>
48 # include <hildon-widgets/hildon-number-editor.h>
49 # include <hildon-widgets/hildon-banner.h>
50 # include <hildon-widgets/hildon-input-mode-hint.h>
66 typedef struct _RepoManInfo RepoManInfo;
74 typedef struct _RepoEditInfo RepoEditInfo;
75 struct _RepoEditInfo {
79 GtkWidget *txt_db_filename;
80 GtkWidget *num_dl_zoom_steps;
81 GtkWidget *num_view_zoom_steps;
82 GtkWidget *chk_double_size;
83 GtkWidget *chk_nextable;
84 GtkWidget *btn_browse;
85 GtkWidget *btn_compact;
86 GtkWidget *num_min_zoom;
87 GtkWidget *num_max_zoom;
88 BrowseInfo browse_info;
93 typedef struct _RepoLayersInfo RepoLayersInfo;
94 struct _RepoLayersInfo {
97 GtkListStore *layers_store;
98 GtkWidget *layers_list;
103 typedef struct _LayerEditInfo LayerEditInfo;
104 struct _LayerEditInfo {
110 GtkWidget *num_autofetch;
111 GtkWidget *chk_visible;
117 typedef struct _MapmanInfo MapmanInfo;
123 /* The "Setup" tab. */
124 GtkWidget *rad_download;
125 GtkWidget *rad_delete;
126 GtkWidget *chk_overwrite;
127 GtkWidget *rad_by_area;
128 GtkWidget *rad_by_route;
129 GtkWidget *num_route_radius;
131 /* The "Area" tab. */
132 GtkWidget *txt_topleft_lat;
133 GtkWidget *txt_topleft_lon;
134 GtkWidget *txt_botright_lat;
135 GtkWidget *txt_botright_lon;
137 /* The "Zoom" tab. */
138 GtkWidget *chk_zoom_levels[MAX_ZOOM + 1];
142 typedef struct _CompactInfo CompactInfo;
143 struct _CompactInfo {
147 const gchar *db_filename;
152 typedef struct _MapCacheKey MapCacheKey;
153 struct _MapCacheKey {
160 typedef struct _MapCacheEntry MapCacheEntry;
161 struct _MapCacheEntry {
172 typedef struct _MapCacheList MapCacheList;
173 struct _MapCacheList {
180 typedef struct _MapCache MapCache;
182 MapCacheList lists[4];
191 static MapCache _map_cache;
193 const gchar* layer_timestamp_key = "tEXt::mm_ts";
197 mapdb_get_data(RepoData *repo, gint zoom, gint tilex, gint tiley, gchar **data)
200 vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
201 repo->name, zoom, tilex, tiley);
205 if(!MAPDB_EXISTS(repo))
207 /* There is no cache. Return NULL. */
208 vprintf("%s(): return %u\n", __PRETTY_FUNCTION__,size);
214 /* Attempt to retrieve map from database. */
215 if(SQLITE_OK == sqlite3_bind_int(repo->stmt_map_select, 1, zoom)
216 && SQLITE_OK == sqlite3_bind_int(repo->stmt_map_select, 2, tilex)
217 && SQLITE_OK == sqlite3_bind_int(repo->stmt_map_select, 3, tiley)
218 && SQLITE_ROW == sqlite3_step(repo->stmt_map_select))
220 const gchar *bytes = NULL;
221 size = sqlite3_column_bytes(repo->stmt_map_select, 0);
223 bytes = sqlite3_column_blob(repo->stmt_map_select, 0);
226 *data = g_slice_alloc(size);
227 memcpy(*data, bytes, size);
230 sqlite3_reset(repo->stmt_map_select);
240 d.dptr = (gchar*)&key;
241 d.dsize = sizeof(key);
242 d = gdbm_fetch(repo->gdbm_db, d);
246 *data = g_slice_alloc(size);
247 memcpy(*data, d.dptr, size);
252 vprintf("%s(): return %u\n", __PRETTY_FUNCTION__, size);
256 static void map_cache_list_remove(MapCacheList *_list, MapCacheEntry *_entry)
258 _list->size -= _entry->size;
259 _list->data_sz -= _entry->data_sz;
260 *(_entry->prev != NULL?&_entry->prev->next:&_list->head) = _entry->next;
261 *(_entry->next != NULL?&_entry->next->prev:&_list->tail) = _entry->prev;
264 static void map_cache_list_prepend(MapCacheList *_list, int _li,
265 MapCacheEntry *_entry)
268 _entry->next = _list[_li].head;
269 *(_list[_li].head != NULL?&_list[_li].head->prev:&_list[_li].tail) = _entry;
270 _list[_li].head = _entry;
271 _list[_li].size += _entry->size;
272 _list[_li].data_sz += _entry->data_sz;
276 static guint map_cache_key_hash(gconstpointer _key){
277 const MapCacheKey *key;
278 key = (const MapCacheKey *)_key;
279 return g_direct_hash(key->repo)+g_int_hash(&key->zoom)+
280 g_int_hash(&key->tilex)+g_int_hash(&key->tiley);
283 static gboolean map_cache_key_equal(gconstpointer _v1, gconstpointer _v2){
284 const MapCacheKey *key1;
285 const MapCacheKey *key2;
286 key1 = (const MapCacheKey *)_v1;
287 key2 = (const MapCacheKey *)_v2;
288 return key1->tilex == key2->tilex && key1->tiley == key2->tiley &&
289 key1->zoom == key2->zoom && key1->repo == key2->repo;
292 static void map_cache_entry_make_pixbuf(MapCacheEntry *_entry){
293 if (_entry->data != NULL)
296 GdkPixbufLoader *loader;
298 loader = gdk_pixbuf_loader_new();
299 gdk_pixbuf_loader_write(loader, _entry->data, _entry->data_sz, NULL);
300 gdk_pixbuf_loader_close(loader, &error);
303 _entry->pixbuf = g_object_ref(gdk_pixbuf_loader_get_pixbuf(loader));
304 _entry->size = _entry->data_sz+
305 gdk_pixbuf_get_rowstride(_entry->pixbuf)*
306 gdk_pixbuf_get_height(_entry->pixbuf);
307 g_object_unref(loader);
310 g_object_unref(loader);
311 g_slice_free1(_entry->data_sz, _entry->data);
315 _entry->pixbuf = NULL;
316 _entry->size = _entry->data_sz;
319 static void map_cache_entry_free_pixbuf(MapCacheEntry *_entry){
320 if(_entry->pixbuf!=NULL)
322 g_object_unref(_entry->pixbuf);
323 _entry->pixbuf = NULL;
327 static void map_cache_entry_free(MapCacheEntry *_entry){
328 if(_entry->list >= 0)
329 map_cache_list_remove(_map_cache.lists+_entry->list, _entry);
330 map_cache_entry_free_pixbuf(_entry);
331 g_slice_free1(_entry->data_sz, _entry->data);
332 g_slice_free(MapCacheEntry, _entry);
336 map_cache_replace(size_t _size, gboolean _b2)
340 total_size = _map_cache.lists[0].size+_map_cache.lists[1].data_sz
341 +_map_cache.lists[2].size+_map_cache.lists[3].data_sz;
343 while(total_size+_size > _map_cache.cache_size)
345 MapCacheEntry *entry;
347 if(_map_cache.lists[0].tail != NULL &&
348 (_map_cache.lists[0].size > _map_cache.p ||
349 (_b2 && _map_cache.lists[0].size == _map_cache.p)))
353 entry = _map_cache.lists[list].tail;
356 map_cache_list_remove(_map_cache.lists+list, entry);
357 map_cache_list_prepend(_map_cache.lists, list+1, entry);
358 total_size -= entry->size - entry->data_sz;
366 map_cache_evict(size_t _size)
370 total_size = _map_cache.lists[0].size+_map_cache.lists[1].size
371 +_map_cache.lists[2].size+_map_cache.lists[3].size;
372 max_size = _map_cache.cache_size<<1;
375 if(_map_cache.lists[0].size+_map_cache.lists[1].size+_size >
376 _map_cache.cache_size)
378 if(_map_cache.lists[1].tail != NULL)
380 g_hash_table_remove(_map_cache.entries,
381 &_map_cache.lists[1].tail->key);
382 map_cache_replace(_size, FALSE);
384 else if(_map_cache.lists[0].tail != NULL)
386 g_hash_table_remove(_map_cache.entries,
387 &_map_cache.lists[0].tail->key);
391 else if(total_size+_size > _map_cache.cache_size)
393 if(total_size+_size > max_size &&
394 _map_cache.lists[3].tail != NULL)
396 g_hash_table_remove(_map_cache.entries,
397 &_map_cache.lists[3].tail->key);
398 map_cache_replace(_size, FALSE);
400 else if(!map_cache_replace(_size, FALSE))
404 total_size = _map_cache.lists[0].size+_map_cache.lists[1].size
405 +_map_cache.lists[2].size+_map_cache.lists[3].size;
410 map_cache_get(RepoData *repo, gint zoom, gint tilex, gint tiley)
413 MapCacheEntry *entry;
418 entry = (MapCacheEntry *)g_hash_table_lookup(_map_cache.entries, &key);
421 map_cache_list_remove(_map_cache.lists+entry->list, entry);
422 if(entry->pixbuf == NULL)
426 map_cache_entry_make_pixbuf(entry);
427 bsize = _map_cache.lists[entry->list].size+entry->size;
430 dp = _map_cache.lists[entry->list^2].size/bsize;
436 if(_map_cache.p > _map_cache.cache_size)
437 _map_cache.p = _map_cache.cache_size;
438 map_cache_replace(entry->size, FALSE);
442 if(dp > _map_cache.p)
446 map_cache_replace(entry->size, TRUE);
452 map_cache_list_prepend(_map_cache.lists, 2, entry);
458 data_sz = mapdb_get_data(repo, zoom, tilex, tiley, &data);
459 entry = g_slice_new(MapCacheEntry);
460 *&entry->key = *&key;
462 entry->data_sz = data_sz;
463 map_cache_entry_make_pixbuf(entry);
464 map_cache_evict(entry->size);
465 map_cache_list_prepend(_map_cache.lists, 0, entry);
466 g_hash_table_insert(_map_cache.entries, &entry->key, entry);
469 if(entry->pixbuf != NULL)
470 g_object_ref(entry->pixbuf);
471 return entry->pixbuf;
475 map_cache_update(RepoData *repo, gint zoom, gint tilex, gint tiley,
476 gchar *data,guint size)
479 MapCacheEntry *entry;
484 entry = (MapCacheEntry *)g_hash_table_lookup(_map_cache.entries, &key);
487 g_slice_free1(entry->data_sz, entry->data);
488 entry->data = g_slice_alloc(size);
489 memcpy(entry->data, data, size);
490 entry->data_sz = size;
491 if(entry->pixbuf != NULL)
493 map_cache_entry_free_pixbuf(entry);
494 map_cache_list_remove(_map_cache.lists+entry->list, entry);
495 map_cache_list_prepend(_map_cache.lists, entry->list+1, entry);
501 map_cache_remove(RepoData *repo, gint zoom, gint tilex, gint tiley)
508 g_hash_table_remove(_map_cache.entries, &key);
512 map_cache_init_unlocked(size_t cache_size)
514 if(_map_cache.entries == NULL)
515 _map_cache.entries = g_hash_table_new_full(map_cache_key_hash,
516 map_cache_key_equal, NULL, (GDestroyNotify)map_cache_entry_free);
517 _map_cache.cache_size = cache_size;
518 if(_map_cache.p > cache_size)
519 _map_cache.p = cache_size;
524 map_cache_init(size_t cache_size)
526 g_mutex_lock(_mapdb_mutex);
527 map_cache_init_unlocked(cache_size);
528 g_mutex_unlock(_mapdb_mutex);
532 map_cache_resize(size_t cache_size)
535 g_mutex_lock(_mapdb_mutex);
536 _map_cache.cache_size = cache_size;
537 total_size = _map_cache.lists[0].size+_map_cache.lists[1].data_sz
538 +_map_cache.lists[2].size+_map_cache.lists[3].data_sz;
539 g_mutex_unlock(_mapdb_mutex);
544 map_cache_destroy_unlocked(void)
546 if(_map_cache.entries != NULL)
548 g_hash_table_destroy(_map_cache.entries);
549 _map_cache.entries = NULL;
550 printf("thits: %u (%0.2f%%) bhits: %u (%0.2f%%) "
551 "misses: %u (%0.2f%%)\n",
552 _map_cache.thits, 100*_map_cache.thits/(double)(
553 _map_cache.thits+_map_cache.bhits+_map_cache.misses),
554 _map_cache.bhits, 100*_map_cache.bhits/(double)(
555 _map_cache.thits+_map_cache.bhits+_map_cache.misses),
556 _map_cache.misses, 100*_map_cache.misses/(double)(
557 _map_cache.thits+_map_cache.bhits+_map_cache.misses));
562 map_cache_destroy(void)
564 g_mutex_lock(_mapdb_mutex);
565 map_cache_destroy_unlocked();
566 g_mutex_unlock(_mapdb_mutex);
570 clean_layers_from_cache(MapCacheKey *key, MapCacheEntry *value, RepoData *repo)
572 if(key->repo == repo)
573 map_cache_entry_free_pixbuf(value);
577 map_cache_clean (void)
579 g_mutex_lock(_mapdb_mutex);
580 g_hash_table_foreach(_map_cache.entries,
581 (GHFunc)clean_layers_from_cache, _curr_repo);
582 g_mutex_unlock(_mapdb_mutex);
587 remove_repo_from_cache(MapCacheKey *key, MapCacheEntry *value, RepoData *repo)
589 if (key->repo == repo)
590 printf("REMOVING ENTRY AT (%d, %d, %d)\n",
591 key->zoom, key->tilex, key->tiley);
592 return key->repo == repo;
596 * This method "refreshes" a layer by both removing the layer from the cache
597 * and removing the layer-applied pixbufs from the base repo's cache entries.
600 map_cache_clean_layer(RepoData *layer)
602 printf("%s()\n", __PRETTY_FUNCTION__);
604 g_hash_table_foreach_remove(_map_cache.entries,
605 (GHRFunc)remove_repo_from_cache, layer);
607 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
611 mapdb_exists(RepoData *repo, gint zoom, gint tilex, gint tiley)
614 vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
615 repo->name, zoom, tilex, tiley);
617 g_mutex_lock(_mapdb_mutex);
619 if(!MAPDB_EXISTS(repo))
621 /* There is no cache. Return FALSE. */
622 g_mutex_unlock(_mapdb_mutex);
623 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
627 /* Search the cache first. */
630 MapCacheEntry *entry;
635 entry = (MapCacheEntry *)g_hash_table_lookup(_map_cache.entries, &key);
639 ret = entry->data != NULL;
640 g_mutex_unlock(_mapdb_mutex);
647 /* Attempt to retrieve map from database. */
648 if(SQLITE_OK == sqlite3_bind_int(repo->stmt_map_exists, 1, zoom)
649 && SQLITE_OK == sqlite3_bind_int(repo->stmt_map_exists, 2, tilex)
650 && SQLITE_OK == sqlite3_bind_int(repo->stmt_map_exists, 3, tiley)
651 && SQLITE_ROW == sqlite3_step(repo->stmt_map_exists)
652 && sqlite3_column_int(repo->stmt_map_exists, 0) > 0)
660 sqlite3_reset(repo->stmt_map_exists);
670 d.dptr = (gchar*)&key;
671 d.dsize = sizeof(key);
672 exists = gdbm_exists(repo->gdbm_db, d);
675 g_mutex_unlock(_mapdb_mutex);
677 vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, exists);
682 mapdb_get(RepoData *repo, gint zoom, gint tilex, gint tiley)
685 vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
686 repo->name, zoom, tilex, tiley);
687 g_mutex_lock(_mapdb_mutex);
688 pixbuf = map_cache_get(repo, zoom, tilex, tiley);
689 g_mutex_unlock(_mapdb_mutex);
690 vprintf("%s(): return %p\n", __PRETTY_FUNCTION__, pixbuf);
695 mapdb_update(RepoData *repo, gint zoom, gint tilex, gint tiley,
696 void *bytes, gint size)
699 vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
700 repo->name, zoom, tilex, tiley);
702 g_mutex_lock(_mapdb_mutex);
703 map_cache_update(repo, zoom, tilex, tiley, bytes, size);
705 if(!MAPDB_EXISTS(repo))
707 /* There is no cache. Return FALSE. */
708 g_mutex_unlock(_mapdb_mutex);
709 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
715 /* Attempt to insert/update map in database. */
716 if(SQLITE_OK != sqlite3_bind_blob(repo->stmt_map_update, 1,
718 || SQLITE_OK != sqlite3_bind_int(repo->stmt_map_update, 2, zoom)
719 || SQLITE_OK != sqlite3_bind_int(repo->stmt_map_update, 3, tilex)
720 || SQLITE_OK != sqlite3_bind_int(repo->stmt_map_update, 4, tiley)
721 || SQLITE_DONE != sqlite3_step(repo->stmt_map_update))
724 fprintf(stderr, "Error in mapdb_update: %s\n",
725 sqlite3_errmsg(repo->sqlite_db));
727 sqlite3_reset(repo->stmt_map_update);
737 dkey.dptr = (gchar*)&key;
738 dkey.dsize = sizeof(key);
741 success = !gdbm_store(repo->gdbm_db, dkey, dcon, GDBM_REPLACE);
743 g_mutex_unlock(_mapdb_mutex);
745 vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, success);
750 mapdb_delete(RepoData *repo, gint zoom, gint tilex, gint tiley)
752 gint success = FALSE;
753 vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
754 repo->name, zoom, tilex, tiley);
756 g_mutex_lock(_mapdb_mutex);
757 map_cache_remove(repo, zoom, tilex, tiley);
759 if(!MAPDB_EXISTS(repo))
761 /* There is no cache. Return FALSE. */
762 g_mutex_unlock(_mapdb_mutex);
763 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
769 if(SQLITE_OK != sqlite3_bind_int(repo->stmt_map_delete, 1, zoom)
770 || SQLITE_OK != sqlite3_bind_int(repo->stmt_map_delete, 2, tilex)
771 || SQLITE_OK != sqlite3_bind_int(repo->stmt_map_delete, 3, tiley)
772 || SQLITE_DONE != sqlite3_step(repo->stmt_map_delete))
775 printf("Error in stmt_map_delete: %s\n",
776 sqlite3_errmsg(repo->sqlite_db));
778 sqlite3_reset(repo->stmt_map_delete);
788 d.dptr = (gchar*)&key;
789 d.dsize = sizeof(key);
790 success = !gdbm_delete(repo->gdbm_db, d);
793 g_mutex_unlock(_mapdb_mutex);
795 vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, success);
800 set_repo_type(RepoData *repo)
802 printf("%s(%s)\n", __PRETTY_FUNCTION__, repo->url);
804 if(repo->url && *repo->url)
806 gchar *url = g_utf8_strdown(repo->url, -1);
808 /* Determine type of repository. */
809 if(strstr(url, "service=wms"))
810 repo->type = REPOTYPE_WMS;
811 else if(strstr(url, "%s"))
812 repo->type = REPOTYPE_QUAD_QRST;
813 else if(strstr(url, "%0d"))
814 repo->type = REPOTYPE_XYZ_INV;
815 else if(strstr(url, "%-d"))
816 repo->type = REPOTYPE_XYZ_SIGNED;
817 else if(strstr(url, "%0s"))
818 repo->type = REPOTYPE_QUAD_ZERO;
820 repo->type = REPOTYPE_XYZ;
825 repo->type = REPOTYPE_NONE;
827 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
830 /* Returns the directory containing the given database filename, or NULL
831 * if the database file could not be created. */
833 repo_make_db(RepoData *rd)
835 printf("%s(%s)\n", __PRETTY_FUNCTION__, rd->db_filename);
839 db_dirname = g_path_get_dirname(rd->db_filename);
841 /* Check if db_filename is a directory and ask to upgrade. */
842 if(g_file_test(rd->db_filename, G_FILE_TEST_IS_DIR))
844 gchar buffer[BUFFER_SIZE];
845 gchar *new_name = g_strdup_printf("%s.sqlite", rd->db_filename);
846 g_free(rd->db_filename);
847 rd->db_filename = new_name;
848 rd->is_sqlite = TRUE;
850 snprintf(buffer, sizeof(buffer), "%s",
851 _("The current repository is in a legacy format and will "
852 "be converted. You should delete your old maps if you "
853 "no longer plan to use them."));
854 popup_error(_window, buffer);
857 if(g_mkdir_with_parents(db_dirname, 0755))
864 if(!g_file_test(rd->db_filename, G_FILE_TEST_EXISTS))
866 fd = g_creat(rd->db_filename, 0644);
875 vprintf("%s(): return %d\n", __PRETTY_FUNCTION__,
876 g_file_test(rd->db_filename, G_FILE_TEST_EXISTS));
877 return g_file_test(rd->db_filename, G_FILE_TEST_EXISTS);
881 repo_set_curr(RepoData *rd)
884 printf("%s()\n", __PRETTY_FUNCTION__);
886 if(rd->db_filename && *rd->db_filename && !repo_make_db(rd))
888 gchar buffer[BUFFER_SIZE];
889 snprintf(buffer, sizeof(buffer), "%s: %s",
890 _("Unable to create map database for repository"), rd->name);
891 popup_error(_window, buffer);
893 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
897 /* Disconnect the previous repository. */
898 for(repo_p = _curr_repo; repo_p; repo_p = repo_p->layers)
900 if(MAPDB_EXISTS(repo_p))
902 g_mutex_lock(_mapdb_mutex);
903 if(repo_p->is_sqlite)
905 sqlite3_close(repo_p->sqlite_db);
906 repo_p->sqlite_db = NULL;
910 gdbm_close(repo_p->gdbm_db);
911 repo_p->gdbm_db = NULL;
913 g_mutex_unlock(_mapdb_mutex);
917 /* Set the current repository! */
920 /* initialize all databases for all layers */
921 for(repo_p = _curr_repo; repo_p; repo_p = repo_p->layers)
923 /* Check if the repository or layer has a backing database. (This is a
924 * redundant check in the case of the base, non-layer repository.) */
925 if (repo_p->db_filename && *repo_p->db_filename
926 && repo_make_db (repo_p))
928 if(repo_p->is_sqlite)
930 printf("Building SQLite3 database: %s\n",
931 repo_p->db_filename);
932 if(SQLITE_OK != (sqlite3_open(repo_p->db_filename,
933 &(repo_p->sqlite_db)))
934 /* Open worked. Now create tables, failing if they already
936 || (sqlite3_exec(repo_p->sqlite_db,
937 "create table maps ("
942 "primary key (zoom, tilex, tiley))",
943 NULL, NULL, NULL), FALSE) /* Comma operator! */
944 /* Prepare select map statement. */
945 || SQLITE_OK != sqlite3_prepare(repo_p->sqlite_db,
946 "select pixbuf from maps "
947 "where zoom = ? and tilex = ? and tiley = ?",
948 -1, &repo_p->stmt_map_select, NULL)
949 /* Prepare exists map statement. */
950 || SQLITE_OK != sqlite3_prepare(repo_p->sqlite_db,
951 "select count(*) from maps "
952 "where zoom = ? and tilex = ? and tiley = ?",
953 -1, &repo_p->stmt_map_exists, NULL)
954 /* Prepare insert map statement. */
955 || SQLITE_OK != sqlite3_prepare(repo_p->sqlite_db,
956 "insert or replace into maps"
957 " (pixbuf, zoom, tilex, tiley)"
958 " values (?, ?, ?, ?)",
959 -1, &repo_p->stmt_map_update, NULL)
960 /* Prepare delete map statement. */
961 || SQLITE_OK != sqlite3_prepare(repo_p->sqlite_db,
963 "where zoom = ? and tilex = ? and tiley = ?",
964 -1, &repo_p->stmt_map_delete, NULL))
966 gchar buffer[BUFFER_SIZE];
967 snprintf(buffer, sizeof(buffer), "%s: %s\n%s",
968 _("Failed to open map database for repository"),
969 sqlite3_errmsg(repo_p->sqlite_db),
970 _("Downloaded maps will not be cached."));
971 sqlite3_close(repo_p->sqlite_db);
972 repo_p->sqlite_db = NULL;
973 popup_error(_window, buffer);
978 printf("Building GDBM database: %s\n",
979 repo_p->db_filename);
980 repo_p->gdbm_db = gdbm_open(repo_p->db_filename,
981 0, GDBM_WRCREAT | GDBM_FAST, 0644, NULL);
986 if(!MAPDB_EXISTS(_curr_repo))
988 gchar buffer[BUFFER_SIZE];
989 snprintf(buffer, sizeof(buffer), "%s\n%s",
990 _("Failed to open map database for repository"),
991 _("Downloaded maps will not be cached."));
992 popup_error(_window, buffer);
994 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1001 * 1. base == layer, or
1002 * 2. layer is sublayer of base
1004 gboolean repo_is_layer (RepoData* base, RepoData* layer)
1009 base = base->layers;
1017 * Given a wms uri pattern, compute the coordinate transformation and
1019 * 'proj' is used for the conversion
1022 map_convert_wms_to_wms(gint tilex, gint tiley, gint zoomlevel, gchar* uri)
1024 gint system_retcode;
1025 gchar cmd[BUFFER_SIZE], srs[BUFFER_SIZE];
1028 gdouble lon1, lat1, lon2, lat2;
1030 gchar *widthstr = strcasestr(uri,"WIDTH=");
1031 gchar *heightstr = strcasestr(uri,"HEIGHT=");
1032 gchar *srsstr = strcasestr(uri,"SRS=EPSG");
1033 gchar *srsstre = strchr(srsstr,'&');
1034 vprintf("%s()\n", __PRETTY_FUNCTION__);
1036 /* missing: test if found */
1038 strncpy(srs+4,srsstr+8,256);
1039 /* missing: test srsstre-srsstr < 526 */
1040 srs[srsstre-srsstr-4] = 0;
1041 /* convert to lower, as WMC is EPSG and cs2cs is epsg */
1043 gint dwidth = widthstr ? atoi(widthstr+6) - TILE_SIZE_PIXELS : 0;
1044 gint dheight = heightstr ? atoi(heightstr+7) - TILE_SIZE_PIXELS : 0;
1046 unit2latlon(tile2zunit(tilex,zoomlevel)
1047 - pixel2zunit(dwidth/2,zoomlevel),
1048 tile2zunit(tiley+1,zoomlevel)
1049 + pixel2zunit((dheight+1)/2,zoomlevel),
1052 unit2latlon(tile2zunit(tilex+1,zoomlevel)
1053 + pixel2zunit((dwidth+1)/2,zoomlevel),
1054 tile2zunit(tiley,zoomlevel)
1055 - pixel2zunit(dheight/2,zoomlevel),
1058 setlocale(LC_NUMERIC, "C");
1060 snprintf(cmd, sizeof(cmd),
1061 "(echo \"%.6f %.6f\"; echo \"%.6f %.6f\") | "
1062 "/usr/bin/cs2cs +proj=longlat +datum=WGS84 +to +init=%s -f %%.6f "
1063 " > /tmp/tmpcs2cs ",
1064 lon1, lat1, lon2, lat2, srs);
1065 vprintf("Running command: %s\n", cmd);
1066 system_retcode = system(cmd);
1069 g_printerr("cs2cs returned error code %d\n",
1070 WEXITSTATUS(system_retcode));
1071 else if(!(in = g_fopen("/tmp/tmpcs2cs","r")))
1072 g_printerr("Cannot open results of conversion\n");
1073 else if(5 != fscanf(in,"%lf %lf %s %lf %lf",
1074 &lon1, &lat1, cmd, &lon2, &lat2))
1076 g_printerr("Wrong conversion\n");
1082 ret = g_strdup_printf(uri, lon1, lat1, lon2, lat2);
1085 setlocale(LC_NUMERIC, "");
1087 vprintf("%s(): return %s\n", __PRETTY_FUNCTION__, ret);
1093 * Given the xyz coordinates of our map coordinate system, write the qrst
1094 * quadtree coordinates to buffer.
1097 map_convert_coords_to_quadtree_string(gint x, gint y, gint zoomlevel,
1098 gchar *buffer, const gchar initial,
1099 const gchar *const quadrant)
1101 gchar *ptr = buffer;
1103 vprintf("%s()\n", __PRETTY_FUNCTION__);
1108 for(n = MAX_ZOOM - zoomlevel; n >= 0; n--)
1110 gint xbit = (x >> n) & 1;
1111 gint ybit = (y >> n) & 1;
1112 *ptr++ = quadrant[xbit + 2 * ybit];
1115 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1119 * Construct the URL that we should fetch, based on the current URI format.
1120 * This method works differently depending on if a "%s" string is present in
1121 * the URI format, since that would indicate a quadtree-based map coordinate
1125 map_construct_url(RepoData *repo, gint zoom, gint tilex, gint tiley)
1128 vprintf("%s(%p, %d, %d, %d)\n", __PRETTY_FUNCTION__,
1129 repo, zoom, tilex, tiley);
1133 retval = g_strdup_printf(repo->url,
1134 tilex, tiley, zoom - (MAX_ZOOM - 16));
1137 case REPOTYPE_XYZ_INV:
1138 retval = g_strdup_printf(repo->url,
1139 MAX_ZOOM + 1 - zoom, tilex, tiley);
1142 case REPOTYPE_XYZ_SIGNED:
1143 retval = g_strdup_printf(repo->url,
1145 (1 << (MAX_ZOOM - zoom)) - tiley - 1,
1146 zoom - (MAX_ZOOM - 17));
1149 case REPOTYPE_QUAD_QRST:
1151 gchar location[MAX_ZOOM + 2];
1152 map_convert_coords_to_quadtree_string(
1153 tilex, tiley, zoom, location, 't', "qrts");
1154 retval = g_strdup_printf(repo->url, location);
1158 case REPOTYPE_QUAD_ZERO:
1160 /* This is a zero-based quadtree URI. */
1161 gchar location[MAX_ZOOM + 2];
1162 map_convert_coords_to_quadtree_string(
1163 tilex, tiley, zoom, location, '\0', "0123");
1164 retval = g_strdup_printf(repo->url, location);
1169 retval = map_convert_wms_to_wms(tilex, tiley, zoom, repo->url);
1173 retval = g_strdup(repo->url);
1176 vprintf("%s(): return \"%s\"\n", __PRETTY_FUNCTION__, retval);
1181 mapdb_initiate_update_banner_idle()
1183 if(!_download_banner && _num_downloads != _curr_download)
1185 _download_banner = hildon_banner_show_progress(
1186 _window, NULL, _("Processing Maps"));
1187 /* If we're not connected, then hide the banner immediately. It will
1188 * be unhidden if/when we're connected. */
1189 if(!_conic_is_connected)
1190 gtk_widget_hide(_download_banner);
1196 * Initiate a download of the given xyz coordinates using the given buffer
1197 * as the URL. If the map already exists on disk, or if we are already
1198 * downloading the map, then this method does nothing.
1201 mapdb_initiate_update(RepoData *repo, gint zoom, gint tilex, gint tiley,
1202 gint update_type, gint batch_id, gint priority,
1203 ThreadLatch *refresh_latch)
1206 MapUpdateTask *old_mut;
1207 gboolean is_replacing = FALSE;
1208 vprintf("%s(%s, %d, %d, %d, %d)\n", __PRETTY_FUNCTION__,
1209 repo->name, zoom, tilex, tiley, update_type);
1211 mut = g_slice_new(MapUpdateTask);
1214 /* Could not allocate memory. */
1215 g_printerr("Out of memory in allocation of update task #%d\n",
1216 _num_downloads + 1);
1222 mut->update_type = update_type;
1223 mut->layer_level = repo->layer_level;
1225 /* Lock the mutex if this is an auto-update. */
1226 if(update_type == MAP_UPDATE_AUTO)
1227 g_mutex_lock(_mut_priority_mutex);
1228 if(NULL != (old_mut = g_hash_table_lookup(_mut_exists_table, mut)))
1230 /* Check if new mut is in a newer batch that the old mut.
1231 * We use vfs_result to indicate a MUT that is already in the process
1232 * of being downloaded. */
1233 if(old_mut->batch_id < batch_id && old_mut->vfs_result < 0)
1235 /* It is, so remove the old one so we can re-add this one. */
1236 g_hash_table_remove(_mut_exists_table, old_mut);
1237 g_tree_remove(_mut_priority_tree, old_mut);
1238 g_slice_free(MapUpdateTask, old_mut);
1239 is_replacing = TRUE;
1243 /* It's not, so just ignore it. */
1244 if(update_type == MAP_UPDATE_AUTO)
1245 g_mutex_unlock(_mut_priority_mutex);
1246 g_slice_free(MapUpdateTask, mut);
1247 vprintf("%s(): return FALSE (1)\n", __PRETTY_FUNCTION__);
1252 g_hash_table_insert(_mut_exists_table, mut, mut);
1255 mut->refresh_latch = refresh_latch;
1256 mut->priority = priority;
1257 mut->batch_id = batch_id;
1259 mut->vfs_result = -1;
1261 g_tree_insert(_mut_priority_tree, mut, mut);
1263 /* Unlock the mutex if this is an auto-update. */
1264 if(update_type == MAP_UPDATE_AUTO)
1265 g_mutex_unlock(_mut_priority_mutex);
1269 /* Increment download count and (possibly) display banner. */
1270 if(++_num_downloads == 20 && !_download_banner)
1271 g_idle_add((GSourceFunc)mapdb_initiate_update_banner_idle, NULL);
1273 /* This doesn't need to be thread-safe. Extras in the pool don't
1274 * really make a difference. */
1275 if(g_thread_pool_get_num_threads(_mut_thread_pool)
1276 < g_thread_pool_get_max_threads(_mut_thread_pool))
1277 g_thread_pool_push(_mut_thread_pool, (gpointer)1, NULL);
1280 vprintf("%s(): return FALSE (2)\n", __PRETTY_FUNCTION__);
1285 get_next_mut(gpointer key, gpointer value, MapUpdateTask **data)
1292 map_handle_error(gchar *error)
1294 MACRO_BANNER_SHOW_INFO(_window, error);
1301 printf("%s()\n", __PRETTY_FUNCTION__);
1303 /* Make sure things are inititalized. */
1306 while(conic_ensure_connected())
1309 gboolean refresh_sent = FALSE, layer_tile;
1310 MapUpdateTask *mut = NULL;
1312 /* Get the next MUT from the mut tree. */
1313 g_mutex_lock(_mut_priority_mutex);
1314 g_tree_foreach(_mut_priority_tree, (GTraverseFunc)get_next_mut, &mut);
1317 /* No more MUTs to process. Return. */
1318 g_mutex_unlock(_mut_priority_mutex);
1321 /* Mark this MUT as "in-progress". */
1322 mut->vfs_result = GNOME_VFS_NUM_ERRORS;
1323 g_tree_remove(_mut_priority_tree, mut);
1324 g_mutex_unlock(_mut_priority_mutex);
1326 printf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
1327 mut->repo->name, mut->zoom, mut->tilex, mut->tiley);
1329 layer_tile = mut->repo != _curr_repo && repo_is_layer (_curr_repo, mut->repo);
1331 if (mut->repo != _curr_repo && !layer_tile)
1333 /* Do nothing, except report that there is no error. */
1334 mut->vfs_result = GNOME_VFS_OK;
1336 else if(mut->update_type == MAP_UPDATE_DELETE)
1338 /* Easy - just delete the entry from the database. We don't care
1339 * about failures (sorry). */
1340 if(MAPDB_EXISTS(mut->repo))
1341 mapdb_delete(mut->repo, mut->zoom, mut->tilex, mut->tiley);
1343 /* Report that there is no error. */
1344 mut->vfs_result = GNOME_VFS_OK;
1346 else for(retries = mut->repo->layer_level
1347 ? 1 : INITIAL_DOWNLOAD_RETRIES; retries > 0; --retries)
1352 GdkPixbufLoader *loader;
1354 gint zoom, tilex, tiley;
1355 GError *error = NULL;
1357 /* First check for existence. */
1358 if(mut->update_type == MAP_UPDATE_ADD)
1360 /* We don't want to overwrite, so check for existence. */
1361 /* Map already exists, and we're not going to overwrite. */
1362 if(mapdb_exists(mut->repo, mut->zoom,
1363 mut->tilex,mut->tiley))
1365 /* Report that there is no error. */
1366 mut->vfs_result = GNOME_VFS_OK;
1371 /* First, construct the URL from which we will get the data. */
1372 src_url = map_construct_url(mut->repo, mut->zoom,
1373 mut->tilex, mut->tiley);
1375 /* Now, attempt to read the entire contents of the URL. */
1376 mut->vfs_result = gnome_vfs_read_entire_file(
1377 src_url, &size, &bytes);
1379 if(mut->vfs_result != GNOME_VFS_OK || !bytes)
1382 printf("Error reading URL: %s\n",
1383 gnome_vfs_result_to_string(mut->vfs_result));
1387 /* usleep(100000); DEBUG */
1389 /* Attempt to parse the bytes into a pixbuf. */
1390 loader = gdk_pixbuf_loader_new();
1391 gdk_pixbuf_loader_write(loader, bytes, size, NULL);
1392 gdk_pixbuf_loader_close(loader, &error);
1393 if(error || (NULL == (mut->pixbuf = g_object_ref(
1394 gdk_pixbuf_loader_get_pixbuf(loader)))))
1396 mut->vfs_result = GNOME_VFS_NUM_ERRORS;
1398 g_object_unref(mut->pixbuf);
1401 g_object_unref(loader);
1402 printf("Error parsing pixbuf: %s\n",
1403 error ? error->message : "?");
1406 g_object_unref(loader);
1408 /* Copy database-relevant mut data before we release it. */
1414 /* Pass the mut to the GTK thread for redrawing, but only if a
1415 * redraw isn't already in the pipeline. */
1416 if(mut->refresh_latch)
1418 /* Wait until the latch is open. */
1419 g_mutex_lock(mut->refresh_latch->mutex);
1420 while(!mut->refresh_latch->is_open)
1422 g_cond_wait(mut->refresh_latch->cond,
1423 mut->refresh_latch->mutex);
1425 /* Latch is open. Decrement the number of waiters and
1426 * check if we're the last waiter to run. */
1427 if(mut->refresh_latch->is_done_adding_tasks)
1429 if(++mut->refresh_latch->num_done
1430 == mut->refresh_latch->num_tasks)
1432 /* Last waiter. Free the latch resources. */
1433 g_mutex_unlock(mut->refresh_latch->mutex);
1434 g_cond_free(mut->refresh_latch->cond);
1435 g_mutex_free(mut->refresh_latch->mutex);
1436 g_slice_free(ThreadLatch, mut->refresh_latch);
1437 mut->refresh_latch = NULL;
1441 /* Not the last waiter. Signal the next waiter.*/
1442 g_cond_signal(mut->refresh_latch->cond);
1443 g_mutex_unlock(mut->refresh_latch->mutex);
1447 g_mutex_unlock(mut->refresh_latch->mutex);
1450 g_idle_add_full(G_PRIORITY_HIGH_IDLE,
1451 (GSourceFunc)map_download_refresh_idle, mut, NULL);
1452 refresh_sent = TRUE;
1454 /* DO NOT USE mut FROM THIS POINT ON. */
1456 /* Also attempt to add to the database. */
1457 if(MAPDB_EXISTS(repo) && !mapdb_update(repo, zoom,
1458 tilex, tiley, bytes, size)) {
1459 g_idle_add((GSourceFunc)map_handle_error,
1460 _("Error saving map to disk - disk full?"));
1469 g_idle_add_full(G_PRIORITY_HIGH_IDLE,
1470 (GSourceFunc)map_download_refresh_idle, mut, NULL);
1473 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
1478 mut_exists_hashfunc(const MapUpdateTask *a)
1480 gint sum = a->zoom + a->tilex + a->tiley + a->update_type + a->layer_level;
1481 return g_int_hash(&sum);
1485 mut_exists_equalfunc(const MapUpdateTask *a, const MapUpdateTask *b)
1487 return (a->tilex == b->tilex
1488 && a->tiley == b->tiley
1489 && a->zoom == b->zoom
1490 && a->update_type == b->update_type
1491 && a->layer_level == b->layer_level);
1495 mut_priority_comparefunc(const MapUpdateTask *a, const MapUpdateTask *b)
1497 /* The update_type enum is sorted in order of ascending priority. */
1498 gint diff = (b->update_type - a->update_type);
1501 diff = (b->batch_id - a->batch_id); /* More recent ones first. */
1504 diff = (a->priority - b->priority); /* Lower priority numbers first. */
1507 diff = (a->layer_level - b->layer_level); /* Lower layers first. */
1511 /* At this point, we don't care, so just pick arbitrarily. */
1512 diff = (a->tilex - b->tilex);
1515 diff = (a->tiley - b->tiley);
1518 return (a->zoom - b->zoom);
1522 repoman_dialog_select(GtkWidget *widget, RepoManInfo *rmi)
1524 printf("%s()\n", __PRETTY_FUNCTION__);
1525 gint curr_index = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
1526 gtk_notebook_set_current_page(GTK_NOTEBOOK(rmi->notebook), curr_index);
1527 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1532 repoman_dialog_browse(GtkWidget *widget, BrowseInfo *browse_info)
1536 printf("%s()\n", __PRETTY_FUNCTION__);
1538 dialog = GTK_WIDGET(
1539 hildon_file_chooser_dialog_new(GTK_WINDOW(browse_info->dialog),
1540 GTK_FILE_CHOOSER_ACTION_SAVE));
1542 gtk_file_chooser_set_uri(GTK_FILE_CHOOSER(dialog),
1543 gtk_entry_get_text(GTK_ENTRY(browse_info->txt)));
1545 /* Work around a bug in HildonFileChooserDialog. */
1546 basename = g_path_get_basename(
1547 gtk_entry_get_text(GTK_ENTRY(browse_info->txt)));
1548 g_object_set(G_OBJECT(dialog), "autonaming", FALSE, NULL);
1549 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), basename);
1551 if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)))
1553 gchar *filename = gtk_file_chooser_get_filename(
1554 GTK_FILE_CHOOSER(dialog));
1555 gtk_entry_set_text(GTK_ENTRY(browse_info->txt), filename);
1559 gtk_widget_destroy(dialog);
1561 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1566 repoman_compact_complete_idle(CompactInfo *ci)
1568 printf("%s()\n", __PRETTY_FUNCTION__);
1570 gtk_widget_destroy(GTK_WIDGET(ci->banner));
1571 popup_error(ci->dialog, ci->status_msg);
1572 gtk_widget_destroy(ci->dialog);
1575 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
1580 thread_repoman_compact(CompactInfo *ci)
1582 printf("%s()\n", __PRETTY_FUNCTION__);
1587 if(SQLITE_OK != (sqlite3_open(ci->db_filename, &db)))
1588 ci->status_msg = _("Failed to open map database for compacting.");
1591 if(SQLITE_OK != sqlite3_exec(db, "vacuum;", NULL, NULL, NULL))
1592 ci->status_msg = _("An error occurred while trying to "
1593 "compact the database.");
1595 ci->status_msg = _("Successfully compacted database.");
1602 if(!(db = gdbm_open((gchar*)ci->db_filename, 0, GDBM_WRITER | GDBM_FAST,
1604 ci->status_msg = _("Failed to open map database for compacting.");
1607 if(gdbm_reorganize(db))
1608 ci->status_msg = _("An error occurred while trying to "
1609 "compact the database.");
1611 ci->status_msg = _("Successfully compacted database.");
1616 g_idle_add((GSourceFunc)repoman_compact_complete_idle, ci);
1618 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1622 repoman_dialog_compact(GtkWidget *widget, RepoEditInfo *rei)
1626 printf("%s()\n", __PRETTY_FUNCTION__);
1628 ci = g_new0(CompactInfo, 1);
1630 ci->dialog = gtk_dialog_new_with_buttons(_("Compact Database"),
1631 GTK_WINDOW(rei->browse_info.dialog), GTK_DIALOG_MODAL,
1632 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1633 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1636 sw = gtk_scrolled_window_new (NULL, NULL);
1637 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
1638 GTK_SHADOW_ETCHED_IN);
1639 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
1642 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(ci->dialog)->vbox),
1645 gtk_container_add(GTK_CONTAINER(sw), ci->txt = gtk_text_view_new());
1646 gtk_text_view_set_editable(GTK_TEXT_VIEW(ci->txt), FALSE);
1647 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(ci->txt), FALSE);
1648 gtk_text_buffer_set_text(
1649 gtk_text_view_get_buffer(GTK_TEXT_VIEW(ci->txt)),
1650 _("Generally, deleted maps create an empty space in the "
1651 "database that is later reused when downloading new maps. "
1652 "Compacting the database reorganizes it such that all "
1653 "that blank space is eliminated. This is the only way "
1654 "that the size of the database can decrease.\n"
1655 "This reorganization requires creating a new file and "
1656 "inserting all the maps in the old database file into the "
1657 "new file. The new file is then renamed to the same name "
1658 "as the old file and dbf is updated to contain all the "
1659 "correct information about the new file. Note that this "
1660 "can require free space on disk of an amount up to the size "
1661 "of the map database.\n"
1662 "This process may take several minutes, especially if "
1663 "your map database is large. As a rough estimate, you can "
1664 "expect to wait approximately 2-5 seconds per megabyte of "
1665 "map data (34-85 minutes per gigabyte). There is no progress "
1666 "indicator, although you can watch the new file grow in any "
1667 "file manager. Do not attempt to close Maemo Mapper while "
1668 "the compacting operation is in progress."),
1672 gtk_text_buffer_get_iter_at_offset(
1673 gtk_text_view_get_buffer(GTK_TEXT_VIEW(ci->txt)),
1675 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(ci->txt),
1676 &iter, 0.0, FALSE, 0, 0);
1679 gtk_widget_set_size_request(GTK_WIDGET(sw), 600, 200);
1680 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(ci->txt), GTK_WRAP_WORD);
1682 gtk_widget_show_all(ci->dialog);
1684 if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(ci->dialog)))
1686 gtk_widget_set_sensitive(GTK_DIALOG(ci->dialog)->action_area, FALSE);
1687 ci->db_filename = gtk_entry_get_text(GTK_ENTRY(rei->txt_db_filename));
1688 ci->is_sqlite = rei->is_sqlite;
1689 ci->banner = hildon_banner_show_animation(ci->dialog, NULL,
1690 _("Compacting database..."));
1692 g_thread_create((GThreadFunc)thread_repoman_compact, ci, FALSE, NULL);
1696 gtk_widget_destroy(ci->dialog);
1699 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1703 repoman_dialog_rename(GtkWidget *widget, RepoManInfo *rmi)
1705 static GtkWidget *hbox = NULL;
1706 static GtkWidget *label = NULL;
1707 static GtkWidget *txt_name = NULL;
1708 static GtkWidget *dialog = NULL;
1709 printf("%s()\n", __PRETTY_FUNCTION__);
1713 dialog = gtk_dialog_new_with_buttons(_("New Name"),
1714 GTK_WINDOW(rmi->dialog), GTK_DIALOG_MODAL,
1715 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1716 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1719 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
1720 hbox = gtk_hbox_new(FALSE, 4), FALSE, FALSE, 4);
1722 gtk_box_pack_start(GTK_BOX(hbox),
1723 label = gtk_label_new(_("Name")),
1725 gtk_box_pack_start(GTK_BOX(hbox),
1726 txt_name = gtk_entry_new(),
1731 gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
1732 RepoEditInfo *rei = g_list_nth_data(rmi->repo_edits, active);
1733 gtk_entry_set_text(GTK_ENTRY(txt_name), rei->name);
1736 gtk_widget_show_all(dialog);
1738 while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
1740 gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
1741 RepoEditInfo *rei = g_list_nth_data(rmi->repo_edits, active);
1743 rei->name = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_name)));
1744 gtk_combo_box_insert_text(GTK_COMBO_BOX(rmi->cmb_repos),
1745 active, g_strdup(rei->name));
1746 gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos), active);
1747 gtk_combo_box_remove_text(GTK_COMBO_BOX(rmi->cmb_repos), active + 1);
1751 gtk_widget_hide(dialog);
1753 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1758 repoman_delete(RepoManInfo *rmi, gint index)
1760 gtk_combo_box_remove_text(GTK_COMBO_BOX(rmi->cmb_repos), index);
1761 gtk_notebook_remove_page(GTK_NOTEBOOK(rmi->notebook), index);
1762 rmi->repo_edits = g_list_remove_link(
1764 g_list_nth(rmi->repo_edits, index));
1768 repoman_dialog_delete(GtkWidget *widget, RepoManInfo *rmi, gint index)
1772 printf("%s()\n", __PRETTY_FUNCTION__);
1774 if(gtk_tree_model_iter_n_children(GTK_TREE_MODEL(
1775 gtk_combo_box_get_model(GTK_COMBO_BOX(rmi->cmb_repos))),
1778 popup_error(rmi->dialog,
1779 _("Cannot delete the last repository - there must be at"
1780 " lease one repository."));
1781 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1785 snprintf(buffer, sizeof(buffer), "%s:\n%s\n",
1786 _("Confirm delete of repository"),
1787 gtk_combo_box_get_active_text(GTK_COMBO_BOX(rmi->cmb_repos)));
1789 confirm = hildon_note_new_confirmation(GTK_WINDOW(rmi->dialog),buffer);
1791 if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
1793 gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
1794 repoman_delete(rmi, active);
1795 gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos),
1799 gtk_widget_destroy(confirm);
1804 static RepoEditInfo*
1805 repoman_dialog_add_repo(RepoManInfo *rmi, gchar *name, gboolean is_sqlite)
1811 RepoEditInfo *rei = g_new0(RepoEditInfo, 1);
1812 printf("%s(%s, %d)\n", __PRETTY_FUNCTION__, name, is_sqlite);
1815 rei->is_sqlite = is_sqlite;
1818 gtk_notebook_append_page(GTK_NOTEBOOK(rmi->notebook),
1819 vbox = gtk_vbox_new(FALSE, 4),
1820 gtk_label_new(name));
1822 /* Prevent destruction of notebook page, because the destruction causes
1823 * a seg fault (!?!?) */
1824 gtk_object_ref(GTK_OBJECT(vbox));
1826 gtk_box_pack_start(GTK_BOX(vbox),
1827 table = gtk_table_new(2, 2, FALSE),
1829 /* Map download URI. */
1830 gtk_table_attach(GTK_TABLE(table),
1831 label = gtk_label_new(_("URL Format")),
1832 0, 1, 0, 1, GTK_FILL, 0, 2, 0);
1833 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1834 gtk_table_attach(GTK_TABLE(table),
1835 rei->txt_url = gtk_entry_new(),
1836 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 0);
1838 /* Map Directory. */
1839 gtk_table_attach(GTK_TABLE(table),
1840 label = gtk_label_new(_("Cache DB")),
1841 0, 1, 1, 2, GTK_FILL, 0, 2, 0);
1842 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1843 gtk_table_attach(GTK_TABLE(table),
1844 hbox = gtk_hbox_new(FALSE, 4),
1845 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 0);
1846 gtk_box_pack_start(GTK_BOX(hbox),
1847 rei->txt_db_filename = gtk_entry_new(),
1849 gtk_box_pack_start(GTK_BOX(hbox),
1850 rei->btn_browse = gtk_button_new_with_label(_("Browse...")),
1852 gtk_box_pack_start(GTK_BOX(hbox),
1853 rei->btn_compact = gtk_button_new_with_label(_("Compact...")),
1856 /* Initialize cache dir */
1858 gchar buffer[BUFFER_SIZE];
1859 snprintf(buffer, sizeof(buffer), "%s.%s", name,
1860 is_sqlite ? "sqlite" : "gdbm");
1861 gchar *db_base = gnome_vfs_expand_initial_tilde(
1862 REPO_DEFAULT_CACHE_BASE);
1863 gchar *db_filename = gnome_vfs_uri_make_full_from_relative(
1865 gtk_entry_set_text(GTK_ENTRY(rei->txt_db_filename), db_filename);
1866 g_free(db_filename);
1870 gtk_box_pack_start(GTK_BOX(vbox),
1871 table = gtk_table_new(3, 2, FALSE),
1874 /* Download Zoom Steps. */
1875 gtk_table_attach(GTK_TABLE(table),
1876 label = gtk_label_new(_("Download Zoom Steps")),
1877 0, 1, 0, 1, GTK_FILL, 0, 2, 0);
1878 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1879 gtk_table_attach(GTK_TABLE(table),
1880 label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
1881 1, 2, 0, 1, GTK_FILL, 0, 2, 0);
1882 gtk_container_add(GTK_CONTAINER(label),
1883 rei->num_dl_zoom_steps = hildon_controlbar_new());
1884 hildon_controlbar_set_range(
1885 HILDON_CONTROLBAR(rei->num_dl_zoom_steps), 1, 4);
1886 hildon_controlbar_set_value(HILDON_CONTROLBAR(rei->num_dl_zoom_steps),
1887 REPO_DEFAULT_DL_ZOOM_STEPS);
1888 force_min_visible_bars(HILDON_CONTROLBAR(rei->num_dl_zoom_steps), 1);
1890 /* Download Zoom Steps. */
1891 gtk_table_attach(GTK_TABLE(table),
1892 label = gtk_label_new(_("View Zoom Steps")),
1893 0, 1, 1, 2, GTK_FILL, 0, 2, 0);
1894 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1895 gtk_table_attach(GTK_TABLE(table),
1896 label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
1897 1, 2, 1, 2, GTK_FILL, 0, 2, 0);
1898 gtk_container_add(GTK_CONTAINER(label),
1899 rei->num_view_zoom_steps = hildon_controlbar_new());
1900 hildon_controlbar_set_range(
1901 HILDON_CONTROLBAR(rei->num_view_zoom_steps), 1, 4);
1902 hildon_controlbar_set_value(HILDON_CONTROLBAR(rei->num_view_zoom_steps),
1903 REPO_DEFAULT_VIEW_ZOOM_STEPS);
1904 force_min_visible_bars(HILDON_CONTROLBAR(rei->num_view_zoom_steps), 1);
1906 gtk_table_attach(GTK_TABLE(table),
1907 label = gtk_vseparator_new(),
1908 2, 3, 0, 2, GTK_FILL, GTK_FILL, 4, 0);
1911 gtk_table_attach(GTK_TABLE(table),
1912 rei->chk_double_size = gtk_check_button_new_with_label(
1913 _("Double Pixels")),
1914 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
1915 gtk_toggle_button_set_active(
1916 GTK_TOGGLE_BUTTON(rei->chk_double_size), FALSE);
1919 gtk_table_attach(GTK_TABLE(table),
1920 rei->chk_nextable = gtk_check_button_new_with_label(
1922 3, 4, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
1923 gtk_toggle_button_set_active(
1924 GTK_TOGGLE_BUTTON(rei->chk_nextable), TRUE);
1926 /* Downloadable Zoom Levels. */
1927 gtk_table_attach(GTK_TABLE(table),
1928 label = gtk_label_new(_("Downloadable Zooms:")),
1929 0, 1, 2, 3, GTK_FILL, 0, 2, 0);
1930 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1931 gtk_table_attach(GTK_TABLE(table),
1932 label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
1933 1, 4, 2, 3, GTK_FILL, 0, 2, 0);
1934 gtk_container_add(GTK_CONTAINER(label),
1935 hbox = gtk_hbox_new(FALSE, 4));
1936 gtk_box_pack_start(GTK_BOX(hbox),
1937 label = gtk_label_new(_("Min.")),
1939 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1940 gtk_box_pack_start(GTK_BOX(hbox),
1941 rei->num_min_zoom = hildon_number_editor_new(MIN_ZOOM, MAX_ZOOM),
1943 hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(rei->num_min_zoom), 4);
1944 gtk_box_pack_start(GTK_BOX(hbox),
1945 label = gtk_label_new(""),
1947 gtk_box_pack_start(GTK_BOX(hbox),
1948 label = gtk_label_new(_("Max.")),
1950 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1951 gtk_box_pack_start(GTK_BOX(hbox),
1952 rei->num_max_zoom = hildon_number_editor_new(MIN_ZOOM, MAX_ZOOM),
1954 hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(rei->num_max_zoom),20);
1956 rmi->repo_edits = g_list_append(rmi->repo_edits, rei);
1958 /* Connect signals. */
1959 rei->browse_info.dialog = rmi->dialog;
1960 rei->browse_info.txt = rei->txt_db_filename;
1961 g_signal_connect(G_OBJECT(rei->btn_browse), "clicked",
1962 G_CALLBACK(repoman_dialog_browse),
1964 g_signal_connect(G_OBJECT(rei->btn_compact), "clicked",
1965 G_CALLBACK(repoman_dialog_compact),
1968 gtk_widget_show_all(vbox);
1970 gtk_combo_box_append_text(GTK_COMBO_BOX(rmi->cmb_repos), name);
1971 gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos),
1972 gtk_tree_model_iter_n_children(GTK_TREE_MODEL(
1973 gtk_combo_box_get_model(GTK_COMBO_BOX(rmi->cmb_repos))),
1976 /* newly created repos keep this NULL in rei, indicating
1977 that layes cannot be added so far */
1980 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1985 repoman_dialog_new(GtkWidget *widget, RepoManInfo *rmi)
1987 static GtkWidget *table = NULL;
1988 static GtkWidget *label = NULL;
1989 static GtkWidget *txt_name = NULL;
1990 static GtkWidget *cmb_type = NULL;
1991 static GtkWidget *dialog = NULL;
1992 printf("%s()\n", __PRETTY_FUNCTION__);
1996 dialog = gtk_dialog_new_with_buttons(_("New Repository"),
1997 GTK_WINDOW(rmi->dialog), GTK_DIALOG_MODAL,
1998 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1999 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
2002 /* Enable the help button. */
2004 hildon_help_dialog_help_enable(
2006 ossohelp_dialog_help_enable(
2008 GTK_DIALOG(dialog), HELP_ID_NEWREPO, _osso);
2010 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
2011 table = gtk_table_new(2, 2, FALSE),
2014 /* Download Zoom Steps. */
2015 gtk_table_attach(GTK_TABLE(table),
2016 label = gtk_label_new(_("Name")),
2017 0, 1, 0, 1, GTK_FILL, 2, 4, 2);
2018 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
2020 gtk_table_attach(GTK_TABLE(table),
2021 txt_name = gtk_entry_new(),
2022 1, 2, 0, 1, GTK_FILL, 2, 4, 2);
2024 gtk_table_attach(GTK_TABLE(table),
2025 label = gtk_label_new(_("Type")),
2026 0, 1, 1, 2, GTK_FILL, 2, 4, 2);
2027 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
2029 gtk_table_attach(GTK_TABLE(table),
2030 cmb_type = gtk_combo_box_new_text(),
2031 1, 2, 1, 2, GTK_FILL, 2, 4, 2);
2033 gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_type),
2034 _("SQLite 3 (default)"));
2035 gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_type),
2036 _("GDBM (legacy)"));
2037 gtk_combo_box_set_active(GTK_COMBO_BOX(cmb_type), 0);
2040 gtk_entry_set_text(GTK_ENTRY(txt_name), "");
2042 gtk_widget_show_all(dialog);
2044 while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
2046 repoman_dialog_add_repo(rmi,
2047 g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_name))),
2048 gtk_combo_box_get_active(GTK_COMBO_BOX(cmb_type)) == 0);
2052 gtk_widget_hide(dialog);
2054 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2059 repoman_reset(GtkWidget *widget, RepoManInfo *rmi)
2062 printf("%s()\n", __PRETTY_FUNCTION__);
2064 confirm = hildon_note_new_confirmation(GTK_WINDOW(rmi->dialog),
2065 _("Replace all repositories with the default repository?"));
2067 if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
2069 /* First, delete all existing repositories. */
2070 while(rmi->repo_edits)
2071 repoman_delete(rmi, 0);
2073 /* Now, add the default repository. */
2074 repoman_dialog_add_repo(rmi, REPO_DEFAULT_NAME, TRUE);
2076 GTK_ENTRY(((RepoEditInfo*)rmi->repo_edits->data)->txt_url),
2077 REPO_DEFAULT_MAP_URI);
2079 gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos), 0);
2081 gtk_widget_destroy(confirm);
2083 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2091 printf("%s()\n", __PRETTY_FUNCTION__);
2093 confirm = hildon_note_new_confirmation(GTK_WINDOW(_window),
2094 _("Maemo Mapper will now download and add a list of "
2095 "possibly-duplicate repositories from the internet. "
2098 if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
2104 GnomeVFSResult vfs_result;
2105 printf("%s()\n", __PRETTY_FUNCTION__);
2107 /* Get repo config file from www.gnuite.com. */
2108 if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
2109 "http://www.gnuite.com/nokia770/maemo-mapper/"
2110 "repos-with-layers.txt",
2113 popup_error(_window,
2114 _("An error occurred while retrieving the repositories. "
2115 "The web service may be temporarily down."));
2116 g_printerr("Error while download repositories: %s\n",
2117 gnome_vfs_result_to_string(vfs_result));
2119 /* Parse each line as a reposotory. */
2122 RepoData *prev_repo = NULL;
2123 menu_maps_remove_repos();
2124 for(head = bytes; head && *head; head = tail)
2127 tail = strchr(head, '\n');
2130 rd = settings_parse_repo(head);
2131 if (rd->layer_level == 0) {
2132 _repo_list = g_list_append(_repo_list, rd);
2135 prev_repo->layers = rd;
2140 menu_maps_add_repos();
2144 gtk_widget_destroy(confirm);
2146 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2152 layer_get_page_index (RepoLayersInfo *rli, GtkTreeIter list_it)
2154 GtkTreePath *p1, *p2;
2158 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (rli->layers_store), &p);
2160 p1 = gtk_tree_model_get_path (GTK_TREE_MODEL (rli->layers_store), &list_it);
2161 p2 = gtk_tree_model_get_path (GTK_TREE_MODEL (rli->layers_store), &p);
2163 while (gtk_tree_path_compare (p1, p2) != 0) {
2164 gtk_tree_path_next (p2);
2168 gtk_tree_path_free (p1);
2169 gtk_tree_path_free (p2);
2176 layer_name_changed (GtkWidget *entry, LayerEditInfo *lei)
2179 GtkTreeSelection *selection;
2182 printf("%s()\n", __PRETTY_FUNCTION__);
2185 name = gtk_entry_get_text (GTK_ENTRY (entry));
2187 /* find selected entry in list view */
2188 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (lei->rli->layers_list));
2190 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
2191 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2195 gtk_list_store_set (lei->rli->layers_store, &iter, 0, name, -1);
2197 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2203 layer_dialog_browse (GtkWidget *widget, LayerEditInfo *lei)
2207 printf("%s()\n", __PRETTY_FUNCTION__);
2209 dialog = GTK_WIDGET(
2210 hildon_file_chooser_dialog_new(GTK_WINDOW(lei->rli->dialog),
2211 GTK_FILE_CHOOSER_ACTION_SAVE));
2213 gtk_file_chooser_set_uri(GTK_FILE_CHOOSER(dialog),
2214 gtk_entry_get_text(GTK_ENTRY(lei->txt_db)));
2216 /* Work around a bug in HildonFileChooserDialog. */
2217 basename = g_path_get_basename(
2218 gtk_entry_get_text(GTK_ENTRY(lei->txt_db)));
2219 g_object_set(G_OBJECT(dialog), "autonaming", FALSE, NULL);
2220 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), basename);
2222 if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)))
2224 gchar *filename = gtk_file_chooser_get_filename(
2225 GTK_FILE_CHOOSER(dialog));
2226 gtk_entry_set_text(GTK_ENTRY(lei->txt_db), filename);
2230 gtk_widget_destroy(dialog);
2232 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2238 static LayerEditInfo*
2239 repoman_layers_add_layer (RepoLayersInfo *rli, gchar* name)
2241 LayerEditInfo *lei = g_new (LayerEditInfo, 1);
2246 GtkWidget *btn_browse;
2247 GtkTreeIter layers_iter;
2249 printf("%s(%s)\n", __PRETTY_FUNCTION__, name);
2253 rli->layer_edits = g_list_append (rli->layer_edits, lei);
2255 gtk_notebook_append_page (GTK_NOTEBOOK (rli->notebook), vbox = gtk_vbox_new (FALSE, 4),
2256 gtk_label_new (name));
2258 gtk_box_pack_start (GTK_BOX (vbox), table = gtk_table_new (4, 2, FALSE),
2262 gtk_table_attach (GTK_TABLE (table), label = gtk_label_new (_("Name")),
2263 0, 1, 0, 1, GTK_FILL, 0, 2, 0);
2264 gtk_misc_set_alignment (GTK_MISC (label), 1.f, 0.5f);
2265 gtk_table_attach (GTK_TABLE (table), lei->txt_name = gtk_entry_new (),
2266 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 0);
2267 gtk_entry_set_text (GTK_ENTRY (lei->txt_name), name);
2270 g_signal_connect(G_OBJECT(lei->txt_name), "changed", G_CALLBACK(layer_name_changed), lei);
2273 gtk_table_attach (GTK_TABLE (table), label = gtk_label_new (_("URL")),
2274 0, 1, 1, 2, GTK_FILL, 0, 2, 0);
2275 gtk_misc_set_alignment (GTK_MISC (label), 1.f, 0.5f);
2276 gtk_table_attach (GTK_TABLE (table), lei->txt_url = gtk_entry_new (),
2277 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 0);
2280 gtk_table_attach (GTK_TABLE (table), label = gtk_label_new (_("Cache DB")),
2281 0, 1, 2, 3, GTK_FILL, 0, 2, 0);
2282 gtk_misc_set_alignment (GTK_MISC (label), 1.f, 0.5f);
2283 gtk_table_attach (GTK_TABLE (table), hbox2 = gtk_hbox_new (FALSE, 4),
2284 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 0);
2285 gtk_box_pack_start (GTK_BOX (hbox2), lei->txt_db = gtk_entry_new (),
2287 gtk_box_pack_start (GTK_BOX (hbox2), btn_browse = gtk_button_new_with_label (_("Browse...")),
2290 g_signal_connect(G_OBJECT(btn_browse), "clicked", G_CALLBACK(layer_dialog_browse), lei);
2293 gtk_table_attach (GTK_TABLE (table), label = gtk_label_new (_("Autofetch")),
2294 0, 1, 3, 4, GTK_FILL, 0, 2, 0);
2295 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
2296 gtk_table_attach (GTK_TABLE (table), hbox2 = gtk_hbox_new (FALSE, 4),
2297 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 0);
2298 gtk_box_pack_start (GTK_BOX (hbox2), lei->num_autofetch = hildon_number_editor_new (0, 120),
2300 gtk_box_pack_start (GTK_BOX (hbox2), label = gtk_label_new (_("min.")), FALSE, FALSE, 4);
2301 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
2304 gtk_box_pack_start (GTK_BOX (vbox), lei->chk_visible = gtk_check_button_new_with_label (_("Layer is visible")),
2307 gtk_widget_show_all (vbox);
2309 /* Side list view with layers */
2310 gtk_list_store_append (rli->layers_store, &layers_iter);
2311 gtk_list_store_set (rli->layers_store, &layers_iter, 0, name, -1);
2313 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2321 repoman_layers_new (GtkWidget *widget, RepoLayersInfo *rli)
2323 static GtkWidget *hbox = NULL;
2324 static GtkWidget *label = NULL;
2325 static GtkWidget *txt_name = NULL;
2326 static GtkWidget *dialog = NULL;
2327 printf("%s()\n", __PRETTY_FUNCTION__);
2331 dialog = gtk_dialog_new_with_buttons(_("New Layer"),
2332 GTK_WINDOW(rli->dialog), GTK_DIALOG_MODAL,
2333 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
2334 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
2337 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
2338 hbox = gtk_hbox_new(FALSE, 4), FALSE, FALSE, 4);
2340 gtk_box_pack_start(GTK_BOX(hbox),
2341 label = gtk_label_new(_("Name")),
2343 gtk_box_pack_start(GTK_BOX(hbox),
2344 txt_name = gtk_entry_new(),
2348 gtk_entry_set_text(GTK_ENTRY(txt_name), "");
2350 gtk_widget_show_all(dialog);
2352 while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
2354 repoman_layers_add_layer(rli,
2355 g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_name))));
2359 gtk_widget_hide(dialog);
2360 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2366 repoman_layers_del (GtkWidget *widget, RepoLayersInfo *rli)
2369 GtkTreeSelection *selection;
2372 printf("%s()\n", __PRETTY_FUNCTION__);
2374 /* delete list item */
2375 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (rli->layers_list));
2377 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
2378 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2382 index = layer_get_page_index (rli, iter);
2383 gtk_list_store_remove (rli->layers_store, &iter);
2385 rli->layer_edits = g_list_remove_link (rli->layer_edits, g_list_nth (rli->layer_edits, index));
2387 /* delete notebook page */
2388 gtk_notebook_remove_page (GTK_NOTEBOOK (rli->notebook), index);
2390 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2396 repoman_layers_up (GtkWidget *widget, RepoLayersInfo *rli)
2398 GtkTreeSelection *selection;
2399 GtkTreeIter iter, iter2;
2405 printf("%s()\n", __PRETTY_FUNCTION__);
2407 /* find selected entry in list view */
2408 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (rli->layers_list));
2410 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
2411 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2416 path = gtk_tree_model_get_path (GTK_TREE_MODEL (rli->layers_store), &iter);
2417 if (!gtk_tree_path_prev (path) || !gtk_tree_model_get_iter (GTK_TREE_MODEL (rli->layers_store), &iter, path)) {
2418 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2422 gtk_tree_path_free (path);
2425 gtk_list_store_move_before (rli->layers_store, &iter2, &iter);
2427 /* reorder notebook tabs */
2428 page = gtk_notebook_get_current_page (GTK_NOTEBOOK (rli->notebook));
2429 gtk_notebook_reorder_child (GTK_NOTEBOOK (rli->notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (rli->notebook), page), page-1);
2431 /* reorder layer edits */
2432 list_elem = g_list_nth (rli->layer_edits, page);
2433 lei = list_elem->data;
2434 rli->layer_edits = g_list_remove_link (rli->layer_edits, list_elem);
2435 rli->layer_edits = g_list_insert (rli->layer_edits, lei, page-1);
2437 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2443 repoman_layers_dn (GtkWidget *widget, RepoLayersInfo *rli)
2445 GtkTreeSelection *selection;
2446 GtkTreeIter iter, iter2;
2451 printf("%s()\n", __PRETTY_FUNCTION__);
2453 /* find selected entry in list view */
2454 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (rli->layers_list));
2456 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
2457 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2462 if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (rli->layers_store), &iter)) {
2463 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2468 gtk_list_store_move_after (rli->layers_store, &iter2, &iter);
2470 /* reorder notebook tabs */
2471 page = gtk_notebook_get_current_page (GTK_NOTEBOOK (rli->notebook));
2472 gtk_notebook_reorder_child (GTK_NOTEBOOK (rli->notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (rli->notebook), page), page+1);
2474 /* reorder layer edits */
2475 list_elem = g_list_nth (rli->layer_edits, page);
2476 lei = list_elem->data;
2477 rli->layer_edits = g_list_remove_link (rli->layer_edits, list_elem);
2478 rli->layer_edits = g_list_insert (rli->layer_edits, lei, page+1);
2480 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2486 repoman_layer_selected (GtkTreeSelection *selection, RepoLayersInfo *rli)
2490 printf("%s()\n", __PRETTY_FUNCTION__);
2492 if (!gtk_tree_selection_get_selected (selection, NULL, &cur)) {
2493 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2497 gtk_notebook_set_current_page (GTK_NOTEBOOK (rli->notebook), layer_get_page_index (rli, cur));
2499 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2505 repoman_layers(GtkWidget *widget, RepoManInfo *rmi)
2507 GtkWidget *hbox = NULL;
2508 GtkWidget *layers_vbox = NULL;
2509 GtkWidget *buttons_hbox = NULL;
2511 GtkCellRenderer *layers_rendeder = NULL;
2512 GtkTreeViewColumn *layers_column = NULL;
2513 GtkTreeSelection *selection;
2515 /* layers buttons */
2516 GtkWidget *btn_new = NULL;
2517 GtkWidget *btn_del = NULL;
2518 GtkWidget *btn_up = NULL;
2519 GtkWidget *btn_dn = NULL;
2521 const char* t_header = _("Manage layers [%s]");
2522 char* header = NULL;
2523 RepoEditInfo* rei = NULL;
2525 gint curr_repo_index = gtk_combo_box_get_active (GTK_COMBO_BOX (rmi->cmb_repos));
2528 printf("%s()\n", __PRETTY_FUNCTION__);
2530 if (curr_repo_index < 0) {
2531 vprintf("%s(): return FALSE (1)\n", __PRETTY_FUNCTION__);
2535 rei = g_list_nth_data (rmi->repo_edits, curr_repo_index);
2538 vprintf("%s(): return FALSE (2)\n", __PRETTY_FUNCTION__);
2542 /* check that rei have repo data structure. If it haven't, it means that repository have just
2543 added, so report about this */
2545 GtkWidget *msg = hildon_note_new_information ( GTK_WINDOW (rmi->dialog),
2546 _("You cannot add layers to not saved repository,\nsorry. So, press ok in repository manager\n"
2547 "and open this dialog again."));
2549 gtk_dialog_run (GTK_DIALOG (msg));
2550 gtk_widget_destroy (msg);
2552 vprintf("%s(): return FALSE (3)\n", __PRETTY_FUNCTION__);
2556 header = g_malloc (strlen (t_header) + strlen (rei->name));
2557 sprintf (header, t_header, rei->name);
2559 printf ("Creating dialog with header: %s\n", header);
2561 rli.layer_edits = NULL;
2562 rli.dialog = gtk_dialog_new_with_buttons (header, GTK_WINDOW (rmi->dialog), GTK_DIALOG_MODAL,
2563 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
2564 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
2566 rli.layers_store = gtk_list_store_new (1, G_TYPE_STRING);
2567 rli.layers_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (rli.layers_store));
2568 layers_rendeder = gtk_cell_renderer_text_new ();
2569 layers_column = gtk_tree_view_column_new_with_attributes ("Column", layers_rendeder, "text", 0, NULL);
2570 gtk_tree_view_append_column (GTK_TREE_VIEW (rli.layers_list), layers_column);
2572 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (rli.layers_list));
2574 frame = gtk_frame_new (NULL);
2575 gtk_container_add (GTK_CONTAINER (frame), rli.layers_list);
2576 gtk_widget_set_size_request (frame, -1, 100);
2578 /* beside layers list with have buttons on bottom */
2579 layers_vbox = gtk_vbox_new (FALSE, 4);
2580 gtk_box_pack_start (GTK_BOX (layers_vbox), frame, TRUE, TRUE, 0);
2581 gtk_box_pack_start (GTK_BOX (layers_vbox), buttons_hbox = gtk_hbox_new (FALSE, 4), FALSE, FALSE, 0);
2584 gtk_box_pack_start (GTK_BOX (buttons_hbox), btn_new = gtk_button_new_with_label (_("New")), FALSE, FALSE, 0);
2585 gtk_box_pack_start (GTK_BOX (buttons_hbox), btn_del = gtk_button_new_with_label (_("Del")), FALSE, FALSE, 0);
2586 gtk_box_pack_start (GTK_BOX (buttons_hbox), btn_up = gtk_button_new_with_label (_("Up")), FALSE, FALSE, 0);
2587 gtk_box_pack_start (GTK_BOX (buttons_hbox), btn_dn = gtk_button_new_with_label (_("Dn")), FALSE, FALSE, 0);
2590 g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(repoman_layer_selected), &rli);
2591 g_signal_connect(G_OBJECT(btn_new), "clicked", G_CALLBACK(repoman_layers_new), &rli);
2592 g_signal_connect(G_OBJECT(btn_del), "clicked", G_CALLBACK(repoman_layers_del), &rli);
2593 g_signal_connect(G_OBJECT(btn_up), "clicked", G_CALLBACK(repoman_layers_up), &rli);
2594 g_signal_connect(G_OBJECT(btn_dn), "clicked", G_CALLBACK(repoman_layers_dn), &rli);
2596 /* notebook with layers' attributes */
2597 rli.notebook = gtk_notebook_new ();
2599 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(rli.notebook), FALSE);
2600 gtk_notebook_set_show_border(GTK_NOTEBOOK(rli.notebook), FALSE);
2602 /* walk through all layers and add notebook pages */
2603 rd = rei->repo->layers;
2605 LayerEditInfo *lei = repoman_layers_add_layer (&rli, rd->name);
2607 gtk_entry_set_text (GTK_ENTRY (lei->txt_url), rd->url);
2608 gtk_entry_set_text (GTK_ENTRY (lei->txt_db), rd->db_filename);
2609 hildon_number_editor_set_value (HILDON_NUMBER_EDITOR (lei->num_autofetch), rd->layer_refresh_interval);
2610 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lei->chk_visible), rd->layer_enabled);
2615 /* pack all widgets together */
2616 hbox = gtk_hbox_new (FALSE, 4);
2618 gtk_box_pack_start (GTK_BOX (hbox), layers_vbox, TRUE, TRUE, 4);
2619 gtk_box_pack_start (GTK_BOX (hbox), rli.notebook, TRUE, TRUE, 4);
2621 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (rli.dialog)->vbox), hbox, FALSE, FALSE, 4);
2623 gtk_widget_show_all (rli.dialog);
2625 while (GTK_RESPONSE_ACCEPT == gtk_dialog_run (GTK_DIALOG (rli.dialog)))
2631 menu_layers_remove_repos ();
2633 /* iterate over notebook's pages and build layers */
2634 /* keep list in memory in case downloads use it (TODO: reference counting) */
2635 rdp = &rei->repo->layers;
2638 for (i = 0, curr = rli.layer_edits; curr; curr = curr->next, i++) {
2639 LayerEditInfo *lei = curr->data;
2641 rd = g_new0 (RepoData, 1);
2644 rd->name = g_strdup (gtk_entry_get_text (GTK_ENTRY (lei->txt_name)));
2645 rd->is_sqlite = rei->repo->is_sqlite;
2646 rd->url = g_strdup (gtk_entry_get_text (GTK_ENTRY (lei->txt_url)));
2647 rd->db_filename = g_strdup (gtk_entry_get_text (GTK_ENTRY (lei->txt_db)));
2648 rd->layer_enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (lei->chk_visible));
2649 rd->layer_refresh_interval = hildon_number_editor_get_value (HILDON_NUMBER_EDITOR (lei->num_autofetch));
2650 rd->layer_refresh_countdown = rd->layer_refresh_interval;
2651 rd->layer_level = i+1;
2653 rd->dl_zoom_steps = rei->repo->dl_zoom_steps;
2654 rd->view_zoom_steps = rei->repo->view_zoom_steps;
2655 rd->double_size = rei->repo->double_size;
2656 rd->nextable = rei->repo->nextable;
2657 rd->min_zoom = rei->repo->min_zoom;
2658 rd->max_zoom = rei->repo->max_zoom;
2664 menu_layers_add_repos ();
2665 repo_set_curr(_curr_repo);
2668 map_refresh_mark (TRUE);
2672 gtk_widget_destroy (rli.dialog);
2674 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2682 static RepoManInfo rmi;
2683 static GtkWidget *dialog = NULL;
2684 static GtkWidget *hbox = NULL;
2685 static GtkWidget *btn_rename = NULL;
2686 static GtkWidget *btn_delete = NULL;
2687 static GtkWidget *btn_new = NULL;
2688 static GtkWidget *btn_reset = NULL;
2689 static GtkWidget *btn_layers = NULL;
2690 gint i, curr_repo_index = 0;
2692 printf("%s()\n", __PRETTY_FUNCTION__);
2696 rmi.dialog = dialog = gtk_dialog_new_with_buttons(
2697 _("Manage Repositories"),
2698 GTK_WINDOW(_window), GTK_DIALOG_MODAL,
2699 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
2702 /* Enable the help button. */
2704 hildon_help_dialog_help_enable(
2706 ossohelp_dialog_help_enable(
2708 GTK_DIALOG(dialog), HELP_ID_REPOMAN, _osso);
2711 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
2712 btn_reset = gtk_button_new_with_label(_("Reset...")));
2713 g_signal_connect(G_OBJECT(btn_reset), "clicked",
2714 G_CALLBACK(repoman_reset), &rmi);
2716 /* Layers button. */
2717 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
2718 btn_layers = gtk_button_new_with_label(_("Layers...")));
2719 g_signal_connect(G_OBJECT(btn_layers), "clicked",
2720 G_CALLBACK(repoman_layers), &rmi);
2722 /* Cancel button. */
2723 gtk_dialog_add_button(GTK_DIALOG(dialog),
2724 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
2726 hbox = gtk_hbox_new(FALSE, 4);
2728 gtk_box_pack_start(GTK_BOX(hbox),
2729 rmi.cmb_repos = gtk_combo_box_new_text(), TRUE, TRUE, 4);
2731 gtk_box_pack_start(GTK_BOX(hbox),
2732 gtk_vseparator_new(), FALSE, FALSE, 4);
2733 gtk_box_pack_start(GTK_BOX(hbox),
2734 btn_rename = gtk_button_new_with_label(_("Rename...")),
2736 gtk_box_pack_start(GTK_BOX(hbox),
2737 btn_delete = gtk_button_new_with_label(_("Delete...")),
2739 gtk_box_pack_start(GTK_BOX(hbox),
2740 btn_new = gtk_button_new_with_label(_("New...")),
2743 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
2744 hbox, FALSE, FALSE, 4);
2746 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
2747 gtk_hseparator_new(), TRUE, TRUE, 4);
2748 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
2749 rmi.notebook = gtk_notebook_new(), TRUE, TRUE, 4);
2751 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(rmi.notebook), FALSE);
2752 gtk_notebook_set_show_border(GTK_NOTEBOOK(rmi.notebook), FALSE);
2754 rmi.repo_edits = NULL;
2756 /* Connect signals. */
2757 g_signal_connect(G_OBJECT(btn_rename), "clicked",
2758 G_CALLBACK(repoman_dialog_rename), &rmi);
2759 g_signal_connect(G_OBJECT(btn_delete), "clicked",
2760 G_CALLBACK(repoman_dialog_delete), &rmi);
2761 g_signal_connect(G_OBJECT(btn_new), "clicked",
2762 G_CALLBACK(repoman_dialog_new), &rmi);
2763 g_signal_connect(G_OBJECT(rmi.cmb_repos), "changed",
2764 G_CALLBACK(repoman_dialog_select), &rmi);
2767 /* Populate combo box and pages in notebook. */
2768 for(i = 0, curr = _repo_list; curr; curr = curr->next, i++)
2770 RepoData *rd = (RepoData*)curr->data;
2771 RepoEditInfo *rei = repoman_dialog_add_repo(&rmi, g_strdup(rd->name),
2774 /* store this to be able to walk through layers attached to repo */
2777 /* Initialize fields with data from the RepoData object. */
2778 gtk_entry_set_text(GTK_ENTRY(rei->txt_url), rd->url);
2779 gtk_entry_set_text(GTK_ENTRY(rei->txt_db_filename),
2781 hildon_controlbar_set_value(
2782 HILDON_CONTROLBAR(rei->num_dl_zoom_steps),
2784 hildon_controlbar_set_value(
2785 HILDON_CONTROLBAR(rei->num_view_zoom_steps),
2786 rd->view_zoom_steps);
2787 gtk_toggle_button_set_active(
2788 GTK_TOGGLE_BUTTON(rei->chk_double_size),
2790 gtk_toggle_button_set_active(
2791 GTK_TOGGLE_BUTTON(rei->chk_nextable),
2793 hildon_number_editor_set_value(
2794 HILDON_NUMBER_EDITOR(rei->num_min_zoom),
2796 hildon_number_editor_set_value(
2797 HILDON_NUMBER_EDITOR(rei->num_max_zoom),
2799 if(rd == _curr_repo)
2800 curr_repo_index = i;
2803 gtk_combo_box_set_active(GTK_COMBO_BOX(rmi.cmb_repos), curr_repo_index);
2804 gtk_notebook_set_current_page(GTK_NOTEBOOK(rmi.notebook), curr_repo_index);
2806 gtk_widget_show_all(dialog);
2808 while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
2810 /* Iterate through repos and verify each. */
2811 gboolean verified = TRUE;
2814 gchar *old_curr_repo_name = _curr_repo->name;
2816 for(i = 0, curr = rmi.repo_edits; curr; curr = curr->next, i++)
2818 /* Check the ranges for the min and max zoom levels. */
2819 RepoEditInfo *rei = curr->data;
2820 if(hildon_number_editor_get_value(
2821 HILDON_NUMBER_EDITOR(rei->num_max_zoom))
2822 < hildon_number_editor_get_value(
2823 HILDON_NUMBER_EDITOR(rei->num_min_zoom)))
2831 gtk_combo_box_set_active(GTK_COMBO_BOX(rmi.cmb_repos), i);
2833 _("Minimum Downloadable Zoom must be less than "
2834 "Maximum Downloadable Zoom."));
2838 /* We're good to replace. Remove old _repo_list menu items. */
2839 menu_maps_remove_repos();
2840 /* But keep the repo list in memory, in case downloads are using it. */
2843 /* Write new _repo_list. */
2844 curr_repo_index = gtk_combo_box_get_active(
2845 GTK_COMBO_BOX(rmi.cmb_repos));
2847 for(i = 0, curr = rmi.repo_edits; curr; curr = curr->next, i++)
2849 RepoEditInfo *rei = curr->data;
2850 RepoData *rd = g_new0(RepoData, 1);
2851 RepoData *rd0, **rd1;
2852 rd->name = g_strdup(rei->name);
2853 rd->is_sqlite = rei->is_sqlite;
2854 rd->url = g_strdup(gtk_entry_get_text(GTK_ENTRY(rei->txt_url)));
2855 rd->db_filename = gnome_vfs_expand_initial_tilde(
2856 gtk_entry_get_text(GTK_ENTRY(rei->txt_db_filename)));
2857 rd->dl_zoom_steps = hildon_controlbar_get_value(
2858 HILDON_CONTROLBAR(rei->num_dl_zoom_steps));
2859 rd->view_zoom_steps = hildon_controlbar_get_value(
2860 HILDON_CONTROLBAR(rei->num_view_zoom_steps));
2861 rd->double_size = gtk_toggle_button_get_active(
2862 GTK_TOGGLE_BUTTON(rei->chk_double_size));
2863 rd->nextable = gtk_toggle_button_get_active(
2864 GTK_TOGGLE_BUTTON(rei->chk_nextable));
2865 rd->min_zoom = hildon_number_editor_get_value(
2866 HILDON_NUMBER_EDITOR(rei->num_min_zoom));
2867 rd->max_zoom = hildon_number_editor_get_value(
2868 HILDON_NUMBER_EDITOR(rei->num_max_zoom));
2872 rd0 = rei->repo->layers;
2876 *rd1 = g_new0 (RepoData, 1);
2877 (*rd1)->name = rd0->name;
2878 (*rd1)->is_sqlite = rd0->is_sqlite;
2879 (*rd1)->url = rd0->url;
2880 (*rd1)->db_filename = rd0->db_filename;
2881 (*rd1)->layer_enabled = rd0->layer_enabled;
2882 (*rd1)->layer_refresh_interval = rd0->layer_refresh_interval;
2883 (*rd1)->layer_refresh_countdown = rd0->layer_refresh_countdown;
2884 (*rd1)->layer_level = rd0->layer_level;
2886 (*rd1)->dl_zoom_steps = rd0->dl_zoom_steps;
2887 (*rd1)->view_zoom_steps = rd0->view_zoom_steps;
2888 (*rd1)->double_size = rd0->double_size;
2889 (*rd1)->nextable = rd0->nextable;
2890 (*rd1)->min_zoom = rd0->min_zoom;
2891 (*rd1)->max_zoom = rd0->max_zoom;
2893 set_repo_type (*rd1);
2896 rd1 = &(*rd1)->layers;
2903 rd->layer_level = 0;
2906 _repo_list = g_list_append(_repo_list, rd);
2908 if(!_curr_repo && !strcmp(old_curr_repo_name, rd->name))
2910 else if(i == curr_repo_index)
2914 repo_set_curr((RepoData*)g_list_first(_repo_list)->data);
2915 menu_maps_add_repos();
2921 gtk_widget_hide(dialog);
2923 /* Clear out the notebook entries. */
2924 while(rmi.repo_edits)
2925 repoman_delete(&rmi, 0);
2927 map_set_zoom(_zoom); /* make sure we're at an appropriate zoom level. */
2928 map_refresh_mark (TRUE);
2930 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2935 mapman_by_area(gdouble start_lat, gdouble start_lon,
2936 gdouble end_lat, gdouble end_lon, MapmanInfo *mapman_info,
2937 MapUpdateType update_type,
2938 gint download_batch_id)
2940 gint start_unitx, start_unity, end_unitx, end_unity;
2945 printf("%s(%f, %f, %f, %f)\n", __PRETTY_FUNCTION__, start_lat, start_lon,
2948 latlon2unit(start_lat, start_lon, start_unitx, start_unity);
2949 latlon2unit(end_lat, end_lon, end_unitx, end_unity);
2951 /* Swap if they specified flipped lats or lons. */
2952 if(start_unitx > end_unitx)
2954 gint swap = start_unitx;
2955 start_unitx = end_unitx;
2958 if(start_unity > end_unity)
2960 gint swap = start_unity;
2961 start_unity = end_unity;
2965 /* First, get the number of maps to download. */
2966 for(z = 0; z <= MAX_ZOOM; ++z)
2968 if(gtk_toggle_button_get_active(
2969 GTK_TOGGLE_BUTTON(mapman_info->chk_zoom_levels[z])))
2971 gint start_tilex, start_tiley, end_tilex, end_tiley;
2972 start_tilex = unit2ztile(start_unitx, z);
2973 start_tiley = unit2ztile(start_unity, z);
2974 end_tilex = unit2ztile(end_unitx, z);
2975 end_tiley = unit2ztile(end_unity, z);
2976 num_maps += (end_tilex - start_tilex + 1)
2977 * (end_tiley - start_tiley + 1);
2981 if(update_type == MAP_UPDATE_DELETE)
2983 snprintf(buffer, sizeof(buffer), "%s %d %s", _("Confirm DELETION of"),
2984 num_maps, _("maps "));
2988 snprintf(buffer, sizeof(buffer),
2989 "%s %d %s\n(%s %.2f MB)\n", _("Confirm download of"),
2990 num_maps, _("maps"), _("up to about"),
2991 num_maps * (strstr(_curr_repo->url, "%s") ? 18e-3 : 6e-3));
2993 confirm = hildon_note_new_confirmation(
2994 GTK_WINDOW(mapman_info->dialog), buffer);
2996 if(GTK_RESPONSE_OK != gtk_dialog_run(GTK_DIALOG(confirm)))
2998 gtk_widget_destroy(confirm);
2999 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
3003 g_mutex_lock(_mut_priority_mutex);
3004 for(z = 0; z <= MAX_ZOOM; ++z)
3006 if(gtk_toggle_button_get_active(
3007 GTK_TOGGLE_BUTTON(mapman_info->chk_zoom_levels[z])))
3009 gint start_tilex, start_tiley, end_tilex, end_tiley;
3011 start_tilex = unit2ztile(start_unitx, z);
3012 start_tiley = unit2ztile(start_unity, z);
3013 end_tilex = unit2ztile(end_unitx, z);
3014 end_tiley = unit2ztile(end_unity, z);
3015 for(tiley = start_tiley; tiley <= end_tiley; tiley++)
3017 for(tilex = start_tilex; tilex <= end_tilex; tilex++)
3019 /* Make sure this tile is even possible. */
3020 if((unsigned)tilex < unit2ztile(WORLD_SIZE_UNITS, z)
3021 && (unsigned)tiley < unit2ztile(WORLD_SIZE_UNITS, z))
3023 RepoData* rd = _curr_repo;
3026 if (rd == _curr_repo
3027 || (rd->layer_enabled && MAPDB_EXISTS(rd)))
3028 mapdb_initiate_update(rd, z, tilex, tiley,
3029 update_type, download_batch_id,
3030 (abs(tilex - unit2tile(_next_center.unitx))
3031 +abs(tiley - unit2tile(_next_center.unity))),
3040 g_mutex_unlock(_mut_priority_mutex);
3042 gtk_widget_destroy(confirm);
3043 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
3048 mapman_by_route(MapmanInfo *mapman_info, MapUpdateType update_type,
3049 gint download_batch_id)
3052 gint prev_tilex, prev_tiley, num_maps = 0, z;
3055 gint radius = hildon_number_editor_get_value(
3056 HILDON_NUMBER_EDITOR(mapman_info->num_route_radius));
3057 printf("%s()\n", __PRETTY_FUNCTION__);
3059 /* First, get the number of maps to download. */
3060 for(z = 0; z <= MAX_ZOOM; ++z)
3062 if(gtk_toggle_button_get_active(
3063 GTK_TOGGLE_BUTTON(mapman_info->chk_zoom_levels[z])))
3067 for(curr = _route.head - 1; curr++ != _route.tail; )
3071 gint tilex = unit2ztile(curr->unitx, z);
3072 gint tiley = unit2ztile(curr->unity, z);
3073 if(tilex != prev_tilex || tiley != prev_tiley)
3076 num_maps += (abs((gint)tilex - prev_tilex) + 1)
3077 * (abs((gint)tiley - prev_tiley) + 1) - 1;
3085 num_maps *= 0.625 * pow(radius + 1, 1.85);
3087 if(update_type == MAP_UPDATE_DELETE)
3089 snprintf(buffer, sizeof(buffer), "%s %s %d %s",
3090 _("Confirm DELETION of"), _("about"),
3091 num_maps, _("maps "));
3095 snprintf(buffer, sizeof(buffer),
3096 "%s %s %d %s\n(%s %.2f MB)\n", _("Confirm download of"),
3098 num_maps, _("maps"), _("up to about"),
3099 num_maps * (strstr(_curr_repo->url, "%s") ? 18e-3 : 6e-3));
3101 confirm = hildon_note_new_confirmation(
3102 GTK_WINDOW(mapman_info->dialog), buffer);
3104 if(GTK_RESPONSE_OK != gtk_dialog_run(GTK_DIALOG(confirm)))
3106 gtk_widget_destroy(confirm);
3107 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
3111 /* Now, do the actual download. */
3112 g_mutex_lock(_mut_priority_mutex);
3113 for(z = 0; z <= MAX_ZOOM; ++z)
3115 if(gtk_toggle_button_get_active(
3116 GTK_TOGGLE_BUTTON(mapman_info->chk_zoom_levels[z])))
3120 for(curr = _route.head - 1; curr++ != _route.tail; )
3124 gint tilex = unit2ztile(curr->unitx, z);
3125 gint tiley = unit2ztile(curr->unity, z);
3126 if(tilex != prev_tilex || tiley != prev_tiley)
3128 gint minx, miny, maxx, maxy, x, y;
3131 minx = MIN(tilex, prev_tilex) - radius;
3132 miny = MIN(tiley, prev_tiley) - radius;
3133 maxx = MAX(tilex, prev_tilex) + radius;
3134 maxy = MAX(tiley, prev_tiley) + radius;
3138 minx = tilex - radius;
3139 miny = tiley - radius;
3140 maxx = tilex + radius;
3141 maxy = tiley + radius;
3143 for(x = minx; x <= maxx; x++)
3145 for(y = miny; y <= maxy; y++)
3147 /* Make sure this tile is even possible. */
3149 < unit2ztile(WORLD_SIZE_UNITS, z)
3151 < unit2ztile(WORLD_SIZE_UNITS, z))
3153 mapdb_initiate_update(_curr_repo, z, x, y,
3154 update_type, download_batch_id,
3155 (abs(tilex - unit2tile(
3156 _next_center.unitx))
3157 + abs(tiley - unit2tile(
3158 _next_center.unity))),
3170 g_mutex_unlock(_mut_priority_mutex);
3171 _route_dl_radius = radius;
3172 gtk_widget_destroy(confirm);
3173 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
3178 mapman_clear(GtkWidget *widget, MapmanInfo *mapman_info)
3181 printf("%s()\n", __PRETTY_FUNCTION__);
3182 if(gtk_notebook_get_current_page(GTK_NOTEBOOK(mapman_info->notebook)))
3183 /* This is the second page (the "Zoom" page) - clear the checks. */
3184 for(z = 0; z <= MAX_ZOOM; ++z)
3185 gtk_toggle_button_set_active(
3186 GTK_TOGGLE_BUTTON(mapman_info->chk_zoom_levels[z]), FALSE);
3189 /* This is the first page (the "Area" page) - clear the text fields. */
3190 gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_topleft_lat), "");
3191 gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_topleft_lon), "");
3192 gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_botright_lat), "");
3193 gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_botright_lon), "");
3195 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
3198 void mapman_update_state(GtkWidget *widget, MapmanInfo *mapman_info)
3200 printf("%s()\n", __PRETTY_FUNCTION__);
3201 gtk_widget_set_sensitive( mapman_info->chk_overwrite,
3202 gtk_toggle_button_get_active(
3203 GTK_TOGGLE_BUTTON(mapman_info->rad_download)));
3205 if(gtk_toggle_button_get_active(
3206 GTK_TOGGLE_BUTTON(mapman_info->rad_by_area)))
3207 gtk_widget_show(mapman_info->tbl_area);
3208 else if(gtk_notebook_get_n_pages(GTK_NOTEBOOK(mapman_info->notebook)) == 3)
3209 gtk_widget_hide(mapman_info->tbl_area);
3211 gtk_widget_set_sensitive(mapman_info->num_route_radius,
3212 gtk_toggle_button_get_active(
3213 GTK_TOGGLE_BUTTON(mapman_info->rad_by_route)));
3214 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
3220 static GtkWidget *dialog = NULL;
3221 static GtkWidget *vbox = NULL;
3222 static GtkWidget *hbox = NULL;
3223 static GtkWidget *table = NULL;
3224 static GtkWidget *label = NULL;
3225 static GtkWidget *button = NULL;
3226 static GtkWidget *lbl_gps_lat = NULL;
3227 static GtkWidget *lbl_gps_lon = NULL;
3228 static GtkWidget *lbl_center_lat = NULL;
3229 static GtkWidget *lbl_center_lon = NULL;
3230 static MapmanInfo mapman_info;
3231 static gint last_deg_format = 0;
3236 gint prev_degformat = _degformat;
3237 gint fallback_deg_format = _degformat;
3238 gdouble top_left_lat, top_left_lon, bottom_right_lat, bottom_right_lon;
3241 printf("%s()\n", __PRETTY_FUNCTION__);
3243 if(!MAPDB_EXISTS(_curr_repo))
3245 popup_error(_window, "To manage maps, you must set a valid repository "
3246 "database filename in the \"Manage Repositories\" dialog.");
3247 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
3251 // - If the coord system has changed then we need to update certain values
3253 /* Initialize to the bounds of the screen. */
3255 _center.unitx - pixel2unit(MAX(_view_width_pixels,
3256 _view_height_pixels) / 2),
3257 _center.unity - pixel2unit(MAX(_view_width_pixels,
3258 _view_height_pixels) / 2), top_left_lat, top_left_lon);
3260 BOUND(top_left_lat, -90.f, 90.f);
3261 BOUND(top_left_lon, -180.f, 180.f);
3265 _center.unitx + pixel2unit(MAX(_view_width_pixels,
3266 _view_height_pixels) / 2),
3267 _center.unity + pixel2unit(MAX(_view_width_pixels,
3268 _view_height_pixels) / 2), bottom_right_lat, bottom_right_lon);
3269 BOUND(bottom_right_lat, -90.f, 90.f);
3270 BOUND(bottom_right_lon, -180.f, 180.f);
3275 if(!coord_system_check_lat_lon (top_left_lat, top_left_lon, &fallback_deg_format))
3277 _degformat = fallback_deg_format;
3281 // top left is valid, also check bottom right
3282 if(!coord_system_check_lat_lon (bottom_right_lat, bottom_right_lon, &fallback_deg_format))
3284 _degformat = fallback_deg_format;
3289 if(_degformat != last_deg_format)
3291 last_deg_format = _degformat;
3293 if(dialog != NULL) gtk_widget_destroy(dialog);
3299 mapman_info.dialog = dialog = gtk_dialog_new_with_buttons(
3301 GTK_WINDOW(_window), GTK_DIALOG_MODAL,
3302 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
3305 /* Enable the help button. */
3307 hildon_help_dialog_help_enable(
3309 ossohelp_dialog_help_enable(
3311 GTK_DIALOG(mapman_info.dialog), HELP_ID_MAPMAN, _osso);
3314 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
3315 button = gtk_button_new_with_label(_("Clear")));
3316 g_signal_connect(G_OBJECT(button), "clicked",
3317 G_CALLBACK(mapman_clear), &mapman_info);
3319 /* Cancel button. */
3320 gtk_dialog_add_button(GTK_DIALOG(dialog),
3321 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
3323 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
3324 mapman_info.notebook = gtk_notebook_new(), TRUE, TRUE, 0);
3327 gtk_notebook_append_page(GTK_NOTEBOOK(mapman_info.notebook),
3328 vbox = gtk_vbox_new(FALSE, 2),
3329 label = gtk_label_new(_("Setup")));
3330 gtk_notebook_set_tab_label_packing(
3331 GTK_NOTEBOOK(mapman_info.notebook), vbox,
3332 FALSE, FALSE, GTK_PACK_START);
3334 gtk_box_pack_start(GTK_BOX(vbox),
3335 hbox = gtk_hbox_new(FALSE, 4),
3337 gtk_box_pack_start(GTK_BOX(hbox),
3338 mapman_info.rad_download = gtk_radio_button_new_with_label(
3339 NULL,_("Download Maps")),
3341 gtk_box_pack_start(GTK_BOX(hbox),
3342 label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
3344 gtk_container_add(GTK_CONTAINER(label),
3345 mapman_info.chk_overwrite
3346 = gtk_check_button_new_with_label(_("Overwrite"))),
3348 gtk_box_pack_start(GTK_BOX(vbox),
3349 mapman_info.rad_delete
3350 = gtk_radio_button_new_with_label_from_widget(
3351 GTK_RADIO_BUTTON(mapman_info.rad_download),
3355 gtk_box_pack_start(GTK_BOX(vbox),
3356 gtk_hseparator_new(),
3359 gtk_box_pack_start(GTK_BOX(vbox),
3360 mapman_info.rad_by_area
3361 = gtk_radio_button_new_with_label(NULL,
3362 _("By Area (see tab)")),
3364 gtk_box_pack_start(GTK_BOX(vbox),
3365 hbox = gtk_hbox_new(FALSE, 4),
3367 gtk_box_pack_start(GTK_BOX(hbox),
3368 mapman_info.rad_by_route
3369 = gtk_radio_button_new_with_label_from_widget(
3370 GTK_RADIO_BUTTON(mapman_info.rad_by_area),
3371 _("Along Route - Radius (tiles):")),
3373 gtk_box_pack_start(GTK_BOX(hbox),
3374 mapman_info.num_route_radius = hildon_number_editor_new(0,100),
3376 hildon_number_editor_set_value(
3377 HILDON_NUMBER_EDITOR(mapman_info.num_route_radius),
3382 gtk_notebook_append_page(GTK_NOTEBOOK(mapman_info.notebook),
3383 table = gtk_table_new(5, 5, FALSE),
3384 label = gtk_label_new(_("Zoom")));
3385 gtk_notebook_set_tab_label_packing(
3386 GTK_NOTEBOOK(mapman_info.notebook), table,
3387 FALSE, FALSE, GTK_PACK_START);
3388 gtk_table_attach(GTK_TABLE(table),
3389 label = gtk_label_new(
3390 _("Zoom Levels to Download: (0 = most detail)")),
3391 0, 4, 0, 1, GTK_FILL, 0, 4, 0);
3392 gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
3393 snprintf(buffer, sizeof(buffer), "%d", 0);
3394 gtk_table_attach(GTK_TABLE(table),
3395 mapman_info.chk_zoom_levels[0]
3396 = gtk_check_button_new_with_label(buffer),
3397 4, 5 , 0, 1, GTK_FILL, 0, 0, 0);
3398 for(z = 0; z < MAX_ZOOM; ++z)
3400 snprintf(buffer, sizeof(buffer), "%d", z + 1);
3401 gtk_table_attach(GTK_TABLE(table),
3402 mapman_info.chk_zoom_levels[z + 1]
3403 = gtk_check_button_new_with_label(buffer),
3404 z / 4, z / 4 + 1, z % 4 + 1, z % 4 + 2,
3409 gtk_notebook_append_page(GTK_NOTEBOOK(mapman_info.notebook),
3410 mapman_info.tbl_area = gtk_table_new(5, 3, FALSE),
3411 label = gtk_label_new(_("Area")));
3413 /* Label Columns. */
3414 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3415 label = gtk_label_new(DEG_FORMAT_ENUM_TEXT[_degformat].long_field_1),
3416 1, 2, 0, 1, GTK_FILL, 0, 4, 0);
3417 gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.5f);
3419 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3421 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3422 label = gtk_label_new(DEG_FORMAT_ENUM_TEXT[_degformat].long_field_2),
3423 2, 3, 0, 1, GTK_FILL, 0, 4, 0);
3424 gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.5f);
3428 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3429 label = gtk_label_new(_("GPS Location")),
3430 0, 1, 1, 2, GTK_FILL, 0, 4, 0);
3431 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
3432 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3433 lbl_gps_lat = gtk_label_new(""),
3434 1, 2, 1, 2, GTK_FILL, 0, 4, 0);
3435 gtk_label_set_selectable(GTK_LABEL(lbl_gps_lat), TRUE);
3436 gtk_misc_set_alignment(GTK_MISC(lbl_gps_lat), 1.f, 0.5f);
3438 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3440 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3441 lbl_gps_lon = gtk_label_new(""),
3442 2, 3, 1, 2, GTK_FILL, 0, 4, 0);
3443 gtk_label_set_selectable(GTK_LABEL(lbl_gps_lon), TRUE);
3444 gtk_misc_set_alignment(GTK_MISC(lbl_gps_lon), 1.f, 0.5f);
3448 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3449 label = gtk_label_new(_("View Center")),
3450 0, 1, 2, 3, GTK_FILL, 0, 4, 0);
3451 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
3452 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3453 lbl_center_lat = gtk_label_new(""),
3454 1, 2, 2, 3, GTK_FILL, 0, 4, 0);
3455 gtk_label_set_selectable(GTK_LABEL(lbl_center_lat), TRUE);
3456 gtk_misc_set_alignment(GTK_MISC(lbl_center_lat), 1.f, 0.5f);
3459 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3461 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3462 lbl_center_lon = gtk_label_new(""),
3463 2, 3, 2, 3, GTK_FILL, 0, 4, 0);
3464 gtk_label_set_selectable(GTK_LABEL(lbl_center_lon), TRUE);
3465 gtk_misc_set_alignment(GTK_MISC(lbl_center_lon), 1.f, 0.5f);
3468 /* default values for Top Left and Bottom Right are defined by the
3469 * rectangle of the current and the previous Center */
3472 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3473 label = gtk_label_new(_("Top-Left")),
3474 0, 1, 3, 4, GTK_FILL, 0, 4, 0);
3475 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
3476 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3477 mapman_info.txt_topleft_lat = gtk_entry_new(),
3478 1, 2, 3, 4, GTK_FILL, 0, 4, 0);
3479 gtk_entry_set_width_chars(GTK_ENTRY(mapman_info.txt_topleft_lat), 12);
3480 gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_topleft_lat), 1.f);
3481 #ifdef MAEMO_CHANGES
3482 g_object_set(G_OBJECT(mapman_info.txt_topleft_lat),
3484 "hildon-input-mode",
3485 HILDON_GTK_INPUT_MODE_FULL, NULL);
3487 HILDON_INPUT_MODE_HINT,
3488 HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL, NULL);
3489 g_object_set(G_OBJECT(mapman_info.txt_topleft_lat),
3495 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3497 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3498 mapman_info.txt_topleft_lon = gtk_entry_new(),
3499 2, 3, 3, 4, GTK_FILL, 0, 4, 0);
3500 gtk_entry_set_width_chars(GTK_ENTRY(mapman_info.txt_topleft_lon), 12);
3501 gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_topleft_lon), 1.f);
3502 #ifdef MAEMO_CHANGES
3503 g_object_set(G_OBJECT(mapman_info.txt_topleft_lon),
3505 "hildon-input-mode",
3506 HILDON_GTK_INPUT_MODE_FULL, NULL);
3508 HILDON_INPUT_MODE_HINT,
3509 HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL, NULL);
3510 g_object_set(G_OBJECT(mapman_info.txt_topleft_lon),
3519 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3520 label = gtk_label_new(_("Bottom-Right")),
3521 0, 1, 4, 5, GTK_FILL, 0, 4, 0);
3522 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
3523 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3524 mapman_info.txt_botright_lat = gtk_entry_new(),
3525 1, 2, 4, 5, GTK_FILL, 0, 4, 0);
3526 gtk_entry_set_width_chars(GTK_ENTRY(mapman_info.txt_botright_lat), 12);
3527 gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_botright_lat), 1.f);
3528 #ifdef MAEMO_CHANGES
3529 g_object_set(G_OBJECT(mapman_info.txt_botright_lat),
3531 "hildon-input-mode",
3532 HILDON_GTK_INPUT_MODE_FULL, NULL);
3534 HILDON_INPUT_MODE_HINT,
3535 HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL, NULL);
3536 g_object_set(G_OBJECT(mapman_info.txt_botright_lat),
3542 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3544 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3545 mapman_info.txt_botright_lon = gtk_entry_new(),
3546 2, 3, 4, 5, GTK_FILL, 0, 4, 0);
3547 gtk_entry_set_width_chars(GTK_ENTRY(mapman_info.txt_botright_lon), 12);
3548 gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_botright_lon), 1.f);
3549 #ifdef MAEMO_CHANGES
3550 g_object_set(G_OBJECT(mapman_info.txt_botright_lon),
3552 "hildon-input-mode",
3553 HILDON_GTK_INPUT_MODE_FULL, NULL);
3555 HILDON_INPUT_MODE_HINT,
3556 HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL, NULL);
3557 g_object_set(G_OBJECT(mapman_info.txt_botright_lon),
3565 /* Default action is to download by area. */
3566 gtk_toggle_button_set_active(
3567 GTK_TOGGLE_BUTTON(mapman_info.rad_by_area), TRUE);
3569 g_signal_connect(G_OBJECT(mapman_info.rad_download), "clicked",
3570 G_CALLBACK(mapman_update_state), &mapman_info);
3571 g_signal_connect(G_OBJECT(mapman_info.rad_delete), "clicked",
3572 G_CALLBACK(mapman_update_state), &mapman_info);
3573 g_signal_connect(G_OBJECT(mapman_info.rad_by_area), "clicked",
3574 G_CALLBACK(mapman_update_state), &mapman_info);
3575 g_signal_connect(G_OBJECT(mapman_info.rad_by_route), "clicked",
3576 G_CALLBACK(mapman_update_state), &mapman_info);
3579 /* Initialize fields. Do no use g_ascii_formatd; these strings will be
3580 * output (and parsed) as locale-dependent. */
3582 gtk_widget_set_sensitive(mapman_info.rad_by_route,
3583 _route.head != _route.tail);
3588 format_lat_lon(_gps.lat, _gps.lon, buffer1, buffer2);
3589 //lat_format(_gps.lat, buffer);
3590 gtk_label_set_text(GTK_LABEL(lbl_gps_lat), buffer1);
3591 //lon_format(_gps.lon, buffer);
3592 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3593 gtk_label_set_text(GTK_LABEL(lbl_gps_lon), buffer2);
3595 unit2latlon(_center.unitx, _center.unity, lat, lon);
3597 format_lat_lon(lat, lon, buffer1, buffer2);
3598 //lat_format(lat, buffer);
3599 gtk_label_set_text(GTK_LABEL(lbl_center_lat), buffer1);
3600 //lon_format(lon, buffer);
3601 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3602 gtk_label_set_text(GTK_LABEL(lbl_center_lon), buffer2);
3604 format_lat_lon(top_left_lat, top_left_lon, buffer1, buffer2);
3606 gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_topleft_lat), buffer1);
3608 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3609 gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_topleft_lon), buffer2);
3611 format_lat_lon(bottom_right_lat, bottom_right_lon, buffer1, buffer2);
3612 //lat_format(lat, buffer);
3613 gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_botright_lat), buffer1);
3614 //lon_format(lon, buffer);
3615 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3616 gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_botright_lon), buffer2);
3618 /* Initialize zoom levels. */
3621 for(i = 0; i <= MAX_ZOOM; i++)
3623 gtk_toggle_button_set_active(
3624 GTK_TOGGLE_BUTTON(mapman_info.chk_zoom_levels[i]), FALSE);
3627 gtk_toggle_button_set_active(
3628 GTK_TOGGLE_BUTTON(mapman_info.chk_zoom_levels[
3629 _zoom + (_curr_repo->double_size ? 1 : 0)]), TRUE);
3631 gtk_widget_show_all(dialog);
3633 mapman_update_state(NULL, &mapman_info);
3635 if(_curr_repo->type != REPOTYPE_NONE)
3637 gtk_widget_set_sensitive(mapman_info.rad_download, TRUE);
3641 gtk_widget_set_sensitive(mapman_info.rad_download, FALSE);
3643 _("NOTE: You must set a Map URI in the current repository in "
3644 "order to download maps."));
3647 while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
3649 MapUpdateType update_type;
3650 static gint8 download_batch_id = INT8_MIN;
3652 if(gtk_toggle_button_get_active(
3653 GTK_TOGGLE_BUTTON(mapman_info.rad_delete)))
3654 update_type = MAP_UPDATE_DELETE;
3655 else if(gtk_toggle_button_get_active(
3656 GTK_TOGGLE_BUTTON(mapman_info.chk_overwrite)))
3657 update_type = MAP_UPDATE_OVERWRITE;
3659 update_type = MAP_UPDATE_ADD;
3661 ++download_batch_id;
3662 if(gtk_toggle_button_get_active(
3663 GTK_TOGGLE_BUTTON(mapman_info.rad_by_route)))
3665 if(mapman_by_route(&mapman_info, update_type, download_batch_id))
3670 const gchar *text_lon, *text_lat;
3671 //gchar *error_check;
3672 gdouble start_lat, start_lon, end_lat, end_lon;
3674 text_lat = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lat));
3675 text_lon = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lon));
3677 if(!parse_coords(text_lat, text_lon, &start_lat, &start_lon))
3679 popup_error(dialog, _("Invalid Top-Left coordinate specified"));
3683 text_lat = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_botright_lat));
3684 text_lon = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_botright_lon));
3686 if(!parse_coords(text_lat, text_lon, &end_lat, &end_lon))
3688 popup_error(dialog, _("Invalid Bottom-Right coordinate specified"));
3694 if(mapman_by_area(start_lat, start_lon, end_lat, end_lon,
3695 &mapman_info, update_type, download_batch_id))
3700 gtk_widget_hide(dialog);
3702 _degformat = prev_degformat;
3704 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
3709 /* changes visibility of current repo's layers to it's previous state */
3710 void maps_toggle_visible_layers ()
3712 RepoData *rd = _curr_repo;
3713 gboolean changed = FALSE;
3715 printf("%s()\n", __PRETTY_FUNCTION__);
3718 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
3725 if (rd->layer_enabled) {
3727 rd->layer_was_enabled = rd->layer_enabled;
3728 rd->layer_enabled = FALSE;
3731 rd->layer_enabled = rd->layer_was_enabled;
3732 if (rd->layer_was_enabled)
3741 menu_layers_remove_repos ();
3742 menu_layers_add_repos ();
3744 map_refresh_mark (TRUE);
3747 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
3750 /* this routine fired by timer every minute and decrements refetch counter of every active layer of
3751 current repository. If one of layer is expired, it forces map redraw. Redraw routine checks every
3752 layer's tile download timestamp and desides performs refetch if needed */
3754 map_layer_refresh_cb (gpointer data)
3756 RepoData* rd = _curr_repo;
3757 gboolean refresh = FALSE;
3758 printf("%s()\n", __PRETTY_FUNCTION__);
3761 for(rd = rd->layers; rd; rd = rd->layers)
3763 if (rd->layer_enabled && rd->layer_refresh_interval) {
3764 rd->layer_refresh_countdown--;
3765 if (rd->layer_refresh_countdown <= 0) {
3766 rd->layer_refresh_countdown = rd->layer_refresh_interval;
3769 printf("Refreshing layer: %s\n", rd->name);
3770 g_mutex_lock(_mapdb_mutex);
3771 if(MAPDB_EXISTS(rd))
3773 /* Clear the database. */
3775 sqlite3_exec(rd->sqlite_db, "delete from maps;",
3779 gdbm_close(rd->gdbm_db);
3780 g_remove(rd->db_filename);
3781 rd->gdbm_db = gdbm_open(rd->db_filename,
3782 0, GDBM_WRCREAT | GDBM_FAST, 0644, NULL);
3785 map_cache_clean_layer(rd);
3786 g_mutex_unlock(_mapdb_mutex);
3795 map_refresh_mark (TRUE);
3798 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
3803 maps_init(gint map_cache_size)
3805 printf("%s()\n", __PRETTY_FUNCTION__);
3807 map_cache_init(map_cache_size);
3809 if(_repo_list == NULL)
3811 /* We have no repositories - create a default one. */
3812 RepoData *repo = g_new0(RepoData, 1);
3814 repo->db_filename = gnome_vfs_expand_initial_tilde(
3815 REPO_DEFAULT_CACHE_DIR);
3816 repo->url=g_strdup(REPO_DEFAULT_MAP_URI);
3817 repo->dl_zoom_steps = REPO_DEFAULT_DL_ZOOM_STEPS;
3818 repo->name = g_strdup(REPO_DEFAULT_NAME);
3819 repo->view_zoom_steps = REPO_DEFAULT_VIEW_ZOOM_STEPS;
3820 repo->double_size = FALSE;
3821 repo->nextable = TRUE;
3822 repo->min_zoom = REPO_DEFAULT_MIN_ZOOM;
3823 repo->max_zoom = REPO_DEFAULT_MAX_ZOOM;
3824 repo->layers = NULL;
3825 repo->layer_level = 0;
3826 repo->is_sqlite = TRUE;
3827 set_repo_type(repo);
3829 _repo_list = g_list_append(_repo_list, repo);
3830 repo_set_curr(repo);
3833 /* this timer decrements layers' counters, clears layer databases, and
3834 * frefresh map if needed */
3835 g_timeout_add (60 * 1000, map_layer_refresh_cb, NULL);
3837 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
3844 printf("%s()\n", __PRETTY_FUNCTION__);
3846 map_cache_destroy();
3848 g_mutex_lock(_mapdb_mutex);
3850 if(MAPDB_EXISTS(_curr_repo))
3853 for(repo_p = _curr_repo; repo_p; repo_p = repo_p->layers)
3855 if(repo_p->is_sqlite)
3857 if(repo_p->sqlite_db)
3859 sqlite3_close(repo_p->sqlite_db);
3860 repo_p->sqlite_db = NULL;
3865 if (repo_p->gdbm_db) {
3866 gdbm_close(repo_p->gdbm_db);
3867 repo_p->gdbm_db = NULL;
3873 /* Go through layer repos and empty ephemeral ones. */
3874 for(curr = _repo_list; curr; curr = curr->next)
3877 for(repo = ((RepoData*)curr->data)->layers; repo; repo = repo->layers)
3879 if(repo->layer_refresh_interval != 0)
3881 printf("Clearing database: %s\n", repo->name);
3885 if(SQLITE_OK == sqlite3_open(repo->db_filename, &db))
3886 sqlite3_exec(db, "delete from maps;", NULL, NULL, NULL);
3887 sqlite3_exec(db, "vacuum;", NULL, NULL, NULL);
3891 /* Just delete the file and re-create. */
3892 g_remove(repo->db_filename);
3893 close(g_creat(repo->db_filename, 0644));
3899 g_mutex_unlock(_mapdb_mutex);
3901 vprintf("%s(): return\n", __PRETTY_FUNCTION__);