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));
561 map_cache_destroy(void)
563 g_mutex_lock(_mapdb_mutex);
564 map_cache_destroy_unlocked();
565 g_mutex_unlock(_mapdb_mutex);
570 map_cache_clean (void)
572 g_mutex_lock(_mapdb_mutex);
573 gint old_size = _map_cache.cache_size;
574 map_cache_destroy_unlocked();
575 map_cache_init_unlocked(old_size);
576 g_mutex_unlock(_mapdb_mutex);
581 mapdb_exists(RepoData *repo, gint zoom, gint tilex, gint tiley)
584 vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
585 repo->name, zoom, tilex, tiley);
587 g_mutex_lock(_mapdb_mutex);
589 if(!MAPDB_EXISTS(repo))
591 /* There is no cache. Return FALSE. */
592 g_mutex_unlock(_mapdb_mutex);
593 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
597 /* Search the cache first. */
600 MapCacheEntry *entry;
605 entry = (MapCacheEntry *)g_hash_table_lookup(_map_cache.entries, &key);
609 ret = entry->data != NULL;
610 g_mutex_unlock(_mapdb_mutex);
617 /* Attempt to retrieve map from database. */
618 if(SQLITE_OK == sqlite3_bind_int(repo->stmt_map_exists, 1, zoom)
619 && SQLITE_OK == sqlite3_bind_int(repo->stmt_map_exists, 2, tilex)
620 && SQLITE_OK == sqlite3_bind_int(repo->stmt_map_exists, 3, tiley)
621 && SQLITE_ROW == sqlite3_step(repo->stmt_map_exists)
622 && sqlite3_column_int(repo->stmt_map_exists, 0) > 0)
630 sqlite3_reset(repo->stmt_map_exists);
640 d.dptr = (gchar*)&key;
641 d.dsize = sizeof(key);
642 exists = gdbm_exists(repo->gdbm_db, d);
645 g_mutex_unlock(_mapdb_mutex);
647 vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, exists);
652 mapdb_get(RepoData *repo, gint zoom, gint tilex, gint tiley)
655 vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
656 repo->name, zoom, tilex, tiley);
657 g_mutex_lock(_mapdb_mutex);
658 pixbuf = map_cache_get(repo, zoom, tilex, tiley);
659 g_mutex_unlock(_mapdb_mutex);
660 vprintf("%s(): return %p\n", __PRETTY_FUNCTION__, pixbuf);
665 mapdb_update(RepoData *repo, gint zoom, gint tilex, gint tiley,
666 void *bytes, gint size)
669 vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
670 repo->name, zoom, tilex, tiley);
672 g_mutex_lock(_mapdb_mutex);
673 map_cache_update(repo, zoom, tilex, tiley, bytes, size);
675 if(!MAPDB_EXISTS(repo))
677 /* There is no cache. Return FALSE. */
678 g_mutex_unlock(_mapdb_mutex);
679 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
685 /* Attempt to insert/update map in database. */
686 if(SQLITE_OK != sqlite3_bind_blob(repo->stmt_map_update, 1,
688 || SQLITE_OK != sqlite3_bind_int(repo->stmt_map_update, 2, zoom)
689 || SQLITE_OK != sqlite3_bind_int(repo->stmt_map_update, 3, tilex)
690 || SQLITE_OK != sqlite3_bind_int(repo->stmt_map_update, 4, tiley)
691 || SQLITE_DONE != sqlite3_step(repo->stmt_map_update))
694 printf("Error in mapdb_update: %s\n",
695 sqlite3_errmsg(repo->sqlite_db));
697 sqlite3_reset(repo->stmt_map_update);
707 dkey.dptr = (gchar*)&key;
708 dkey.dsize = sizeof(key);
711 success = !gdbm_store(repo->gdbm_db, dkey, dcon, GDBM_REPLACE);
713 g_mutex_unlock(_mapdb_mutex);
715 vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, success);
720 mapdb_delete(RepoData *repo, gint zoom, gint tilex, gint tiley)
722 gint success = FALSE;
723 vprintf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
724 repo->name, zoom, tilex, tiley);
726 g_mutex_lock(_mapdb_mutex);
727 map_cache_remove(repo, zoom, tilex, tiley);
729 if(!MAPDB_EXISTS(repo))
731 /* There is no cache. Return FALSE. */
732 g_mutex_unlock(_mapdb_mutex);
733 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
739 if(SQLITE_OK != sqlite3_bind_int(repo->stmt_map_delete, 1, zoom)
740 || SQLITE_OK != sqlite3_bind_int(repo->stmt_map_delete, 2, tilex)
741 || SQLITE_OK != sqlite3_bind_int(repo->stmt_map_delete, 3, tiley)
742 || SQLITE_DONE != sqlite3_step(repo->stmt_map_delete))
745 printf("Error in stmt_map_delete: %s\n",
746 sqlite3_errmsg(repo->sqlite_db));
748 sqlite3_reset(repo->stmt_map_delete);
758 d.dptr = (gchar*)&key;
759 d.dsize = sizeof(key);
760 success = !gdbm_delete(repo->gdbm_db, d);
763 g_mutex_unlock(_mapdb_mutex);
765 vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, success);
770 set_repo_type(RepoData *repo)
772 printf("%s(%s)\n", __PRETTY_FUNCTION__, repo->url);
774 if(repo->url && *repo->url)
776 gchar *url = g_utf8_strdown(repo->url, -1);
778 /* Determine type of repository. */
779 if(strstr(url, "service=wms"))
780 repo->type = REPOTYPE_WMS;
781 else if(strstr(url, "%s"))
782 repo->type = REPOTYPE_QUAD_QRST;
783 else if(strstr(url, "%0d"))
784 repo->type = REPOTYPE_XYZ_INV;
785 else if(strstr(url, "%-d"))
786 repo->type = REPOTYPE_XYZ_SIGNED;
787 else if(strstr(url, "%0s"))
788 repo->type = REPOTYPE_QUAD_ZERO;
790 repo->type = REPOTYPE_XYZ;
795 repo->type = REPOTYPE_NONE;
797 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
800 /* Returns the directory containing the given database filename, or NULL
801 * if the database file could not be created. */
803 repo_make_db(RepoData *rd)
805 printf("%s(%s)\n", __PRETTY_FUNCTION__, rd->db_filename);
809 db_dirname = g_path_get_dirname(rd->db_filename);
811 /* Check if db_filename is a directory and ask to upgrade. */
812 if(g_file_test(rd->db_filename, G_FILE_TEST_IS_DIR))
814 gchar buffer[BUFFER_SIZE];
815 gchar *new_name = g_strdup_printf("%s.sqlite", rd->db_filename);
816 g_free(rd->db_filename);
817 rd->db_filename = new_name;
818 rd->is_sqlite = TRUE;
820 snprintf(buffer, sizeof(buffer), "%s",
821 _("The current repository is in a legacy format and will "
822 "be converted. You should delete your old maps if you "
823 "no longer plan to use them."));
824 popup_error(_window, buffer);
827 if(g_mkdir_with_parents(db_dirname, 0755))
834 if(!g_file_test(rd->db_filename, G_FILE_TEST_EXISTS))
836 fd = g_creat(rd->db_filename, 0644);
845 vprintf("%s(): return %d\n", __PRETTY_FUNCTION__,
846 g_file_test(rd->db_filename, G_FILE_TEST_EXISTS));
847 return g_file_test(rd->db_filename, G_FILE_TEST_EXISTS);
851 repo_set_curr(RepoData *rd)
854 printf("%s()\n", __PRETTY_FUNCTION__);
856 if(rd->db_filename && *rd->db_filename && !repo_make_db(rd))
858 gchar buffer[BUFFER_SIZE];
859 snprintf(buffer, sizeof(buffer), "%s: %s",
860 _("Unable to create map database for repository"), rd->name);
861 popup_error(_window, buffer);
863 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
867 /* Disconnect the previous repository. */
868 for(repo_p = _curr_repo; repo_p; repo_p = repo_p->layers)
870 if(MAPDB_EXISTS(repo_p))
872 g_mutex_lock(_mapdb_mutex);
873 if(repo_p->is_sqlite)
875 sqlite3_close(repo_p->sqlite_db);
876 repo_p->sqlite_db = NULL;
880 gdbm_close(repo_p->gdbm_db);
881 repo_p->gdbm_db = NULL;
883 g_mutex_unlock(_mapdb_mutex);
887 /* Set the current repository! */
890 /* initialize all databases for all layers */
891 for(repo_p = _curr_repo; repo_p; repo_p = repo_p->layers)
893 /* Check if the repository or layer has a backing database. (This is a
894 * redundant check in the case of the base, non-layer repository.) */
895 if (repo_p->db_filename && *repo_p->db_filename
896 && repo_make_db (repo_p))
898 if(repo_p->is_sqlite)
900 printf("Building SQLite3 database: %s\n",
901 repo_p->db_filename);
902 if(SQLITE_OK != (sqlite3_open(repo_p->db_filename,
903 &(repo_p->sqlite_db)))
904 /* Open worked. Now create tables, failing if they already
906 || (sqlite3_exec(repo_p->sqlite_db,
907 "create table maps ("
912 "primary key (zoom, tilex, tiley))",
913 NULL, NULL, NULL), FALSE) /* Comma operator! */
914 /* Prepare select map statement. */
915 || SQLITE_OK != sqlite3_prepare(repo_p->sqlite_db,
916 "select pixbuf from maps "
917 "where zoom = ? and tilex = ? and tiley = ?",
918 -1, &repo_p->stmt_map_select, NULL)
919 /* Prepare exists map statement. */
920 || SQLITE_OK != sqlite3_prepare(repo_p->sqlite_db,
921 "select count(*) from maps "
922 "where zoom = ? and tilex = ? and tiley = ?",
923 -1, &repo_p->stmt_map_exists, NULL)
924 /* Prepare insert map statement. */
925 || SQLITE_OK != sqlite3_prepare(repo_p->sqlite_db,
926 "insert or replace into maps"
927 " (pixbuf, zoom, tilex, tiley)"
928 " values (?, ?, ?, ?)",
929 -1, &repo_p->stmt_map_update, NULL)
930 /* Prepare delete map statement. */
931 || SQLITE_OK != sqlite3_prepare(repo_p->sqlite_db,
933 "where zoom = ? and tilex = ? and tiley = ?",
934 -1, &repo_p->stmt_map_delete, NULL))
936 gchar buffer[BUFFER_SIZE];
937 snprintf(buffer, sizeof(buffer), "%s: %s\n%s",
938 _("Failed to open map database for repository"),
939 sqlite3_errmsg(repo_p->sqlite_db),
940 _("Downloaded maps will not be cached."));
941 sqlite3_close(repo_p->sqlite_db);
942 repo_p->sqlite_db = NULL;
943 popup_error(_window, buffer);
948 printf("Building GDBM database: %s\n",
949 repo_p->db_filename);
950 repo_p->gdbm_db = gdbm_open(repo_p->db_filename,
951 0, GDBM_WRCREAT | GDBM_FAST, 0644, NULL);
956 if(!MAPDB_EXISTS(_curr_repo))
958 gchar buffer[BUFFER_SIZE];
959 snprintf(buffer, sizeof(buffer), "%s\n%s",
960 _("Failed to open map database for repository"),
961 _("Downloaded maps will not be cached."));
962 popup_error(_window, buffer);
964 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
971 * 1. base == layer, or
972 * 2. layer is sublayer of base
974 gboolean repo_is_layer (RepoData* base, RepoData* layer)
987 * Given a wms uri pattern, compute the coordinate transformation and
989 * 'proj' is used for the conversion
992 map_convert_wms_to_wms(gint tilex, gint tiley, gint zoomlevel, gchar* uri)
995 gchar cmd[BUFFER_SIZE], srs[BUFFER_SIZE];
998 gdouble lon1, lat1, lon2, lat2;
1000 gchar *widthstr = strcasestr(uri,"WIDTH=");
1001 gchar *heightstr = strcasestr(uri,"HEIGHT=");
1002 gchar *srsstr = strcasestr(uri,"SRS=EPSG");
1003 gchar *srsstre = strchr(srsstr,'&');
1004 vprintf("%s()\n", __PRETTY_FUNCTION__);
1006 /* missing: test if found */
1008 strncpy(srs+4,srsstr+8,256);
1009 /* missing: test srsstre-srsstr < 526 */
1010 srs[srsstre-srsstr-4] = 0;
1011 /* convert to lower, as WMC is EPSG and cs2cs is epsg */
1013 gint dwidth = widthstr ? atoi(widthstr+6) - TILE_SIZE_PIXELS : 0;
1014 gint dheight = heightstr ? atoi(heightstr+7) - TILE_SIZE_PIXELS : 0;
1016 unit2latlon(tile2zunit(tilex,zoomlevel)
1017 - pixel2zunit(dwidth/2,zoomlevel),
1018 tile2zunit(tiley+1,zoomlevel)
1019 + pixel2zunit((dheight+1)/2,zoomlevel),
1022 unit2latlon(tile2zunit(tilex+1,zoomlevel)
1023 + pixel2zunit((dwidth+1)/2,zoomlevel),
1024 tile2zunit(tiley,zoomlevel)
1025 - pixel2zunit(dheight/2,zoomlevel),
1028 setlocale(LC_NUMERIC, "C");
1030 snprintf(cmd, sizeof(cmd),
1031 "(echo \"%.6f %.6f\"; echo \"%.6f %.6f\") | "
1032 "/usr/bin/cs2cs +proj=longlat +datum=WGS84 +to +init=%s -f %%.6f "
1033 " > /tmp/tmpcs2cs ",
1034 lon1, lat1, lon2, lat2, srs);
1035 vprintf("Running command: %s\n", cmd);
1036 system_retcode = system(cmd);
1039 g_printerr("cs2cs returned error code %d\n",
1040 WEXITSTATUS(system_retcode));
1041 else if(!(in = g_fopen("/tmp/tmpcs2cs","r")))
1042 g_printerr("Cannot open results of conversion\n");
1043 else if(5 != fscanf(in,"%lf %lf %s %lf %lf",
1044 &lon1, &lat1, cmd, &lon2, &lat2))
1046 g_printerr("Wrong conversion\n");
1052 ret = g_strdup_printf(uri, lon1, lat1, lon2, lat2);
1055 setlocale(LC_NUMERIC, "");
1057 vprintf("%s(): return %s\n", __PRETTY_FUNCTION__, ret);
1063 * Given the xyz coordinates of our map coordinate system, write the qrst
1064 * quadtree coordinates to buffer.
1067 map_convert_coords_to_quadtree_string(gint x, gint y, gint zoomlevel,
1068 gchar *buffer, const gchar initial,
1069 const gchar *const quadrant)
1071 gchar *ptr = buffer;
1073 vprintf("%s()\n", __PRETTY_FUNCTION__);
1078 for(n = MAX_ZOOM - zoomlevel; n >= 0; n--)
1080 gint xbit = (x >> n) & 1;
1081 gint ybit = (y >> n) & 1;
1082 *ptr++ = quadrant[xbit + 2 * ybit];
1085 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1089 * Construct the URL that we should fetch, based on the current URI format.
1090 * This method works differently depending on if a "%s" string is present in
1091 * the URI format, since that would indicate a quadtree-based map coordinate
1095 map_construct_url(RepoData *repo, gint zoom, gint tilex, gint tiley)
1098 vprintf("%s(%p, %d, %d, %d)\n", __PRETTY_FUNCTION__,
1099 repo, zoom, tilex, tiley);
1103 retval = g_strdup_printf(repo->url,
1104 tilex, tiley, zoom - (MAX_ZOOM - 16));
1107 case REPOTYPE_XYZ_INV:
1108 retval = g_strdup_printf(repo->url,
1109 MAX_ZOOM + 1 - zoom, tilex, tiley);
1112 case REPOTYPE_XYZ_SIGNED:
1113 retval = g_strdup_printf(repo->url,
1115 (1 << (MAX_ZOOM - zoom)) - tiley - 1,
1116 zoom - (MAX_ZOOM - 17));
1119 case REPOTYPE_QUAD_QRST:
1121 gchar location[MAX_ZOOM + 2];
1122 map_convert_coords_to_quadtree_string(
1123 tilex, tiley, zoom, location, 't', "qrts");
1124 retval = g_strdup_printf(repo->url, location);
1128 case REPOTYPE_QUAD_ZERO:
1130 /* This is a zero-based quadtree URI. */
1131 gchar location[MAX_ZOOM + 2];
1132 map_convert_coords_to_quadtree_string(
1133 tilex, tiley, zoom, location, '\0', "0123");
1134 retval = g_strdup_printf(repo->url, location);
1139 retval = map_convert_wms_to_wms(tilex, tiley, zoom, repo->url);
1143 retval = g_strdup(repo->url);
1146 vprintf("%s(): return \"%s\"\n", __PRETTY_FUNCTION__, retval);
1151 mapdb_initiate_update_banner_idle()
1153 if(!_download_banner && _num_downloads != _curr_download)
1155 _download_banner = hildon_banner_show_progress(
1156 _window, NULL, _("Processing Maps"));
1157 /* If we're not connected, then hide the banner immediately. It will
1158 * be unhidden if/when we're connected. */
1159 if(!_conic_is_connected)
1160 gtk_widget_hide(_download_banner);
1166 * Initiate a download of the given xyz coordinates using the given buffer
1167 * as the URL. If the map already exists on disk, or if we are already
1168 * downloading the map, then this method does nothing.
1171 mapdb_initiate_update(RepoData *repo, gint zoom, gint tilex, gint tiley,
1172 gint update_type, gint batch_id, gint priority,
1173 ThreadLatch *refresh_latch)
1176 MapUpdateTask *old_mut;
1177 gboolean is_replacing = FALSE;
1178 vprintf("%s(%s, %d, %d, %d, %d)\n", __PRETTY_FUNCTION__,
1179 repo->name, zoom, tilex, tiley, update_type);
1181 mut = g_slice_new(MapUpdateTask);
1184 /* Could not allocate memory. */
1185 g_printerr("Out of memory in allocation of update task #%d\n",
1186 _num_downloads + 1);
1192 mut->update_type = update_type;
1193 mut->layer_level = repo->layer_level;
1195 /* Lock the mutex if this is an auto-update. */
1196 if(update_type == MAP_UPDATE_AUTO)
1197 g_mutex_lock(_mut_priority_mutex);
1198 if(NULL != (old_mut = g_hash_table_lookup(_mut_exists_table, mut)))
1200 /* Check if new mut is in a newer batch that the old mut.
1201 * We use vfs_result to indicate a MUT that is already in the process
1202 * of being downloaded. */
1203 if(old_mut->batch_id < batch_id && old_mut->vfs_result < 0)
1205 /* It is, so remove the old one so we can re-add this one. */
1206 g_hash_table_remove(_mut_exists_table, old_mut);
1207 g_tree_remove(_mut_priority_tree, old_mut);
1208 g_slice_free(MapUpdateTask, old_mut);
1209 is_replacing = TRUE;
1213 /* It's not, so just ignore it. */
1214 if(update_type == MAP_UPDATE_AUTO)
1215 g_mutex_unlock(_mut_priority_mutex);
1216 g_slice_free(MapUpdateTask, mut);
1217 vprintf("%s(): return FALSE (1)\n", __PRETTY_FUNCTION__);
1222 g_hash_table_insert(_mut_exists_table, mut, mut);
1225 mut->refresh_latch = refresh_latch;
1226 mut->priority = priority;
1227 mut->batch_id = batch_id;
1229 mut->vfs_result = -1;
1231 g_tree_insert(_mut_priority_tree, mut, mut);
1233 /* Unlock the mutex if this is an auto-update. */
1234 if(update_type == MAP_UPDATE_AUTO)
1235 g_mutex_unlock(_mut_priority_mutex);
1239 /* Increment download count and (possibly) display banner. */
1240 if(++_num_downloads == 20 && !_download_banner)
1241 g_idle_add((GSourceFunc)mapdb_initiate_update_banner_idle, NULL);
1243 /* This doesn't need to be thread-safe. Extras in the pool don't
1244 * really make a difference. */
1245 if(g_thread_pool_get_num_threads(_mut_thread_pool)
1246 < g_thread_pool_get_max_threads(_mut_thread_pool))
1247 g_thread_pool_push(_mut_thread_pool, (gpointer)1, NULL);
1250 vprintf("%s(): return FALSE (2)\n", __PRETTY_FUNCTION__);
1255 get_next_mut(gpointer key, gpointer value, MapUpdateTask **data)
1262 map_handle_error(gchar *error)
1264 MACRO_BANNER_SHOW_INFO(_window, error);
1271 printf("%s()\n", __PRETTY_FUNCTION__);
1273 /* Make sure things are inititalized. */
1276 while(conic_ensure_connected())
1279 gboolean refresh_sent = FALSE, layer_tile;
1280 MapUpdateTask *mut = NULL;
1282 /* Get the next MUT from the mut tree. */
1283 g_mutex_lock(_mut_priority_mutex);
1284 g_tree_foreach(_mut_priority_tree, (GTraverseFunc)get_next_mut, &mut);
1287 /* No more MUTs to process. Return. */
1288 g_mutex_unlock(_mut_priority_mutex);
1291 /* Mark this MUT as "in-progress". */
1292 mut->vfs_result = GNOME_VFS_NUM_ERRORS;
1293 g_tree_remove(_mut_priority_tree, mut);
1294 g_mutex_unlock(_mut_priority_mutex);
1296 printf("%s(%s, %d, %d, %d)\n", __PRETTY_FUNCTION__,
1297 mut->repo->name, mut->zoom, mut->tilex, mut->tiley);
1299 layer_tile = mut->repo != _curr_repo && repo_is_layer (_curr_repo, mut->repo);
1301 if (mut->repo != _curr_repo && !layer_tile)
1303 /* Do nothing, except report that there is no error. */
1304 mut->vfs_result = GNOME_VFS_OK;
1306 else if(mut->update_type == MAP_UPDATE_DELETE)
1308 /* Easy - just delete the entry from the database. We don't care
1309 * about failures (sorry). */
1310 if(MAPDB_EXISTS(mut->repo))
1311 mapdb_delete(mut->repo, mut->zoom, mut->tilex, mut->tiley);
1313 /* Report that there is no error. */
1314 mut->vfs_result = GNOME_VFS_OK;
1316 else for(retries = mut->repo->layer_level
1317 ? 1 : INITIAL_DOWNLOAD_RETRIES; retries > 0; --retries)
1322 GdkPixbufLoader *loader;
1324 gint zoom, tilex, tiley;
1325 GError *error = NULL;
1327 /* First check for existence. */
1328 if(mut->update_type == MAP_UPDATE_ADD)
1330 /* We don't want to overwrite, so check for existence. */
1331 /* Map already exists, and we're not going to overwrite. */
1332 if(mapdb_exists(mut->repo, mut->zoom,
1333 mut->tilex,mut->tiley))
1335 /* Report that there is no error. */
1336 mut->vfs_result = GNOME_VFS_OK;
1341 /* First, construct the URL from which we will get the data. */
1342 src_url = map_construct_url(mut->repo, mut->zoom,
1343 mut->tilex, mut->tiley);
1345 /* Now, attempt to read the entire contents of the URL. */
1346 mut->vfs_result = gnome_vfs_read_entire_file(
1347 src_url, &size, &bytes);
1349 if(mut->vfs_result != GNOME_VFS_OK || !bytes)
1352 printf("Error reading URL: %s\n",
1353 gnome_vfs_result_to_string(mut->vfs_result));
1357 /* usleep(100000); DEBUG */
1359 /* Attempt to parse the bytes into a pixbuf. */
1360 loader = gdk_pixbuf_loader_new();
1361 gdk_pixbuf_loader_write(loader, bytes, size, NULL);
1362 gdk_pixbuf_loader_close(loader, &error);
1363 if(error || (NULL == (mut->pixbuf = g_object_ref(
1364 gdk_pixbuf_loader_get_pixbuf(loader)))))
1366 mut->vfs_result = GNOME_VFS_NUM_ERRORS;
1368 g_object_unref(mut->pixbuf);
1371 g_object_unref(loader);
1372 printf("Error parsing pixbuf: %s\n",
1373 error ? error->message : "?");
1376 g_object_unref(loader);
1378 /* attach timestamp with loaded pixbuf */
1382 GError* error = NULL;
1385 sprintf (ts_val, "%u", (unsigned int)time (NULL));
1387 /* update bytes with new, timestamped pixbuf */
1388 if (gdk_pixbuf_save_to_buffer (mut->pixbuf, &new_bytes, &new_size, "png", &error, layer_timestamp_key, ts_val, NULL))
1396 /* Copy database-relevant mut data before we release it. */
1402 /* Pass the mut to the GTK thread for redrawing, but only if a
1403 * redraw isn't already in the pipeline. */
1404 if(mut->refresh_latch)
1406 /* Wait until the latch is open. */
1407 g_mutex_lock(mut->refresh_latch->mutex);
1408 while(!mut->refresh_latch->is_open)
1410 g_cond_wait(mut->refresh_latch->cond,
1411 mut->refresh_latch->mutex);
1413 /* Latch is open. Decrement the number of waiters and
1414 * check if we're the last waiter to run. */
1415 if(mut->refresh_latch->is_done_adding_tasks)
1417 if(++mut->refresh_latch->num_done
1418 == mut->refresh_latch->num_tasks)
1420 /* Last waiter. Free the latch resources. */
1421 g_mutex_unlock(mut->refresh_latch->mutex);
1422 g_cond_free(mut->refresh_latch->cond);
1423 g_mutex_free(mut->refresh_latch->mutex);
1424 g_slice_free(ThreadLatch, mut->refresh_latch);
1425 mut->refresh_latch = NULL;
1429 /* Not the last waiter. Signal the next waiter.*/
1430 g_cond_signal(mut->refresh_latch->cond);
1431 g_mutex_unlock(mut->refresh_latch->mutex);
1435 g_mutex_unlock(mut->refresh_latch->mutex);
1438 g_idle_add_full(G_PRIORITY_HIGH_IDLE,
1439 (GSourceFunc)map_download_refresh_idle, mut, NULL);
1440 refresh_sent = TRUE;
1442 /* DO NOT USE mut FROM THIS POINT ON. */
1444 /* Also attempt to add to the database. */
1445 if(MAPDB_EXISTS(repo) && !mapdb_update(repo, zoom,
1446 tilex, tiley, bytes, size)) {
1447 g_idle_add((GSourceFunc)map_handle_error,
1448 _("Error saving map to disk - disk full?"));
1457 g_idle_add_full(G_PRIORITY_HIGH_IDLE,
1458 (GSourceFunc)map_download_refresh_idle, mut, NULL);
1461 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
1466 mut_exists_hashfunc(const MapUpdateTask *a)
1468 gint sum = a->zoom + a->tilex + a->tiley + a->update_type + a->layer_level;
1469 return g_int_hash(&sum);
1473 mut_exists_equalfunc(const MapUpdateTask *a, const MapUpdateTask *b)
1475 return (a->tilex == b->tilex
1476 && a->tiley == b->tiley
1477 && a->zoom == b->zoom
1478 && a->update_type == b->update_type
1479 && a->layer_level == b->layer_level);
1483 mut_priority_comparefunc(const MapUpdateTask *a, const MapUpdateTask *b)
1485 /* The update_type enum is sorted in order of ascending priority. */
1486 gint diff = (b->update_type - a->update_type);
1489 diff = (b->batch_id - a->batch_id); /* More recent ones first. */
1492 diff = (a->priority - b->priority); /* Lower priority numbers first. */
1495 diff = (a->layer_level - b->layer_level); /* Lower layers first. */
1499 /* At this point, we don't care, so just pick arbitrarily. */
1500 diff = (a->tilex - b->tilex);
1503 diff = (a->tiley - b->tiley);
1506 return (a->zoom - b->zoom);
1510 repoman_dialog_select(GtkWidget *widget, RepoManInfo *rmi)
1512 printf("%s()\n", __PRETTY_FUNCTION__);
1513 gint curr_index = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
1514 gtk_notebook_set_current_page(GTK_NOTEBOOK(rmi->notebook), curr_index);
1515 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1520 repoman_dialog_browse(GtkWidget *widget, BrowseInfo *browse_info)
1524 printf("%s()\n", __PRETTY_FUNCTION__);
1526 dialog = GTK_WIDGET(
1527 hildon_file_chooser_dialog_new(GTK_WINDOW(browse_info->dialog),
1528 GTK_FILE_CHOOSER_ACTION_SAVE));
1530 gtk_file_chooser_set_uri(GTK_FILE_CHOOSER(dialog),
1531 gtk_entry_get_text(GTK_ENTRY(browse_info->txt)));
1533 /* Work around a bug in HildonFileChooserDialog. */
1534 basename = g_path_get_basename(
1535 gtk_entry_get_text(GTK_ENTRY(browse_info->txt)));
1536 g_object_set(G_OBJECT(dialog), "autonaming", FALSE, NULL);
1537 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), basename);
1539 if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)))
1541 gchar *filename = gtk_file_chooser_get_filename(
1542 GTK_FILE_CHOOSER(dialog));
1543 gtk_entry_set_text(GTK_ENTRY(browse_info->txt), filename);
1547 gtk_widget_destroy(dialog);
1549 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1554 repoman_compact_complete_idle(CompactInfo *ci)
1556 printf("%s()\n", __PRETTY_FUNCTION__);
1558 gtk_widget_destroy(GTK_WIDGET(ci->banner));
1559 popup_error(ci->dialog, ci->status_msg);
1560 gtk_widget_destroy(ci->dialog);
1563 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
1568 thread_repoman_compact(CompactInfo *ci)
1570 printf("%s()\n", __PRETTY_FUNCTION__);
1575 if(SQLITE_OK != (sqlite3_open(ci->db_filename, &db)))
1576 ci->status_msg = _("Failed to open map database for compacting.");
1579 if(SQLITE_OK != sqlite3_exec(db, "VACUUM;", NULL, NULL, NULL))
1580 ci->status_msg = _("An error occurred while trying to "
1581 "compact the database.");
1583 ci->status_msg = _("Successfully compacted database.");
1590 if(!(db = gdbm_open((gchar*)ci->db_filename, 0, GDBM_WRITER | GDBM_FAST,
1592 ci->status_msg = _("Failed to open map database for compacting.");
1595 if(gdbm_reorganize(db))
1596 ci->status_msg = _("An error occurred while trying to "
1597 "compact the database.");
1599 ci->status_msg = _("Successfully compacted database.");
1604 g_idle_add((GSourceFunc)repoman_compact_complete_idle, ci);
1606 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1610 repoman_dialog_compact(GtkWidget *widget, RepoEditInfo *rei)
1614 printf("%s()\n", __PRETTY_FUNCTION__);
1616 ci = g_new0(CompactInfo, 1);
1618 ci->dialog = gtk_dialog_new_with_buttons(_("Compact Database"),
1619 GTK_WINDOW(rei->browse_info.dialog), GTK_DIALOG_MODAL,
1620 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1621 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1624 sw = gtk_scrolled_window_new (NULL, NULL);
1625 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
1626 GTK_SHADOW_ETCHED_IN);
1627 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
1630 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(ci->dialog)->vbox),
1633 gtk_container_add(GTK_CONTAINER(sw), ci->txt = gtk_text_view_new());
1634 gtk_text_view_set_editable(GTK_TEXT_VIEW(ci->txt), FALSE);
1635 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(ci->txt), FALSE);
1636 gtk_text_buffer_set_text(
1637 gtk_text_view_get_buffer(GTK_TEXT_VIEW(ci->txt)),
1638 _("Generally, deleted maps create an empty space in the "
1639 "database that is later reused when downloading new maps. "
1640 "Compacting the database reorganizes it such that all "
1641 "that blank space is eliminated. This is the only way "
1642 "that the size of the database can decrease.\n"
1643 "This reorganization requires creating a new file and "
1644 "inserting all the maps in the old database file into the "
1645 "new file. The new file is then renamed to the same name "
1646 "as the old file and dbf is updated to contain all the "
1647 "correct information about the new file. Note that this "
1648 "can require free space on disk of an amount up to the size "
1649 "of the map database.\n"
1650 "This process may take several minutes, especially if "
1651 "your map database is large. As a rough estimate, you can "
1652 "expect to wait approximately 2-5 seconds per megabyte of "
1653 "map data (34-85 minutes per gigabyte). There is no progress "
1654 "indicator, although you can watch the new file grow in any "
1655 "file manager. Do not attempt to close Maemo Mapper while "
1656 "the compacting operation is in progress."),
1660 gtk_text_buffer_get_iter_at_offset(
1661 gtk_text_view_get_buffer(GTK_TEXT_VIEW(ci->txt)),
1663 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(ci->txt),
1664 &iter, 0.0, FALSE, 0, 0);
1667 gtk_widget_set_size_request(GTK_WIDGET(sw), 600, 200);
1668 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(ci->txt), GTK_WRAP_WORD);
1670 gtk_widget_show_all(ci->dialog);
1672 if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(ci->dialog)))
1674 gtk_widget_set_sensitive(GTK_DIALOG(ci->dialog)->action_area, FALSE);
1675 ci->db_filename = gtk_entry_get_text(GTK_ENTRY(rei->txt_db_filename));
1676 ci->is_sqlite = rei->is_sqlite;
1677 ci->banner = hildon_banner_show_animation(ci->dialog, NULL,
1678 _("Compacting database..."));
1680 g_thread_create((GThreadFunc)thread_repoman_compact, ci, FALSE, NULL);
1684 gtk_widget_destroy(ci->dialog);
1687 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1691 repoman_dialog_rename(GtkWidget *widget, RepoManInfo *rmi)
1693 static GtkWidget *hbox = NULL;
1694 static GtkWidget *label = NULL;
1695 static GtkWidget *txt_name = NULL;
1696 static GtkWidget *dialog = NULL;
1697 printf("%s()\n", __PRETTY_FUNCTION__);
1701 dialog = gtk_dialog_new_with_buttons(_("New Name"),
1702 GTK_WINDOW(rmi->dialog), GTK_DIALOG_MODAL,
1703 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1704 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1707 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
1708 hbox = gtk_hbox_new(FALSE, 4), FALSE, FALSE, 4);
1710 gtk_box_pack_start(GTK_BOX(hbox),
1711 label = gtk_label_new(_("Name")),
1713 gtk_box_pack_start(GTK_BOX(hbox),
1714 txt_name = gtk_entry_new(),
1719 gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
1720 RepoEditInfo *rei = g_list_nth_data(rmi->repo_edits, active);
1721 gtk_entry_set_text(GTK_ENTRY(txt_name), rei->name);
1724 gtk_widget_show_all(dialog);
1726 while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
1728 gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
1729 RepoEditInfo *rei = g_list_nth_data(rmi->repo_edits, active);
1731 rei->name = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_name)));
1732 gtk_combo_box_insert_text(GTK_COMBO_BOX(rmi->cmb_repos),
1733 active, g_strdup(rei->name));
1734 gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos), active);
1735 gtk_combo_box_remove_text(GTK_COMBO_BOX(rmi->cmb_repos), active + 1);
1739 gtk_widget_hide(dialog);
1741 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1746 repoman_delete(RepoManInfo *rmi, gint index)
1748 gtk_combo_box_remove_text(GTK_COMBO_BOX(rmi->cmb_repos), index);
1749 gtk_notebook_remove_page(GTK_NOTEBOOK(rmi->notebook), index);
1750 rmi->repo_edits = g_list_remove_link(
1752 g_list_nth(rmi->repo_edits, index));
1756 repoman_dialog_delete(GtkWidget *widget, RepoManInfo *rmi, gint index)
1760 printf("%s()\n", __PRETTY_FUNCTION__);
1762 if(gtk_tree_model_iter_n_children(GTK_TREE_MODEL(
1763 gtk_combo_box_get_model(GTK_COMBO_BOX(rmi->cmb_repos))),
1766 popup_error(rmi->dialog,
1767 _("Cannot delete the last repository - there must be at"
1768 " lease one repository."));
1769 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1773 snprintf(buffer, sizeof(buffer), "%s:\n%s\n",
1774 _("Confirm delete of repository"),
1775 gtk_combo_box_get_active_text(GTK_COMBO_BOX(rmi->cmb_repos)));
1777 confirm = hildon_note_new_confirmation(GTK_WINDOW(rmi->dialog),buffer);
1779 if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
1781 gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
1782 repoman_delete(rmi, active);
1783 gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos),
1787 gtk_widget_destroy(confirm);
1792 static RepoEditInfo*
1793 repoman_dialog_add_repo(RepoManInfo *rmi, gchar *name, gboolean is_sqlite)
1799 RepoEditInfo *rei = g_new0(RepoEditInfo, 1);
1800 printf("%s(%s, %d)\n", __PRETTY_FUNCTION__, name, is_sqlite);
1803 rei->is_sqlite = is_sqlite;
1806 gtk_notebook_append_page(GTK_NOTEBOOK(rmi->notebook),
1807 vbox = gtk_vbox_new(FALSE, 4),
1808 gtk_label_new(name));
1810 /* Prevent destruction of notebook page, because the destruction causes
1811 * a seg fault (!?!?) */
1812 gtk_object_ref(GTK_OBJECT(vbox));
1814 gtk_box_pack_start(GTK_BOX(vbox),
1815 table = gtk_table_new(2, 2, FALSE),
1817 /* Map download URI. */
1818 gtk_table_attach(GTK_TABLE(table),
1819 label = gtk_label_new(_("URL Format")),
1820 0, 1, 0, 1, GTK_FILL, 0, 2, 0);
1821 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1822 gtk_table_attach(GTK_TABLE(table),
1823 rei->txt_url = gtk_entry_new(),
1824 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 0);
1826 /* Map Directory. */
1827 gtk_table_attach(GTK_TABLE(table),
1828 label = gtk_label_new(_("Cache DB")),
1829 0, 1, 1, 2, GTK_FILL, 0, 2, 0);
1830 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1831 gtk_table_attach(GTK_TABLE(table),
1832 hbox = gtk_hbox_new(FALSE, 4),
1833 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 0);
1834 gtk_box_pack_start(GTK_BOX(hbox),
1835 rei->txt_db_filename = gtk_entry_new(),
1837 gtk_box_pack_start(GTK_BOX(hbox),
1838 rei->btn_browse = gtk_button_new_with_label(_("Browse...")),
1840 gtk_box_pack_start(GTK_BOX(hbox),
1841 rei->btn_compact = gtk_button_new_with_label(_("Compact...")),
1844 /* Initialize cache dir */
1846 gchar buffer[BUFFER_SIZE];
1847 snprintf(buffer, sizeof(buffer), "%s.%s", name,
1848 is_sqlite ? "sqlite" : "gdbm");
1849 gchar *db_base = gnome_vfs_expand_initial_tilde(
1850 REPO_DEFAULT_CACHE_BASE);
1851 gchar *db_filename = gnome_vfs_uri_make_full_from_relative(
1853 gtk_entry_set_text(GTK_ENTRY(rei->txt_db_filename), db_filename);
1854 g_free(db_filename);
1858 gtk_box_pack_start(GTK_BOX(vbox),
1859 table = gtk_table_new(3, 2, FALSE),
1862 /* Download Zoom Steps. */
1863 gtk_table_attach(GTK_TABLE(table),
1864 label = gtk_label_new(_("Download Zoom Steps")),
1865 0, 1, 0, 1, GTK_FILL, 0, 2, 0);
1866 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1867 gtk_table_attach(GTK_TABLE(table),
1868 label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
1869 1, 2, 0, 1, GTK_FILL, 0, 2, 0);
1870 gtk_container_add(GTK_CONTAINER(label),
1871 rei->num_dl_zoom_steps = hildon_controlbar_new());
1872 hildon_controlbar_set_range(
1873 HILDON_CONTROLBAR(rei->num_dl_zoom_steps), 1, 4);
1874 hildon_controlbar_set_value(HILDON_CONTROLBAR(rei->num_dl_zoom_steps),
1875 REPO_DEFAULT_DL_ZOOM_STEPS);
1876 force_min_visible_bars(HILDON_CONTROLBAR(rei->num_dl_zoom_steps), 1);
1878 /* Download Zoom Steps. */
1879 gtk_table_attach(GTK_TABLE(table),
1880 label = gtk_label_new(_("View Zoom Steps")),
1881 0, 1, 1, 2, GTK_FILL, 0, 2, 0);
1882 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1883 gtk_table_attach(GTK_TABLE(table),
1884 label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
1885 1, 2, 1, 2, GTK_FILL, 0, 2, 0);
1886 gtk_container_add(GTK_CONTAINER(label),
1887 rei->num_view_zoom_steps = hildon_controlbar_new());
1888 hildon_controlbar_set_range(
1889 HILDON_CONTROLBAR(rei->num_view_zoom_steps), 1, 4);
1890 hildon_controlbar_set_value(HILDON_CONTROLBAR(rei->num_view_zoom_steps),
1891 REPO_DEFAULT_VIEW_ZOOM_STEPS);
1892 force_min_visible_bars(HILDON_CONTROLBAR(rei->num_view_zoom_steps), 1);
1894 gtk_table_attach(GTK_TABLE(table),
1895 label = gtk_vseparator_new(),
1896 2, 3, 0, 2, GTK_FILL, GTK_FILL, 4, 0);
1899 gtk_table_attach(GTK_TABLE(table),
1900 rei->chk_double_size = gtk_check_button_new_with_label(
1901 _("Double Pixels")),
1902 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
1903 gtk_toggle_button_set_active(
1904 GTK_TOGGLE_BUTTON(rei->chk_double_size), FALSE);
1907 gtk_table_attach(GTK_TABLE(table),
1908 rei->chk_nextable = gtk_check_button_new_with_label(
1910 3, 4, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
1911 gtk_toggle_button_set_active(
1912 GTK_TOGGLE_BUTTON(rei->chk_nextable), TRUE);
1914 /* Downloadable Zoom Levels. */
1915 gtk_table_attach(GTK_TABLE(table),
1916 label = gtk_label_new(_("Downloadable Zooms:")),
1917 0, 1, 2, 3, GTK_FILL, 0, 2, 0);
1918 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1919 gtk_table_attach(GTK_TABLE(table),
1920 label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
1921 1, 4, 2, 3, GTK_FILL, 0, 2, 0);
1922 gtk_container_add(GTK_CONTAINER(label),
1923 hbox = gtk_hbox_new(FALSE, 4));
1924 gtk_box_pack_start(GTK_BOX(hbox),
1925 label = gtk_label_new(_("Min.")),
1927 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1928 gtk_box_pack_start(GTK_BOX(hbox),
1929 rei->num_min_zoom = hildon_number_editor_new(MIN_ZOOM, MAX_ZOOM),
1931 hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(rei->num_min_zoom), 4);
1932 gtk_box_pack_start(GTK_BOX(hbox),
1933 label = gtk_label_new(""),
1935 gtk_box_pack_start(GTK_BOX(hbox),
1936 label = gtk_label_new(_("Max.")),
1938 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1939 gtk_box_pack_start(GTK_BOX(hbox),
1940 rei->num_max_zoom = hildon_number_editor_new(MIN_ZOOM, MAX_ZOOM),
1942 hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(rei->num_max_zoom),20);
1944 rmi->repo_edits = g_list_append(rmi->repo_edits, rei);
1946 /* Connect signals. */
1947 rei->browse_info.dialog = rmi->dialog;
1948 rei->browse_info.txt = rei->txt_db_filename;
1949 g_signal_connect(G_OBJECT(rei->btn_browse), "clicked",
1950 G_CALLBACK(repoman_dialog_browse),
1952 g_signal_connect(G_OBJECT(rei->btn_compact), "clicked",
1953 G_CALLBACK(repoman_dialog_compact),
1956 gtk_widget_show_all(vbox);
1958 gtk_combo_box_append_text(GTK_COMBO_BOX(rmi->cmb_repos), name);
1959 gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos),
1960 gtk_tree_model_iter_n_children(GTK_TREE_MODEL(
1961 gtk_combo_box_get_model(GTK_COMBO_BOX(rmi->cmb_repos))),
1964 /* newly created repos keep this NULL in rei, indicating
1965 that layes cannot be added so far */
1968 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1973 repoman_dialog_new(GtkWidget *widget, RepoManInfo *rmi)
1975 static GtkWidget *table = NULL;
1976 static GtkWidget *label = NULL;
1977 static GtkWidget *txt_name = NULL;
1978 static GtkWidget *cmb_type = NULL;
1979 static GtkWidget *dialog = NULL;
1980 printf("%s()\n", __PRETTY_FUNCTION__);
1984 dialog = gtk_dialog_new_with_buttons(_("New Repository"),
1985 GTK_WINDOW(rmi->dialog), GTK_DIALOG_MODAL,
1986 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1987 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1990 /* Enable the help button. */
1992 hildon_help_dialog_help_enable(
1994 ossohelp_dialog_help_enable(
1996 GTK_DIALOG(dialog), HELP_ID_NEWREPO, _osso);
1998 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
1999 table = gtk_table_new(2, 2, FALSE),
2002 /* Download Zoom Steps. */
2003 gtk_table_attach(GTK_TABLE(table),
2004 label = gtk_label_new(_("Name")),
2005 0, 1, 0, 1, GTK_FILL, 2, 4, 2);
2006 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
2008 gtk_table_attach(GTK_TABLE(table),
2009 txt_name = gtk_entry_new(),
2010 1, 2, 0, 1, GTK_FILL, 2, 4, 2);
2012 gtk_table_attach(GTK_TABLE(table),
2013 label = gtk_label_new(_("Type")),
2014 0, 1, 1, 2, GTK_FILL, 2, 4, 2);
2015 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
2017 gtk_table_attach(GTK_TABLE(table),
2018 cmb_type = gtk_combo_box_new_text(),
2019 1, 2, 1, 2, GTK_FILL, 2, 4, 2);
2021 gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_type),
2022 _("SQLite 3 (default)"));
2023 gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_type),
2024 _("GDBM (legacy)"));
2025 gtk_combo_box_set_active(GTK_COMBO_BOX(cmb_type), 0);
2028 gtk_entry_set_text(GTK_ENTRY(txt_name), "");
2030 gtk_widget_show_all(dialog);
2032 while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
2034 repoman_dialog_add_repo(rmi,
2035 g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_name))),
2036 gtk_combo_box_get_active(GTK_COMBO_BOX(cmb_type)) == 0);
2040 gtk_widget_hide(dialog);
2042 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2047 repoman_reset(GtkWidget *widget, RepoManInfo *rmi)
2050 printf("%s()\n", __PRETTY_FUNCTION__);
2052 confirm = hildon_note_new_confirmation(GTK_WINDOW(rmi->dialog),
2053 _("Replace all repositories with the default repository?"));
2055 if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
2057 /* First, delete all existing repositories. */
2058 while(rmi->repo_edits)
2059 repoman_delete(rmi, 0);
2061 /* Now, add the default repository. */
2062 repoman_dialog_add_repo(rmi, REPO_DEFAULT_NAME, TRUE);
2064 GTK_ENTRY(((RepoEditInfo*)rmi->repo_edits->data)->txt_url),
2065 REPO_DEFAULT_MAP_URI);
2067 gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos), 0);
2069 gtk_widget_destroy(confirm);
2071 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2079 printf("%s()\n", __PRETTY_FUNCTION__);
2081 confirm = hildon_note_new_confirmation(GTK_WINDOW(_window),
2082 _("Maemo Mapper will now download and add a list of "
2083 "possibly-duplicate repositories from the internet. "
2086 if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
2092 GnomeVFSResult vfs_result;
2093 printf("%s()\n", __PRETTY_FUNCTION__);
2095 /* Get repo config file from www.gnuite.com. */
2096 if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
2097 "http://www.gnuite.com/nokia770/maemo-mapper/"
2098 "repos-with-layers.txt",
2101 popup_error(_window,
2102 _("An error occurred while retrieving the repositories. "
2103 "The web service may be temporarily down."));
2104 g_printerr("Error while download repositories: %s\n",
2105 gnome_vfs_result_to_string(vfs_result));
2107 /* Parse each line as a reposotory. */
2110 RepoData *prev_repo = NULL;
2111 menu_maps_remove_repos();
2112 for(head = bytes; head && *head; head = tail)
2115 tail = strchr(head, '\n');
2118 rd = settings_parse_repo(head);
2119 if (rd->layer_level == 0) {
2120 _repo_list = g_list_append(_repo_list, rd);
2123 prev_repo->layers = rd;
2128 menu_maps_add_repos();
2132 gtk_widget_destroy(confirm);
2134 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2140 layer_get_page_index (RepoLayersInfo *rli, GtkTreeIter list_it)
2142 GtkTreePath *p1, *p2;
2146 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (rli->layers_store), &p);
2148 p1 = gtk_tree_model_get_path (GTK_TREE_MODEL (rli->layers_store), &list_it);
2149 p2 = gtk_tree_model_get_path (GTK_TREE_MODEL (rli->layers_store), &p);
2151 while (gtk_tree_path_compare (p1, p2) != 0) {
2152 gtk_tree_path_next (p2);
2156 gtk_tree_path_free (p1);
2157 gtk_tree_path_free (p2);
2164 layer_name_changed (GtkWidget *entry, LayerEditInfo *lei)
2167 GtkTreeSelection *selection;
2170 printf("%s()\n", __PRETTY_FUNCTION__);
2173 name = gtk_entry_get_text (GTK_ENTRY (entry));
2175 /* find selected entry in list view */
2176 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (lei->rli->layers_list));
2178 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
2179 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2183 gtk_list_store_set (lei->rli->layers_store, &iter, 0, name, -1);
2185 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2191 layer_dialog_browse (GtkWidget *widget, LayerEditInfo *lei)
2195 printf("%s()\n", __PRETTY_FUNCTION__);
2197 dialog = GTK_WIDGET(
2198 hildon_file_chooser_dialog_new(GTK_WINDOW(lei->rli->dialog),
2199 GTK_FILE_CHOOSER_ACTION_SAVE));
2201 gtk_file_chooser_set_uri(GTK_FILE_CHOOSER(dialog),
2202 gtk_entry_get_text(GTK_ENTRY(lei->txt_db)));
2204 /* Work around a bug in HildonFileChooserDialog. */
2205 basename = g_path_get_basename(
2206 gtk_entry_get_text(GTK_ENTRY(lei->txt_db)));
2207 g_object_set(G_OBJECT(dialog), "autonaming", FALSE, NULL);
2208 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), basename);
2210 if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)))
2212 gchar *filename = gtk_file_chooser_get_filename(
2213 GTK_FILE_CHOOSER(dialog));
2214 gtk_entry_set_text(GTK_ENTRY(lei->txt_db), filename);
2218 gtk_widget_destroy(dialog);
2220 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2226 static LayerEditInfo*
2227 repoman_layers_add_layer (RepoLayersInfo *rli, gchar* name)
2229 LayerEditInfo *lei = g_new (LayerEditInfo, 1);
2234 GtkWidget *btn_browse;
2235 GtkTreeIter layers_iter;
2237 printf("%s(%s)\n", __PRETTY_FUNCTION__, name);
2241 rli->layer_edits = g_list_append (rli->layer_edits, lei);
2243 gtk_notebook_append_page (GTK_NOTEBOOK (rli->notebook), vbox = gtk_vbox_new (FALSE, 4),
2244 gtk_label_new (name));
2246 gtk_box_pack_start (GTK_BOX (vbox), table = gtk_table_new (4, 2, FALSE),
2250 gtk_table_attach (GTK_TABLE (table), label = gtk_label_new (_("Name")),
2251 0, 1, 0, 1, GTK_FILL, 0, 2, 0);
2252 gtk_misc_set_alignment (GTK_MISC (label), 1.f, 0.5f);
2253 gtk_table_attach (GTK_TABLE (table), lei->txt_name = gtk_entry_new (),
2254 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 0);
2255 gtk_entry_set_text (GTK_ENTRY (lei->txt_name), name);
2258 g_signal_connect(G_OBJECT(lei->txt_name), "changed", G_CALLBACK(layer_name_changed), lei);
2261 gtk_table_attach (GTK_TABLE (table), label = gtk_label_new (_("URL")),
2262 0, 1, 1, 2, GTK_FILL, 0, 2, 0);
2263 gtk_misc_set_alignment (GTK_MISC (label), 1.f, 0.5f);
2264 gtk_table_attach (GTK_TABLE (table), lei->txt_url = gtk_entry_new (),
2265 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 0);
2268 gtk_table_attach (GTK_TABLE (table), label = gtk_label_new (_("Cache DB")),
2269 0, 1, 2, 3, GTK_FILL, 0, 2, 0);
2270 gtk_misc_set_alignment (GTK_MISC (label), 1.f, 0.5f);
2271 gtk_table_attach (GTK_TABLE (table), hbox2 = gtk_hbox_new (FALSE, 4),
2272 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 0);
2273 gtk_box_pack_start (GTK_BOX (hbox2), lei->txt_db = gtk_entry_new (),
2275 gtk_box_pack_start (GTK_BOX (hbox2), btn_browse = gtk_button_new_with_label (_("Browse...")),
2278 g_signal_connect(G_OBJECT(btn_browse), "clicked", G_CALLBACK(layer_dialog_browse), lei);
2281 gtk_table_attach (GTK_TABLE (table), label = gtk_label_new (_("Autofetch")),
2282 0, 1, 3, 4, GTK_FILL, 0, 2, 0);
2283 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
2284 gtk_table_attach (GTK_TABLE (table), hbox2 = gtk_hbox_new (FALSE, 4),
2285 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 0);
2286 gtk_box_pack_start (GTK_BOX (hbox2), lei->num_autofetch = hildon_number_editor_new (0, 120),
2288 gtk_box_pack_start (GTK_BOX (hbox2), label = gtk_label_new (_("min.")), FALSE, FALSE, 4);
2289 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
2292 gtk_box_pack_start (GTK_BOX (vbox), lei->chk_visible = gtk_check_button_new_with_label (_("Layer is visible")),
2295 gtk_widget_show_all (vbox);
2297 /* Side list view with layers */
2298 gtk_list_store_append (rli->layers_store, &layers_iter);
2299 gtk_list_store_set (rli->layers_store, &layers_iter, 0, name, -1);
2301 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2309 repoman_layers_new (GtkWidget *widget, RepoLayersInfo *rli)
2311 static GtkWidget *hbox = NULL;
2312 static GtkWidget *label = NULL;
2313 static GtkWidget *txt_name = NULL;
2314 static GtkWidget *dialog = NULL;
2315 printf("%s()\n", __PRETTY_FUNCTION__);
2319 dialog = gtk_dialog_new_with_buttons(_("New Layer"),
2320 GTK_WINDOW(rli->dialog), GTK_DIALOG_MODAL,
2321 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
2322 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
2325 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
2326 hbox = gtk_hbox_new(FALSE, 4), FALSE, FALSE, 4);
2328 gtk_box_pack_start(GTK_BOX(hbox),
2329 label = gtk_label_new(_("Name")),
2331 gtk_box_pack_start(GTK_BOX(hbox),
2332 txt_name = gtk_entry_new(),
2336 gtk_entry_set_text(GTK_ENTRY(txt_name), "");
2338 gtk_widget_show_all(dialog);
2340 while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
2342 repoman_layers_add_layer(rli,
2343 g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_name))));
2347 gtk_widget_hide(dialog);
2348 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2354 repoman_layers_del (GtkWidget *widget, RepoLayersInfo *rli)
2357 GtkTreeSelection *selection;
2360 printf("%s()\n", __PRETTY_FUNCTION__);
2362 /* delete list item */
2363 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (rli->layers_list));
2365 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
2366 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2370 index = layer_get_page_index (rli, iter);
2371 gtk_list_store_remove (rli->layers_store, &iter);
2373 rli->layer_edits = g_list_remove_link (rli->layer_edits, g_list_nth (rli->layer_edits, index));
2375 /* delete notebook page */
2376 gtk_notebook_remove_page (GTK_NOTEBOOK (rli->notebook), index);
2378 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2384 repoman_layers_up (GtkWidget *widget, RepoLayersInfo *rli)
2386 GtkTreeSelection *selection;
2387 GtkTreeIter iter, iter2;
2393 printf("%s()\n", __PRETTY_FUNCTION__);
2395 /* find selected entry in list view */
2396 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (rli->layers_list));
2398 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
2399 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2404 path = gtk_tree_model_get_path (GTK_TREE_MODEL (rli->layers_store), &iter);
2405 if (!gtk_tree_path_prev (path) || !gtk_tree_model_get_iter (GTK_TREE_MODEL (rli->layers_store), &iter, path)) {
2406 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2410 gtk_tree_path_free (path);
2413 gtk_list_store_move_before (rli->layers_store, &iter2, &iter);
2415 /* reorder notebook tabs */
2416 page = gtk_notebook_get_current_page (GTK_NOTEBOOK (rli->notebook));
2417 gtk_notebook_reorder_child (GTK_NOTEBOOK (rli->notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (rli->notebook), page), page-1);
2419 /* reorder layer edits */
2420 list_elem = g_list_nth (rli->layer_edits, page);
2421 lei = list_elem->data;
2422 rli->layer_edits = g_list_remove_link (rli->layer_edits, list_elem);
2423 rli->layer_edits = g_list_insert (rli->layer_edits, lei, page-1);
2425 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2431 repoman_layers_dn (GtkWidget *widget, RepoLayersInfo *rli)
2433 GtkTreeSelection *selection;
2434 GtkTreeIter iter, iter2;
2439 printf("%s()\n", __PRETTY_FUNCTION__);
2441 /* find selected entry in list view */
2442 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (rli->layers_list));
2444 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
2445 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2450 if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (rli->layers_store), &iter)) {
2451 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2456 gtk_list_store_move_after (rli->layers_store, &iter2, &iter);
2458 /* reorder notebook tabs */
2459 page = gtk_notebook_get_current_page (GTK_NOTEBOOK (rli->notebook));
2460 gtk_notebook_reorder_child (GTK_NOTEBOOK (rli->notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (rli->notebook), page), page+1);
2462 /* reorder layer edits */
2463 list_elem = g_list_nth (rli->layer_edits, page);
2464 lei = list_elem->data;
2465 rli->layer_edits = g_list_remove_link (rli->layer_edits, list_elem);
2466 rli->layer_edits = g_list_insert (rli->layer_edits, lei, page+1);
2468 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2474 repoman_layer_selected (GtkTreeSelection *selection, RepoLayersInfo *rli)
2478 printf("%s()\n", __PRETTY_FUNCTION__);
2480 if (!gtk_tree_selection_get_selected (selection, NULL, &cur)) {
2481 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2485 gtk_notebook_set_current_page (GTK_NOTEBOOK (rli->notebook), layer_get_page_index (rli, cur));
2487 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2493 repoman_layers(GtkWidget *widget, RepoManInfo *rmi)
2495 GtkWidget *hbox = NULL;
2496 GtkWidget *layers_vbox = NULL;
2497 GtkWidget *buttons_hbox = NULL;
2499 GtkCellRenderer *layers_rendeder = NULL;
2500 GtkTreeViewColumn *layers_column = NULL;
2501 GtkTreeSelection *selection;
2503 /* layers buttons */
2504 GtkWidget *btn_new = NULL;
2505 GtkWidget *btn_del = NULL;
2506 GtkWidget *btn_up = NULL;
2507 GtkWidget *btn_dn = NULL;
2509 const char* t_header = _("Manage layers [%s]");
2510 char* header = NULL;
2511 RepoEditInfo* rei = NULL;
2513 gint curr_repo_index = gtk_combo_box_get_active (GTK_COMBO_BOX (rmi->cmb_repos));
2516 printf("%s()\n", __PRETTY_FUNCTION__);
2518 if (curr_repo_index < 0) {
2519 vprintf("%s(): return FALSE (1)\n", __PRETTY_FUNCTION__);
2523 rei = g_list_nth_data (rmi->repo_edits, curr_repo_index);
2526 vprintf("%s(): return FALSE (2)\n", __PRETTY_FUNCTION__);
2530 /* check that rei have repo data structure. If it haven't, it means that repository have just
2531 added, so report about this */
2533 GtkWidget *msg = hildon_note_new_information ( GTK_WINDOW (rmi->dialog),
2534 _("You cannot add layers to not saved repository,\nsorry. So, press ok in repository manager\n"
2535 "and open this dialog again."));
2537 gtk_dialog_run (GTK_DIALOG (msg));
2538 gtk_widget_destroy (msg);
2540 vprintf("%s(): return FALSE (3)\n", __PRETTY_FUNCTION__);
2544 header = g_malloc (strlen (t_header) + strlen (rei->name));
2545 sprintf (header, t_header, rei->name);
2547 printf ("Creating dialog with header: %s\n", header);
2549 rli.layer_edits = NULL;
2550 rli.dialog = gtk_dialog_new_with_buttons (header, GTK_WINDOW (rmi->dialog), GTK_DIALOG_MODAL,
2551 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
2552 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
2554 rli.layers_store = gtk_list_store_new (1, G_TYPE_STRING);
2555 rli.layers_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (rli.layers_store));
2556 layers_rendeder = gtk_cell_renderer_text_new ();
2557 layers_column = gtk_tree_view_column_new_with_attributes ("Column", layers_rendeder, "text", 0, NULL);
2558 gtk_tree_view_append_column (GTK_TREE_VIEW (rli.layers_list), layers_column);
2560 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (rli.layers_list));
2562 frame = gtk_frame_new (NULL);
2563 gtk_container_add (GTK_CONTAINER (frame), rli.layers_list);
2564 gtk_widget_set_size_request (frame, -1, 100);
2566 /* beside layers list with have buttons on bottom */
2567 layers_vbox = gtk_vbox_new (FALSE, 4);
2568 gtk_box_pack_start (GTK_BOX (layers_vbox), frame, TRUE, TRUE, 0);
2569 gtk_box_pack_start (GTK_BOX (layers_vbox), buttons_hbox = gtk_hbox_new (FALSE, 4), FALSE, FALSE, 0);
2572 gtk_box_pack_start (GTK_BOX (buttons_hbox), btn_new = gtk_button_new_with_label (_("New")), FALSE, FALSE, 0);
2573 gtk_box_pack_start (GTK_BOX (buttons_hbox), btn_del = gtk_button_new_with_label (_("Del")), FALSE, FALSE, 0);
2574 gtk_box_pack_start (GTK_BOX (buttons_hbox), btn_up = gtk_button_new_with_label (_("Up")), FALSE, FALSE, 0);
2575 gtk_box_pack_start (GTK_BOX (buttons_hbox), btn_dn = gtk_button_new_with_label (_("Dn")), FALSE, FALSE, 0);
2578 g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(repoman_layer_selected), &rli);
2579 g_signal_connect(G_OBJECT(btn_new), "clicked", G_CALLBACK(repoman_layers_new), &rli);
2580 g_signal_connect(G_OBJECT(btn_del), "clicked", G_CALLBACK(repoman_layers_del), &rli);
2581 g_signal_connect(G_OBJECT(btn_up), "clicked", G_CALLBACK(repoman_layers_up), &rli);
2582 g_signal_connect(G_OBJECT(btn_dn), "clicked", G_CALLBACK(repoman_layers_dn), &rli);
2584 /* notebook with layers' attributes */
2585 rli.notebook = gtk_notebook_new ();
2587 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(rli.notebook), FALSE);
2588 gtk_notebook_set_show_border(GTK_NOTEBOOK(rli.notebook), FALSE);
2590 /* walk through all layers and add notebook pages */
2591 rd = rei->repo->layers;
2593 LayerEditInfo *lei = repoman_layers_add_layer (&rli, rd->name);
2595 gtk_entry_set_text (GTK_ENTRY (lei->txt_url), rd->url);
2596 gtk_entry_set_text (GTK_ENTRY (lei->txt_db), rd->db_filename);
2597 hildon_number_editor_set_value (HILDON_NUMBER_EDITOR (lei->num_autofetch), rd->layer_refresh_interval);
2598 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lei->chk_visible), rd->layer_enabled);
2603 /* pack all widgets together */
2604 hbox = gtk_hbox_new (FALSE, 4);
2606 gtk_box_pack_start (GTK_BOX (hbox), layers_vbox, TRUE, TRUE, 4);
2607 gtk_box_pack_start (GTK_BOX (hbox), rli.notebook, TRUE, TRUE, 4);
2609 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (rli.dialog)->vbox), hbox, FALSE, FALSE, 4);
2611 gtk_widget_show_all (rli.dialog);
2613 while (GTK_RESPONSE_ACCEPT == gtk_dialog_run (GTK_DIALOG (rli.dialog)))
2619 menu_layers_remove_repos ();
2621 /* iterate over notebook's pages and build layers */
2622 /* keep list in memory in case downloads use it (TODO: reference counting) */
2623 rdp = &rei->repo->layers;
2626 for (i = 0, curr = rli.layer_edits; curr; curr = curr->next, i++) {
2627 LayerEditInfo *lei = curr->data;
2629 rd = g_new0 (RepoData, 1);
2632 rd->name = g_strdup (gtk_entry_get_text (GTK_ENTRY (lei->txt_name)));
2633 rd->url = g_strdup (gtk_entry_get_text (GTK_ENTRY (lei->txt_url)));
2634 rd->db_filename = g_strdup (gtk_entry_get_text (GTK_ENTRY (lei->txt_db)));
2635 rd->layer_enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (lei->chk_visible));
2636 rd->layer_refresh_interval = hildon_number_editor_get_value (HILDON_NUMBER_EDITOR (lei->num_autofetch));
2637 rd->layer_refresh_countdown = rd->layer_refresh_interval;
2638 rd->layer_level = i+1;
2640 rd->dl_zoom_steps = rei->repo->dl_zoom_steps;
2641 rd->view_zoom_steps = rei->repo->view_zoom_steps;
2642 rd->double_size = rei->repo->double_size;
2643 rd->nextable = rei->repo->nextable;
2644 rd->min_zoom = rei->repo->min_zoom;
2645 rd->max_zoom = rei->repo->max_zoom;
2651 menu_layers_add_repos ();
2652 repo_set_curr(_curr_repo);
2655 map_refresh_mark (TRUE);
2659 gtk_widget_destroy (rli.dialog);
2661 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2669 static RepoManInfo rmi;
2670 static GtkWidget *dialog = NULL;
2671 static GtkWidget *hbox = NULL;
2672 static GtkWidget *btn_rename = NULL;
2673 static GtkWidget *btn_delete = NULL;
2674 static GtkWidget *btn_new = NULL;
2675 static GtkWidget *btn_reset = NULL;
2676 static GtkWidget *btn_layers = NULL;
2677 gint i, curr_repo_index = 0;
2679 printf("%s()\n", __PRETTY_FUNCTION__);
2683 rmi.dialog = dialog = gtk_dialog_new_with_buttons(
2684 _("Manage Repositories"),
2685 GTK_WINDOW(_window), GTK_DIALOG_MODAL,
2686 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
2689 /* Enable the help button. */
2691 hildon_help_dialog_help_enable(
2693 ossohelp_dialog_help_enable(
2695 GTK_DIALOG(dialog), HELP_ID_REPOMAN, _osso);
2698 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
2699 btn_reset = gtk_button_new_with_label(_("Reset...")));
2700 g_signal_connect(G_OBJECT(btn_reset), "clicked",
2701 G_CALLBACK(repoman_reset), &rmi);
2703 /* Layers button. */
2704 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
2705 btn_layers = gtk_button_new_with_label(_("Layers...")));
2706 g_signal_connect(G_OBJECT(btn_layers), "clicked",
2707 G_CALLBACK(repoman_layers), &rmi);
2709 /* Cancel button. */
2710 gtk_dialog_add_button(GTK_DIALOG(dialog),
2711 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
2713 hbox = gtk_hbox_new(FALSE, 4);
2715 gtk_box_pack_start(GTK_BOX(hbox),
2716 rmi.cmb_repos = gtk_combo_box_new_text(), TRUE, TRUE, 4);
2718 gtk_box_pack_start(GTK_BOX(hbox),
2719 gtk_vseparator_new(), FALSE, FALSE, 4);
2720 gtk_box_pack_start(GTK_BOX(hbox),
2721 btn_rename = gtk_button_new_with_label(_("Rename...")),
2723 gtk_box_pack_start(GTK_BOX(hbox),
2724 btn_delete = gtk_button_new_with_label(_("Delete...")),
2726 gtk_box_pack_start(GTK_BOX(hbox),
2727 btn_new = gtk_button_new_with_label(_("New...")),
2730 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
2731 hbox, FALSE, FALSE, 4);
2733 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
2734 gtk_hseparator_new(), TRUE, TRUE, 4);
2735 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
2736 rmi.notebook = gtk_notebook_new(), TRUE, TRUE, 4);
2738 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(rmi.notebook), FALSE);
2739 gtk_notebook_set_show_border(GTK_NOTEBOOK(rmi.notebook), FALSE);
2741 rmi.repo_edits = NULL;
2743 /* Connect signals. */
2744 g_signal_connect(G_OBJECT(btn_rename), "clicked",
2745 G_CALLBACK(repoman_dialog_rename), &rmi);
2746 g_signal_connect(G_OBJECT(btn_delete), "clicked",
2747 G_CALLBACK(repoman_dialog_delete), &rmi);
2748 g_signal_connect(G_OBJECT(btn_new), "clicked",
2749 G_CALLBACK(repoman_dialog_new), &rmi);
2750 g_signal_connect(G_OBJECT(rmi.cmb_repos), "changed",
2751 G_CALLBACK(repoman_dialog_select), &rmi);
2754 /* Populate combo box and pages in notebook. */
2755 for(i = 0, curr = _repo_list; curr; curr = curr->next, i++)
2757 RepoData *rd = (RepoData*)curr->data;
2758 RepoEditInfo *rei = repoman_dialog_add_repo(&rmi, g_strdup(rd->name),
2761 /* store this to be able to walk through layers attached to repo */
2764 /* Initialize fields with data from the RepoData object. */
2765 gtk_entry_set_text(GTK_ENTRY(rei->txt_url), rd->url);
2766 gtk_entry_set_text(GTK_ENTRY(rei->txt_db_filename),
2768 hildon_controlbar_set_value(
2769 HILDON_CONTROLBAR(rei->num_dl_zoom_steps),
2771 hildon_controlbar_set_value(
2772 HILDON_CONTROLBAR(rei->num_view_zoom_steps),
2773 rd->view_zoom_steps);
2774 gtk_toggle_button_set_active(
2775 GTK_TOGGLE_BUTTON(rei->chk_double_size),
2777 gtk_toggle_button_set_active(
2778 GTK_TOGGLE_BUTTON(rei->chk_nextable),
2780 hildon_number_editor_set_value(
2781 HILDON_NUMBER_EDITOR(rei->num_min_zoom),
2783 hildon_number_editor_set_value(
2784 HILDON_NUMBER_EDITOR(rei->num_max_zoom),
2786 if(rd == _curr_repo)
2787 curr_repo_index = i;
2790 gtk_combo_box_set_active(GTK_COMBO_BOX(rmi.cmb_repos), curr_repo_index);
2791 gtk_notebook_set_current_page(GTK_NOTEBOOK(rmi.notebook), curr_repo_index);
2793 gtk_widget_show_all(dialog);
2795 while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
2797 /* Iterate through repos and verify each. */
2798 gboolean verified = TRUE;
2801 gchar *old_curr_repo_name = _curr_repo->name;
2803 for(i = 0, curr = rmi.repo_edits; curr; curr = curr->next, i++)
2805 /* Check the ranges for the min and max zoom levels. */
2806 RepoEditInfo *rei = curr->data;
2807 if(hildon_number_editor_get_value(
2808 HILDON_NUMBER_EDITOR(rei->num_max_zoom))
2809 < hildon_number_editor_get_value(
2810 HILDON_NUMBER_EDITOR(rei->num_min_zoom)))
2818 gtk_combo_box_set_active(GTK_COMBO_BOX(rmi.cmb_repos), i);
2820 _("Minimum Downloadable Zoom must be less than "
2821 "Maximum Downloadable Zoom."));
2825 /* We're good to replace. Remove old _repo_list menu items. */
2826 menu_maps_remove_repos();
2827 /* But keep the repo list in memory, in case downloads are using it. */
2830 /* Write new _repo_list. */
2831 curr_repo_index = gtk_combo_box_get_active(
2832 GTK_COMBO_BOX(rmi.cmb_repos));
2834 for(i = 0, curr = rmi.repo_edits; curr; curr = curr->next, i++)
2836 RepoEditInfo *rei = curr->data;
2837 RepoData *rd = g_new0(RepoData, 1);
2838 RepoData *rd0, **rd1;
2839 rd->name = g_strdup(rei->name);
2840 rd->is_sqlite = rei->is_sqlite;
2841 rd->url = g_strdup(gtk_entry_get_text(GTK_ENTRY(rei->txt_url)));
2842 rd->db_filename = gnome_vfs_expand_initial_tilde(
2843 gtk_entry_get_text(GTK_ENTRY(rei->txt_db_filename)));
2844 rd->dl_zoom_steps = hildon_controlbar_get_value(
2845 HILDON_CONTROLBAR(rei->num_dl_zoom_steps));
2846 rd->view_zoom_steps = hildon_controlbar_get_value(
2847 HILDON_CONTROLBAR(rei->num_view_zoom_steps));
2848 rd->double_size = gtk_toggle_button_get_active(
2849 GTK_TOGGLE_BUTTON(rei->chk_double_size));
2850 rd->nextable = gtk_toggle_button_get_active(
2851 GTK_TOGGLE_BUTTON(rei->chk_nextable));
2852 rd->min_zoom = hildon_number_editor_get_value(
2853 HILDON_NUMBER_EDITOR(rei->num_min_zoom));
2854 rd->max_zoom = hildon_number_editor_get_value(
2855 HILDON_NUMBER_EDITOR(rei->num_max_zoom));
2859 rd0 = rei->repo->layers;
2863 *rd1 = g_new0 (RepoData, 1);
2864 (*rd1)->name = rd0->name;
2865 (*rd1)->is_sqlite = rd0->is_sqlite;
2866 (*rd1)->url = rd0->url;
2867 (*rd1)->db_filename = rd0->db_filename;
2868 (*rd1)->layer_enabled = rd0->layer_enabled;
2869 (*rd1)->layer_refresh_interval = rd0->layer_refresh_interval;
2870 (*rd1)->layer_refresh_countdown = rd0->layer_refresh_countdown;
2871 (*rd1)->layer_level = rd0->layer_level;
2873 (*rd1)->dl_zoom_steps = rd0->dl_zoom_steps;
2874 (*rd1)->view_zoom_steps = rd0->view_zoom_steps;
2875 (*rd1)->double_size = rd0->double_size;
2876 (*rd1)->nextable = rd0->nextable;
2877 (*rd1)->min_zoom = rd0->min_zoom;
2878 (*rd1)->max_zoom = rd0->max_zoom;
2880 set_repo_type (*rd1);
2883 rd1 = &(*rd1)->layers;
2890 rd->layer_level = 0;
2893 _repo_list = g_list_append(_repo_list, rd);
2895 if(!_curr_repo && !strcmp(old_curr_repo_name, rd->name))
2897 else if(i == curr_repo_index)
2901 repo_set_curr((RepoData*)g_list_first(_repo_list)->data);
2902 menu_maps_add_repos();
2908 gtk_widget_hide(dialog);
2910 /* Clear out the notebook entries. */
2911 while(rmi.repo_edits)
2912 repoman_delete(&rmi, 0);
2914 map_set_zoom(_zoom); /* make sure we're at an appropriate zoom level. */
2915 map_refresh_mark (TRUE);
2917 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2922 mapman_by_area(gdouble start_lat, gdouble start_lon,
2923 gdouble end_lat, gdouble end_lon, MapmanInfo *mapman_info,
2924 MapUpdateType update_type,
2925 gint download_batch_id)
2927 gint start_unitx, start_unity, end_unitx, end_unity;
2932 printf("%s(%f, %f, %f, %f)\n", __PRETTY_FUNCTION__, start_lat, start_lon,
2935 latlon2unit(start_lat, start_lon, start_unitx, start_unity);
2936 latlon2unit(end_lat, end_lon, end_unitx, end_unity);
2938 /* Swap if they specified flipped lats or lons. */
2939 if(start_unitx > end_unitx)
2941 gint swap = start_unitx;
2942 start_unitx = end_unitx;
2945 if(start_unity > end_unity)
2947 gint swap = start_unity;
2948 start_unity = end_unity;
2952 /* First, get the number of maps to download. */
2953 for(z = 0; z <= MAX_ZOOM; ++z)
2955 if(gtk_toggle_button_get_active(
2956 GTK_TOGGLE_BUTTON(mapman_info->chk_zoom_levels[z])))
2958 gint start_tilex, start_tiley, end_tilex, end_tiley;
2959 start_tilex = unit2ztile(start_unitx, z);
2960 start_tiley = unit2ztile(start_unity, z);
2961 end_tilex = unit2ztile(end_unitx, z);
2962 end_tiley = unit2ztile(end_unity, z);
2963 num_maps += (end_tilex - start_tilex + 1)
2964 * (end_tiley - start_tiley + 1);
2968 if(update_type == MAP_UPDATE_DELETE)
2970 snprintf(buffer, sizeof(buffer), "%s %d %s", _("Confirm DELETION of"),
2971 num_maps, _("maps "));
2975 snprintf(buffer, sizeof(buffer),
2976 "%s %d %s\n(%s %.2f MB)\n", _("Confirm download of"),
2977 num_maps, _("maps"), _("up to about"),
2978 num_maps * (strstr(_curr_repo->url, "%s") ? 18e-3 : 6e-3));
2980 confirm = hildon_note_new_confirmation(
2981 GTK_WINDOW(mapman_info->dialog), buffer);
2983 if(GTK_RESPONSE_OK != gtk_dialog_run(GTK_DIALOG(confirm)))
2985 gtk_widget_destroy(confirm);
2986 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2990 g_mutex_lock(_mut_priority_mutex);
2991 for(z = 0; z <= MAX_ZOOM; ++z)
2993 if(gtk_toggle_button_get_active(
2994 GTK_TOGGLE_BUTTON(mapman_info->chk_zoom_levels[z])))
2996 gint start_tilex, start_tiley, end_tilex, end_tiley;
2998 start_tilex = unit2ztile(start_unitx, z);
2999 start_tiley = unit2ztile(start_unity, z);
3000 end_tilex = unit2ztile(end_unitx, z);
3001 end_tiley = unit2ztile(end_unity, z);
3002 for(tiley = start_tiley; tiley <= end_tiley; tiley++)
3004 for(tilex = start_tilex; tilex <= end_tilex; tilex++)
3006 /* Make sure this tile is even possible. */
3007 if((unsigned)tilex < unit2ztile(WORLD_SIZE_UNITS, z)
3008 && (unsigned)tiley < unit2ztile(WORLD_SIZE_UNITS, z))
3010 RepoData* rd = _curr_repo;
3013 if (rd == _curr_repo
3014 || (rd->layer_enabled && MAPDB_EXISTS(rd)))
3015 mapdb_initiate_update(rd, z, tilex, tiley,
3016 update_type, download_batch_id,
3017 (abs(tilex - unit2tile(_next_center.unitx))
3018 +abs(tiley - unit2tile(_next_center.unity))),
3027 g_mutex_unlock(_mut_priority_mutex);
3029 gtk_widget_destroy(confirm);
3030 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
3035 mapman_by_route(MapmanInfo *mapman_info, MapUpdateType update_type,
3036 gint download_batch_id)
3039 gint prev_tilex, prev_tiley, num_maps = 0, z;
3042 gint radius = hildon_number_editor_get_value(
3043 HILDON_NUMBER_EDITOR(mapman_info->num_route_radius));
3044 printf("%s()\n", __PRETTY_FUNCTION__);
3046 /* First, get the number of maps to download. */
3047 for(z = 0; z <= MAX_ZOOM; ++z)
3049 if(gtk_toggle_button_get_active(
3050 GTK_TOGGLE_BUTTON(mapman_info->chk_zoom_levels[z])))
3054 for(curr = _route.head - 1; curr++ != _route.tail; )
3058 gint tilex = unit2ztile(curr->unitx, z);
3059 gint tiley = unit2ztile(curr->unity, z);
3060 if(tilex != prev_tilex || tiley != prev_tiley)
3063 num_maps += (abs((gint)tilex - prev_tilex) + 1)
3064 * (abs((gint)tiley - prev_tiley) + 1) - 1;
3072 num_maps *= 0.625 * pow(radius + 1, 1.85);
3074 if(update_type == MAP_UPDATE_DELETE)
3076 snprintf(buffer, sizeof(buffer), "%s %s %d %s",
3077 _("Confirm DELETION of"), _("about"),
3078 num_maps, _("maps "));
3082 snprintf(buffer, sizeof(buffer),
3083 "%s %s %d %s\n(%s %.2f MB)\n", _("Confirm download of"),
3085 num_maps, _("maps"), _("up to about"),
3086 num_maps * (strstr(_curr_repo->url, "%s") ? 18e-3 : 6e-3));
3088 confirm = hildon_note_new_confirmation(
3089 GTK_WINDOW(mapman_info->dialog), buffer);
3091 if(GTK_RESPONSE_OK != gtk_dialog_run(GTK_DIALOG(confirm)))
3093 gtk_widget_destroy(confirm);
3094 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
3098 /* Now, do the actual download. */
3099 g_mutex_lock(_mut_priority_mutex);
3100 for(z = 0; z <= MAX_ZOOM; ++z)
3102 if(gtk_toggle_button_get_active(
3103 GTK_TOGGLE_BUTTON(mapman_info->chk_zoom_levels[z])))
3107 for(curr = _route.head - 1; curr++ != _route.tail; )
3111 gint tilex = unit2ztile(curr->unitx, z);
3112 gint tiley = unit2ztile(curr->unity, z);
3113 if(tilex != prev_tilex || tiley != prev_tiley)
3115 gint minx, miny, maxx, maxy, x, y;
3118 minx = MIN(tilex, prev_tilex) - radius;
3119 miny = MIN(tiley, prev_tiley) - radius;
3120 maxx = MAX(tilex, prev_tilex) + radius;
3121 maxy = MAX(tiley, prev_tiley) + radius;
3125 minx = tilex - radius;
3126 miny = tiley - radius;
3127 maxx = tilex + radius;
3128 maxy = tiley + radius;
3130 for(x = minx; x <= maxx; x++)
3132 for(y = miny; y <= maxy; y++)
3134 /* Make sure this tile is even possible. */
3136 < unit2ztile(WORLD_SIZE_UNITS, z)
3138 < unit2ztile(WORLD_SIZE_UNITS, z))
3140 mapdb_initiate_update(_curr_repo, z, x, y,
3141 update_type, download_batch_id,
3142 (abs(tilex - unit2tile(
3143 _next_center.unitx))
3144 + abs(tiley - unit2tile(
3145 _next_center.unity))),
3157 g_mutex_unlock(_mut_priority_mutex);
3158 _route_dl_radius = radius;
3159 gtk_widget_destroy(confirm);
3160 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
3165 mapman_clear(GtkWidget *widget, MapmanInfo *mapman_info)
3168 printf("%s()\n", __PRETTY_FUNCTION__);
3169 if(gtk_notebook_get_current_page(GTK_NOTEBOOK(mapman_info->notebook)))
3170 /* This is the second page (the "Zoom" page) - clear the checks. */
3171 for(z = 0; z <= MAX_ZOOM; ++z)
3172 gtk_toggle_button_set_active(
3173 GTK_TOGGLE_BUTTON(mapman_info->chk_zoom_levels[z]), FALSE);
3176 /* This is the first page (the "Area" page) - clear the text fields. */
3177 gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_topleft_lat), "");
3178 gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_topleft_lon), "");
3179 gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_botright_lat), "");
3180 gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_botright_lon), "");
3182 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
3185 void mapman_update_state(GtkWidget *widget, MapmanInfo *mapman_info)
3187 printf("%s()\n", __PRETTY_FUNCTION__);
3188 gtk_widget_set_sensitive( mapman_info->chk_overwrite,
3189 gtk_toggle_button_get_active(
3190 GTK_TOGGLE_BUTTON(mapman_info->rad_download)));
3192 if(gtk_toggle_button_get_active(
3193 GTK_TOGGLE_BUTTON(mapman_info->rad_by_area)))
3194 gtk_widget_show(mapman_info->tbl_area);
3195 else if(gtk_notebook_get_n_pages(GTK_NOTEBOOK(mapman_info->notebook)) == 3)
3196 gtk_widget_hide(mapman_info->tbl_area);
3198 gtk_widget_set_sensitive(mapman_info->num_route_radius,
3199 gtk_toggle_button_get_active(
3200 GTK_TOGGLE_BUTTON(mapman_info->rad_by_route)));
3201 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
3207 static GtkWidget *dialog = NULL;
3208 static GtkWidget *vbox = NULL;
3209 static GtkWidget *hbox = NULL;
3210 static GtkWidget *table = NULL;
3211 static GtkWidget *label = NULL;
3212 static GtkWidget *button = NULL;
3213 static GtkWidget *lbl_gps_lat = NULL;
3214 static GtkWidget *lbl_gps_lon = NULL;
3215 static GtkWidget *lbl_center_lat = NULL;
3216 static GtkWidget *lbl_center_lon = NULL;
3217 static MapmanInfo mapman_info;
3218 static gint last_deg_format = 0;
3223 gint prev_degformat = _degformat;
3224 gint fallback_deg_format = _degformat;
3225 gdouble top_left_lat, top_left_lon, bottom_right_lat, bottom_right_lon;
3228 printf("%s()\n", __PRETTY_FUNCTION__);
3230 if(!MAPDB_EXISTS(_curr_repo))
3232 popup_error(_window, "To manage maps, you must set a valid repository "
3233 "database filename in the \"Manage Repositories\" dialog.");
3234 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
3238 // - If the coord system has changed then we need to update certain values
3240 /* Initialize to the bounds of the screen. */
3242 _center.unitx - pixel2unit(MAX(_view_width_pixels,
3243 _view_height_pixels) / 2),
3244 _center.unity - pixel2unit(MAX(_view_width_pixels,
3245 _view_height_pixels) / 2), top_left_lat, top_left_lon);
3247 BOUND(top_left_lat, -90.f, 90.f);
3248 BOUND(top_left_lon, -180.f, 180.f);
3252 _center.unitx + pixel2unit(MAX(_view_width_pixels,
3253 _view_height_pixels) / 2),
3254 _center.unity + pixel2unit(MAX(_view_width_pixels,
3255 _view_height_pixels) / 2), bottom_right_lat, bottom_right_lon);
3256 BOUND(bottom_right_lat, -90.f, 90.f);
3257 BOUND(bottom_right_lon, -180.f, 180.f);
3262 if(!coord_system_check_lat_lon (top_left_lat, top_left_lon, &fallback_deg_format))
3264 _degformat = fallback_deg_format;
3268 // top left is valid, also check bottom right
3269 if(!coord_system_check_lat_lon (bottom_right_lat, bottom_right_lon, &fallback_deg_format))
3271 _degformat = fallback_deg_format;
3276 if(_degformat != last_deg_format)
3278 last_deg_format = _degformat;
3280 if(dialog != NULL) gtk_widget_destroy(dialog);
3286 mapman_info.dialog = dialog = gtk_dialog_new_with_buttons(
3288 GTK_WINDOW(_window), GTK_DIALOG_MODAL,
3289 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
3292 /* Enable the help button. */
3294 hildon_help_dialog_help_enable(
3296 ossohelp_dialog_help_enable(
3298 GTK_DIALOG(mapman_info.dialog), HELP_ID_MAPMAN, _osso);
3301 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
3302 button = gtk_button_new_with_label(_("Clear")));
3303 g_signal_connect(G_OBJECT(button), "clicked",
3304 G_CALLBACK(mapman_clear), &mapman_info);
3306 /* Cancel button. */
3307 gtk_dialog_add_button(GTK_DIALOG(dialog),
3308 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
3310 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
3311 mapman_info.notebook = gtk_notebook_new(), TRUE, TRUE, 0);
3314 gtk_notebook_append_page(GTK_NOTEBOOK(mapman_info.notebook),
3315 vbox = gtk_vbox_new(FALSE, 2),
3316 label = gtk_label_new(_("Setup")));
3317 gtk_notebook_set_tab_label_packing(
3318 GTK_NOTEBOOK(mapman_info.notebook), vbox,
3319 FALSE, FALSE, GTK_PACK_START);
3321 gtk_box_pack_start(GTK_BOX(vbox),
3322 hbox = gtk_hbox_new(FALSE, 4),
3324 gtk_box_pack_start(GTK_BOX(hbox),
3325 mapman_info.rad_download = gtk_radio_button_new_with_label(
3326 NULL,_("Download Maps")),
3328 gtk_box_pack_start(GTK_BOX(hbox),
3329 label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
3331 gtk_container_add(GTK_CONTAINER(label),
3332 mapman_info.chk_overwrite
3333 = gtk_check_button_new_with_label(_("Overwrite"))),
3335 gtk_box_pack_start(GTK_BOX(vbox),
3336 mapman_info.rad_delete
3337 = gtk_radio_button_new_with_label_from_widget(
3338 GTK_RADIO_BUTTON(mapman_info.rad_download),
3342 gtk_box_pack_start(GTK_BOX(vbox),
3343 gtk_hseparator_new(),
3346 gtk_box_pack_start(GTK_BOX(vbox),
3347 mapman_info.rad_by_area
3348 = gtk_radio_button_new_with_label(NULL,
3349 _("By Area (see tab)")),
3351 gtk_box_pack_start(GTK_BOX(vbox),
3352 hbox = gtk_hbox_new(FALSE, 4),
3354 gtk_box_pack_start(GTK_BOX(hbox),
3355 mapman_info.rad_by_route
3356 = gtk_radio_button_new_with_label_from_widget(
3357 GTK_RADIO_BUTTON(mapman_info.rad_by_area),
3358 _("Along Route - Radius (tiles):")),
3360 gtk_box_pack_start(GTK_BOX(hbox),
3361 mapman_info.num_route_radius = hildon_number_editor_new(0,100),
3363 hildon_number_editor_set_value(
3364 HILDON_NUMBER_EDITOR(mapman_info.num_route_radius),
3369 gtk_notebook_append_page(GTK_NOTEBOOK(mapman_info.notebook),
3370 table = gtk_table_new(5, 5, FALSE),
3371 label = gtk_label_new(_("Zoom")));
3372 gtk_notebook_set_tab_label_packing(
3373 GTK_NOTEBOOK(mapman_info.notebook), table,
3374 FALSE, FALSE, GTK_PACK_START);
3375 gtk_table_attach(GTK_TABLE(table),
3376 label = gtk_label_new(
3377 _("Zoom Levels to Download: (0 = most detail)")),
3378 0, 4, 0, 1, GTK_FILL, 0, 4, 0);
3379 gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
3380 snprintf(buffer, sizeof(buffer), "%d", 0);
3381 gtk_table_attach(GTK_TABLE(table),
3382 mapman_info.chk_zoom_levels[0]
3383 = gtk_check_button_new_with_label(buffer),
3384 4, 5 , 0, 1, GTK_FILL, 0, 0, 0);
3385 for(z = 0; z < MAX_ZOOM; ++z)
3387 snprintf(buffer, sizeof(buffer), "%d", z + 1);
3388 gtk_table_attach(GTK_TABLE(table),
3389 mapman_info.chk_zoom_levels[z + 1]
3390 = gtk_check_button_new_with_label(buffer),
3391 z / 4, z / 4 + 1, z % 4 + 1, z % 4 + 2,
3396 gtk_notebook_append_page(GTK_NOTEBOOK(mapman_info.notebook),
3397 mapman_info.tbl_area = gtk_table_new(5, 3, FALSE),
3398 label = gtk_label_new(_("Area")));
3400 /* Label Columns. */
3401 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3402 label = gtk_label_new(DEG_FORMAT_ENUM_TEXT[_degformat].long_field_1),
3403 1, 2, 0, 1, GTK_FILL, 0, 4, 0);
3404 gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.5f);
3406 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3408 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3409 label = gtk_label_new(DEG_FORMAT_ENUM_TEXT[_degformat].long_field_2),
3410 2, 3, 0, 1, GTK_FILL, 0, 4, 0);
3411 gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.5f);
3415 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3416 label = gtk_label_new(_("GPS Location")),
3417 0, 1, 1, 2, GTK_FILL, 0, 4, 0);
3418 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
3419 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3420 lbl_gps_lat = gtk_label_new(""),
3421 1, 2, 1, 2, GTK_FILL, 0, 4, 0);
3422 gtk_label_set_selectable(GTK_LABEL(lbl_gps_lat), TRUE);
3423 gtk_misc_set_alignment(GTK_MISC(lbl_gps_lat), 1.f, 0.5f);
3425 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3427 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3428 lbl_gps_lon = gtk_label_new(""),
3429 2, 3, 1, 2, GTK_FILL, 0, 4, 0);
3430 gtk_label_set_selectable(GTK_LABEL(lbl_gps_lon), TRUE);
3431 gtk_misc_set_alignment(GTK_MISC(lbl_gps_lon), 1.f, 0.5f);
3435 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3436 label = gtk_label_new(_("View Center")),
3437 0, 1, 2, 3, GTK_FILL, 0, 4, 0);
3438 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
3439 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3440 lbl_center_lat = gtk_label_new(""),
3441 1, 2, 2, 3, GTK_FILL, 0, 4, 0);
3442 gtk_label_set_selectable(GTK_LABEL(lbl_center_lat), TRUE);
3443 gtk_misc_set_alignment(GTK_MISC(lbl_center_lat), 1.f, 0.5f);
3446 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3448 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3449 lbl_center_lon = gtk_label_new(""),
3450 2, 3, 2, 3, GTK_FILL, 0, 4, 0);
3451 gtk_label_set_selectable(GTK_LABEL(lbl_center_lon), TRUE);
3452 gtk_misc_set_alignment(GTK_MISC(lbl_center_lon), 1.f, 0.5f);
3455 /* default values for Top Left and Bottom Right are defined by the
3456 * rectangle of the current and the previous Center */
3459 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3460 label = gtk_label_new(_("Top-Left")),
3461 0, 1, 3, 4, GTK_FILL, 0, 4, 0);
3462 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
3463 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3464 mapman_info.txt_topleft_lat = gtk_entry_new(),
3465 1, 2, 3, 4, GTK_FILL, 0, 4, 0);
3466 gtk_entry_set_width_chars(GTK_ENTRY(mapman_info.txt_topleft_lat), 12);
3467 gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_topleft_lat), 1.f);
3468 #ifdef MAEMO_CHANGES
3469 g_object_set(G_OBJECT(mapman_info.txt_topleft_lat),
3471 "hildon-input-mode",
3472 HILDON_GTK_INPUT_MODE_FULL, NULL);
3474 HILDON_INPUT_MODE_HINT,
3475 HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL, NULL);
3476 g_object_set(G_OBJECT(mapman_info.txt_topleft_lat),
3482 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3484 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3485 mapman_info.txt_topleft_lon = gtk_entry_new(),
3486 2, 3, 3, 4, GTK_FILL, 0, 4, 0);
3487 gtk_entry_set_width_chars(GTK_ENTRY(mapman_info.txt_topleft_lon), 12);
3488 gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_topleft_lon), 1.f);
3489 #ifdef MAEMO_CHANGES
3490 g_object_set(G_OBJECT(mapman_info.txt_topleft_lon),
3492 "hildon-input-mode",
3493 HILDON_GTK_INPUT_MODE_FULL, NULL);
3495 HILDON_INPUT_MODE_HINT,
3496 HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL, NULL);
3497 g_object_set(G_OBJECT(mapman_info.txt_topleft_lon),
3506 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3507 label = gtk_label_new(_("Bottom-Right")),
3508 0, 1, 4, 5, GTK_FILL, 0, 4, 0);
3509 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
3510 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3511 mapman_info.txt_botright_lat = gtk_entry_new(),
3512 1, 2, 4, 5, GTK_FILL, 0, 4, 0);
3513 gtk_entry_set_width_chars(GTK_ENTRY(mapman_info.txt_botright_lat), 12);
3514 gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_botright_lat), 1.f);
3515 #ifdef MAEMO_CHANGES
3516 g_object_set(G_OBJECT(mapman_info.txt_botright_lat),
3518 "hildon-input-mode",
3519 HILDON_GTK_INPUT_MODE_FULL, NULL);
3521 HILDON_INPUT_MODE_HINT,
3522 HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL, NULL);
3523 g_object_set(G_OBJECT(mapman_info.txt_botright_lat),
3529 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3531 gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
3532 mapman_info.txt_botright_lon = gtk_entry_new(),
3533 2, 3, 4, 5, GTK_FILL, 0, 4, 0);
3534 gtk_entry_set_width_chars(GTK_ENTRY(mapman_info.txt_botright_lon), 12);
3535 gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_botright_lon), 1.f);
3536 #ifdef MAEMO_CHANGES
3537 g_object_set(G_OBJECT(mapman_info.txt_botright_lon),
3539 "hildon-input-mode",
3540 HILDON_GTK_INPUT_MODE_FULL, NULL);
3542 HILDON_INPUT_MODE_HINT,
3543 HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL, NULL);
3544 g_object_set(G_OBJECT(mapman_info.txt_botright_lon),
3552 /* Default action is to download by area. */
3553 gtk_toggle_button_set_active(
3554 GTK_TOGGLE_BUTTON(mapman_info.rad_by_area), TRUE);
3556 g_signal_connect(G_OBJECT(mapman_info.rad_download), "clicked",
3557 G_CALLBACK(mapman_update_state), &mapman_info);
3558 g_signal_connect(G_OBJECT(mapman_info.rad_delete), "clicked",
3559 G_CALLBACK(mapman_update_state), &mapman_info);
3560 g_signal_connect(G_OBJECT(mapman_info.rad_by_area), "clicked",
3561 G_CALLBACK(mapman_update_state), &mapman_info);
3562 g_signal_connect(G_OBJECT(mapman_info.rad_by_route), "clicked",
3563 G_CALLBACK(mapman_update_state), &mapman_info);
3566 /* Initialize fields. Do no use g_ascii_formatd; these strings will be
3567 * output (and parsed) as locale-dependent. */
3569 gtk_widget_set_sensitive(mapman_info.rad_by_route,
3570 _route.head != _route.tail);
3575 format_lat_lon(_gps.lat, _gps.lon, buffer1, buffer2);
3576 //lat_format(_gps.lat, buffer);
3577 gtk_label_set_text(GTK_LABEL(lbl_gps_lat), buffer1);
3578 //lon_format(_gps.lon, buffer);
3579 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3580 gtk_label_set_text(GTK_LABEL(lbl_gps_lon), buffer2);
3582 unit2latlon(_center.unitx, _center.unity, lat, lon);
3584 format_lat_lon(lat, lon, buffer1, buffer2);
3585 //lat_format(lat, buffer);
3586 gtk_label_set_text(GTK_LABEL(lbl_center_lat), buffer1);
3587 //lon_format(lon, buffer);
3588 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3589 gtk_label_set_text(GTK_LABEL(lbl_center_lon), buffer2);
3591 format_lat_lon(top_left_lat, top_left_lon, buffer1, buffer2);
3593 gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_topleft_lat), buffer1);
3595 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3596 gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_topleft_lon), buffer2);
3598 format_lat_lon(bottom_right_lat, bottom_right_lon, buffer1, buffer2);
3599 //lat_format(lat, buffer);
3600 gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_botright_lat), buffer1);
3601 //lon_format(lon, buffer);
3602 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
3603 gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_botright_lon), buffer2);
3605 /* Initialize zoom levels. */
3608 for(i = 0; i <= MAX_ZOOM; i++)
3610 gtk_toggle_button_set_active(
3611 GTK_TOGGLE_BUTTON(mapman_info.chk_zoom_levels[i]), FALSE);
3614 gtk_toggle_button_set_active(
3615 GTK_TOGGLE_BUTTON(mapman_info.chk_zoom_levels[
3616 _zoom + (_curr_repo->double_size ? 1 : 0)]), TRUE);
3618 gtk_widget_show_all(dialog);
3620 mapman_update_state(NULL, &mapman_info);
3622 if(_curr_repo->type != REPOTYPE_NONE)
3624 gtk_widget_set_sensitive(mapman_info.rad_download, TRUE);
3628 gtk_widget_set_sensitive(mapman_info.rad_download, FALSE);
3630 _("NOTE: You must set a Map URI in the current repository in "
3631 "order to download maps."));
3634 while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
3636 MapUpdateType update_type;
3637 static gint8 download_batch_id = INT8_MIN;
3639 if(gtk_toggle_button_get_active(
3640 GTK_TOGGLE_BUTTON(mapman_info.rad_delete)))
3641 update_type = MAP_UPDATE_DELETE;
3642 else if(gtk_toggle_button_get_active(
3643 GTK_TOGGLE_BUTTON(mapman_info.chk_overwrite)))
3644 update_type = MAP_UPDATE_OVERWRITE;
3646 update_type = MAP_UPDATE_ADD;
3648 ++download_batch_id;
3649 if(gtk_toggle_button_get_active(
3650 GTK_TOGGLE_BUTTON(mapman_info.rad_by_route)))
3652 if(mapman_by_route(&mapman_info, update_type, download_batch_id))
3657 const gchar *text_lon, *text_lat;
3658 //gchar *error_check;
3659 gdouble start_lat, start_lon, end_lat, end_lon;
3661 text_lat = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lat));
3662 text_lon = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lon));
3664 if(!parse_coords(text_lat, text_lon, &start_lat, &start_lon))
3666 popup_error(dialog, _("Invalid Top-Left coordinate specified"));
3670 text_lat = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_botright_lat));
3671 text_lon = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_botright_lon));
3673 if(!parse_coords(text_lat, text_lon, &end_lat, &end_lon))
3675 popup_error(dialog, _("Invalid Bottom-Right coordinate specified"));
3681 if(mapman_by_area(start_lat, start_lon, end_lat, end_lon,
3682 &mapman_info, update_type, download_batch_id))
3687 gtk_widget_hide(dialog);
3689 _degformat = prev_degformat;
3691 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
3696 /* changes visibility of current repo's layers to it's previous state */
3697 void maps_toggle_visible_layers ()
3699 RepoData *rd = _curr_repo;
3700 gboolean changed = FALSE;
3702 printf("%s()\n", __PRETTY_FUNCTION__);
3705 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
3712 if (rd->layer_enabled) {
3714 rd->layer_was_enabled = rd->layer_enabled;
3715 rd->layer_enabled = FALSE;
3718 rd->layer_enabled = rd->layer_was_enabled;
3719 if (rd->layer_was_enabled)
3728 menu_layers_remove_repos ();
3729 menu_layers_add_repos ();
3731 map_refresh_mark (TRUE);
3734 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
3739 /* this routine fired by timer every minute and decrements refetch counter of every active layer of
3740 current repository. If one of layer is expired, it forces map redraw. Redraw routine checks every
3741 layer's tile download timestamp and desides performs refetch if needed */
3743 map_layer_refresh_cb (gpointer data)
3745 RepoData* rd = _curr_repo;
3746 gboolean refresh = FALSE;
3747 printf("%s()\n", __PRETTY_FUNCTION__);
3753 if (rd->layer_enabled && rd->layer_refresh_interval) {
3754 rd->layer_refresh_countdown--;
3755 if (rd->layer_refresh_countdown <= 0) {
3756 rd->layer_refresh_countdown = rd->layer_refresh_interval;
3766 map_refresh_mark (TRUE);
3768 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
3775 Returns amount of seconds since tile downloaded or 0 if tile
3776 have no such information.
3778 gint get_tile_age (GdkPixbuf* pixbuf)
3783 ts = gdk_pixbuf_get_option (pixbuf, layer_timestamp_key);
3788 if (sscanf (ts, "%u", &val))
3789 return time (NULL) - val;