diff --git a/OsmAnd-java/src/net/osmand/osm/MapPoiTypes.java b/OsmAnd-java/src/net/osmand/osm/MapPoiTypes.java index 231fc8e94a..3b0348e2ae 100644 --- a/OsmAnd-java/src/net/osmand/osm/MapPoiTypes.java +++ b/OsmAnd-java/src/net/osmand/osm/MapPoiTypes.java @@ -139,7 +139,7 @@ public class MapPoiTypes { } public Map getAllTranslatedNames() { - Map translation = new HashMap<>(); + Map translation = new HashMap(); for(PoiCategory pc : categories) { for(PoiType pt : pc.getPoiTypes()) { if(pt.isReference()) { diff --git a/OsmAnd/res/layout/download_index_fragment.xml b/OsmAnd/res/layout/download_index_fragment.xml new file mode 100644 index 0000000000..673114158f --- /dev/null +++ b/OsmAnd/res/layout/download_index_fragment.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/values-ca/phrases.xml b/OsmAnd/res/values-ca/phrases.xml index 6708ce9a0d..df7ca75910 100644 --- a/OsmAnd/res/values-ca/phrases.xml +++ b/OsmAnd/res/values-ca/phrases.xml @@ -891,15 +891,15 @@ Arbre Pas de vianants - Xarxa de nodes d\'una ruta ciclista internacional - Xarxa de nodes d\'una ruta ciclista nacional - Xarxa de nodes d\'una ruta ciclista regional - Xarxa de nodes d\'una ruta ciclista local + Xarxa internacional de rutes ciclistes + Xarxa nacional de rutes ciclistes + Xarxa regional de rutes ciclistes + Xarxa local de rutes ciclistes - Xarxa de nodes d\'una ruta senderista internacional - Xarxa de nodes d\'una ruta senderista nacional - Xarxa de nodes d\'una ruta senderista regional - Xarxa de nodes d\'una ruta senderista local + Xarxa internacional de rutes de senderisme + Xarxa nacional de rutes de senderisme + Xarxa regional de rutes de senderisme + Xarxa local de rutes de senderisme Horari de servei Horari de recollida @@ -961,8 +961,8 @@ Refugi per a gossos i gats Refugi per a ocells -Deixalleria - Contenidor +Tipus: deixalleria + Tipus: contenidor Vidre Paper Roba @@ -1040,7 +1040,7 @@ Bolquers Supervisat No supervisat - Encreuament senyalitzat + Amb llums de parada Encreuament no controlat Encreuament no senyalitzat @@ -1050,7 +1050,7 @@ Bassa del molí Twitter Skype - Youtube + YouTube Instagram VKontakte Google+ @@ -1170,11 +1170,38 @@ Alçada sobre el nivell del mar Venda majorista - Aigua (contingut) + Contingut: aigua Portes Pas sobre pedres Torre d\'il·luminació Zona de desenvolupament urbà - Vi (contingut) - Aigües residuals (contingut) + Contingut: vi + Contingut: aigües residuals + Descripció de pagament + + S\'accepta targes de regal + No s\'accepta targes de regal + Pediatria + + Accés a Internet: sí + Accés a Internet: no + + Cadira de rodes: no permesa + Cadira de rodes: restringida + Contingut: carburant + Contingut: gas + Contingut: biomassa + Contingut: aigües residuals + Contingut: cervesa + Contingut: sal + Contingut: gra + + Nudisme: permès + Nudisme: prohibit + Nudisme: obligatori + Població + Edifici especial + Pilona + Informal + diff --git a/OsmAnd/res/values-ca/strings.xml b/OsmAnd/res/values-ca/strings.xml index f8e5ae0120..79392141ea 100644 --- a/OsmAnd/res/values-ca/strings.xml +++ b/OsmAnd/res/values-ca/strings.xml @@ -2134,4 +2134,21 @@ Per retornar a l\'estil habitual dels mapes d\'OsmAnd, només cal desactivar aqu Enregistrament de trajectes Navegació Execució en procés de fons + Afegeix nova categoria + Selecciona categoria + Defineix el sistema de mesura de velocitat + Mesura de velocitat + mm + Milles marines + Quilòmetres per hora + Milles per hora + Metres per segon + Minuts per quilòmetre + Minuts per milla + Millesmarines per hora (nusos) + mmh + min/m + min/km + m/s + diff --git a/OsmAnd/res/values-da/phrases.xml b/OsmAnd/res/values-da/phrases.xml index 482cbdfee7..04fc3a5490 100644 --- a/OsmAnd/res/values-da/phrases.xml +++ b/OsmAnd/res/values-da/phrases.xml @@ -955,7 +955,7 @@ Adgang privat Ingen adgang Adgang destination - Adgang tolerant + Adgang med tilladelse Kundenadgang Adgang for levering Adgang for landbrug @@ -1229,7 +1229,7 @@ Naturisme: forbudt Naturisme: obligatorisk Naturisme: sædvane - Naturisme: liberalt + Naturisme: med tilladelse Højde Højde over havoverfladen @@ -1381,7 +1381,7 @@ Pistepreparering: offpiste Pistepreparering: snescooter Pistepreparering: skating - Pistepreparering: ingen + Pistepreparering: nej Pistepreparering: pukkelpist Havetype: beboelse @@ -1593,4 +1593,94 @@ Internetadgang - gebyr Internetadgang - inget gebyr - +Kun vegetarkost + Vegetarkost + Vegetarkost: nej + Vegetarkost: kun få + Kun veganerkost + Veganerkost + Veganerkost: nej + Kun glutenfri kost + Glutenfri kost + Glutenfri kost: nej + Kun kosher kost + Kosher kost + Kosher kost: nej + Kun halal kost + Halal kost + Halal kost: nej + Kun laktosefri kost + Laktosefri kost + Laktosefri kost: nej + pesco-vegetarkost + + Drive-in: ja + Drive-in: nej + Drive-through: ja + Drive-through: nej + + Bryggeriet navn + Mikrobryggeri + Ingen mikrobryggeri + + Takeway + Ingen takeaway + Kun takeaway + + Levering + Ingen levering + Kun levering + + Udendørsservering + Ingen udendørsservering + Udendørsservering: terrasse + Udendørsservering: fortov + Udendørsservering: gågade + Udendørsservering: have + Udendørsservering: gårdhave + + Cocktails + + Brugte varer + Ingen brugte varer + Kun brugte varer + + Dele + Forhandler + Reparation + Ingen reparation + Reparation af elektriske køretøjer + Motorcykel reparation + Selvbetjening + Ingen selvbetjening + Automatiseret + Ikke automatiseret + Fuld service + Børsteløs + Børsteløs: nej + + Fly tankstation + Offentligt bad + + Mand + Forbudt for mænd + Kvinde + Forbudt for kvinder + Indendørs + Udendørs + Med toiletter + Uden toiletter + Adgang til toiletter for kørestole: ja + Adgang til toiletter for kørestole: nej + Toiletadgang: kunder + Toiletadgang: med tilladelse + Toiletadgang: fællesskab + Toiletadgang: offentlig + + Puslebord + Ingen puslebord + Puslerum + +begivenheder mødested + + diff --git a/OsmAnd/res/values-es-rAR/phrases.xml b/OsmAnd/res/values-es-rAR/phrases.xml index 3e9ff72a1e..b5c6666aac 100644 --- a/OsmAnd/res/values-es-rAR/phrases.xml +++ b/OsmAnd/res/values-es-rAR/phrases.xml @@ -1553,4 +1553,110 @@ Acceso a Internet tarifado Acceso a Internet sin cargo +Acepta tarjetas de combustible Routex + No acepta tarjetas de combustible Routex + Acepta tarjetas Quick + No acepta tarjetas Quick + Acepta SVG + No acepta SVG + Acepta PIKEPASS (designado) + Acepta tarjeta de dinero (Geldkarte) + No acepta tarjeta de dinero (Geldkarte) + Acepta MiniCash + No acepta MiniCash + Acepta Moneo + No acepta Moneo + Acepta vales de comida + No acepta vales de comida + Acepta tarjetas Golden Crown + No acepta tarjetas Golden Crown + Acepta MTS-Money + No acepta MTS-Money + Lugar de eventos + + Sólo dieta vegetariana + Dieta vegetariana + Sin dieta vegetariana + Poca dieta vegetariana + Sólo dieta vegana + Dieta vegana + Sin dieta vegana + Sólo dieta libre de gluten + Dieta libre de gluten + Sin dieta libre de gluten + Sólo dieta kosher + Dieta kosher + Sin dieta kosher + Sólo dieta halal + Dieta halal + Sin dieta halal + Sólo dieta libre de lactosa + Dieta libre de lactosa + Sin dieta libre de lactosa + Dieta pescetariana + + Conducir dentro: si + Conducir dentro: no + Autoservicio: si + Autoservicio: no + + Nombre de cervecería + Micro-cervecería + Sin micro-cervecería + + Servicio de comida para llevar + Sin servicio de comida para llevar + Sólo servicio de comida para llevar + + Sin delivery + Con delivery + Sólo delivery + + Con asientos exteriores + Sin asientos exteriores + Asientos exteriores: terraza + Asientos exteriores: vereda + Asientos exteriores: zona peatonal + Asientos exteriores: jardín + Asientos exteriores: patio + + Con cócteles + + Con artículos de segunda mano + Sin artículos de segunda mano + Sólo artículos de segunda mano + + Partes + Repartidor + Reparación + Sin reparación + Reparación de vehículos eléctricos + Reparación de motocicletas + Con autoservicio + Sin autoservicio + Automatizado + No automatizado + Servicio completo + Estación de combustible para aviones + Baño público + + Masculino + Prohibido para hombres + Femenino + Prohibido para mujeres + Cubierto (puertas adentro) + Al aire libre + Con baños + Sin baños + Acceso a los baños para sillas de rueda + Sin acceso a los baños para sillas de rueda + Acceso a los baños: clientes + Acceso a los baños: permisivo + Acceso a los baños: comunidad + Acceso a los baños: público + + Con cambiador de pañales + Sin cambiador de pañales + Habitación para cambio de pañales + diff --git a/OsmAnd/res/values-es/phrases.xml b/OsmAnd/res/values-es/phrases.xml index fd0efe3f6d..63b5771726 100644 --- a/OsmAnd/res/values-es/phrases.xml +++ b/OsmAnd/res/values-es/phrases.xml @@ -1557,4 +1557,110 @@ Acceso a Internet tarifado Acceso a Internet sin cargo +Acepta PIKEPASS (designado) + Acepta tarjetas de combustible Routex + No acepta tarjetas de combustible Routex + Acepta tarjetas Quick + No acepta tarjetas Quick + Acepta tarjeta de dinero (Geldkarte) + No acepta tarjeta de dinero (Geldkarte) + Acepta MiniCash + No acepta MiniCash + Acepta Moneo + No acepta Moneo + Acepta SVG + No acepta SVG + Acepta vales de comida + No acepta vales de comida + Acepta tarjetas Golden Crown + No acepta tarjetas Golden Crown + Acepta MTS-Money + No acepta MTS-Money + Lugar de eventos + + Sólo dieta vegetariana + Dieta vegetariana + Sin dieta vegetariana + Poca dieta vegetariana + Sólo dieta vegana + Dieta vegana + Sin dieta vegana + Sólo dieta libre de gluten + Dieta libre de gluten + Sin dieta libre de gluten + Sólo dieta kosher + Dieta kosher + Sin dieta kosher + Sólo dieta halal + Dieta halal + Sin dieta halal + Sólo dieta libre de lactosa + Dieta libre de lactosa + Sin dieta libre de lactosa + Dieta pescetariana + + Conducir dentro: si + Conducir dentro: no + Autoservicio: si + Autoservicio: no + + Nombre de cervecería + Micro-cervecería + Sin micro-cervecería + + Servicio de comida para llevar + Sin servicio de comida para llevar + Sólo servicio de comida para llevar + + Con delivery + Sin delivery + Sólo delivery + + Con asientos exteriores + Sin asientos exteriores + Asientos exteriores: terraza + Asientos exteriores: vereda + Asientos exteriores: zona peatonal + Asientos exteriores: jardín + Asientos exteriores: patio + + Con cócteles + + Con artículos de segunda mano + Sin artículos de segunda mano + Sólo artículos de segunda mano + + Partes + Repartidor + Reparación + Sin reparación + Reparación de vehículos eléctricos + Reparación de motocicletas + Con autoservicio + Sin autoservicio + Automatizado + No automatizado + Servicio completo + Estación de combustible para aviones + Baño público + + Masculino + Prohibido para hombres + Femenino + Prohibido para mujeres + Cubierto (puertas adentro) + Al aire libre + Con baños + Sin baños + Acceso a los baños para sillas de rueda + Sin acceso a los baños para sillas de rueda + Acceso a los baños: clientes + Acceso a los baños: permisivo + Acceso a los baños: comunidad + Acceso a los baños: público + + Con cambiador de pañales + Sin cambiador de pañales + Habitación para cambio de pañales + diff --git a/OsmAnd/res/values-it/strings.xml b/OsmAnd/res/values-it/strings.xml index cfb6c1d446..0dedda6007 100644 --- a/OsmAnd/res/values-it/strings.xml +++ b/OsmAnd/res/values-it/strings.xml @@ -845,7 +845,7 @@ Usa i nomi degli oggetti Preferenze relative all\'accessibilità Accessibilità - Nord America - Messico + Nord America Nord America - Stati Uniti America Centrale Sud America @@ -2033,7 +2033,7 @@ Si consiglia di aggiungere uno o più punti intermedi per migliorarne le prestaz Gestisci Modifica Filtra per nome - Digita per cercare fra tutti i PDI + Scrivi per cercare fra tutti i PDI Europa - Paesi Bassi Copia dei file fallita Memoria esterna @@ -2127,7 +2127,7 @@ Si consiglia di aggiungere uno o più punti intermedi per migliorarne le prestaz Ci teniamo molto Valuta questa app Dicci perché. - Per favore dai a OsmAnd la tua valutazione su Google Play + Dai a OsmAnd un punteggio su Google Play Dicci cosa cambieresti in questa app. Aggiornamenti automatici Caricamento fallito diff --git a/OsmAnd/res/values-ku/strings.xml b/OsmAnd/res/values-ku/strings.xml index 26dd45c472..af4295a6f8 100644 --- a/OsmAnd/res/values-ku/strings.xml +++ b/OsmAnd/res/values-ku/strings.xml @@ -11,4 +11,5 @@ کامێرا له به رده ست نيه Vai vēlaties, lai OsmAnd kopē uz jauno vietu arī savus datu failus? Norādītajā direktorijā nevar veidot Kartes - + Nu Texe + diff --git a/OsmAnd/res/values-pt-rBR/phrases.xml b/OsmAnd/res/values-pt-rBR/phrases.xml index 88a62a0f57..32ade2a7b4 100644 --- a/OsmAnd/res/values-pt-rBR/phrases.xml +++ b/OsmAnd/res/values-pt-rBR/phrases.xml @@ -887,15 +887,15 @@ Guindaste Atração turística Árvore - Ponto de rede cicloviária internacional - Ponto de rede cicloviária nacional - Ponto de rede cicloviária regional - Ponto de rede cicloviária local + Rede de rota cicloviária internacional + Rede de rota cicloviária nacional + Rede de rota cicloviária regional + Rede de rota cicloviária local - Ponto de rede de caminhada internacional - Ponto de rede de caminhada nacional - Ponto de rede de caminhada regional - Ponto de rede de caminhada local + Rede de rota internacional de caminhada + Rede de rota nacional de caminhada + Rede de rota regional de caminhada + Rede de rota local de caminhada Horário de funcionamento Descrição @@ -926,10 +926,10 @@ Taxa Objeto abandonado - Rota de caminhada internacional - Rota de caminhada nacional - Rota de caminhada regional - Rota de caminhada local + Rota internacional de caminhada + Rota nacional de caminhada + Rota regional de caminhada + Rota local de caminhada Referência de rota de caminhada Fiscalização de trânsito @@ -939,7 +939,7 @@ Acesso proibido Acesso de destino Acesso autorizado - Acesso para clientes + Acesso para cliente Acesso para entrega Acesso agrícola @@ -1141,22 +1141,22 @@ Cadeirante Silo de abrigo - Silagem (conteúdo) - Água (conteúdo) - Chorume (conteúdo) - Óleo (conteúdo) - Combustível (conteúdo) - Estrume (conteúdo) - Vinho (conteúdo) - Esgoto (conteúdo) - Gás (conteúdo) - Biomassa (conteúdo) - Águas residuais (conteúdo) - Colheita (conteúdo) - Forragens (conteúdo) - Cerveja (conteúdo) - Sal (conteúdo) - Grão (conteúdo) + Conteúdo: silagem + Conteúdo: água + Conteúdo: chorume + Conteúdo: óleo + Conteúdo: combustível + Conteúdo: estrume + Conteúdo: vinho + Conteúdo: esgoto + Conteúdo: gás + Conteúdo: biomassa + Conteúdo: águas residuais + Conteúdo: colheita + Conteúdo: forragens + Conteúdo: cerveja + Conteúdo: sal + Conteúdo: grão Atacado @@ -1213,7 +1213,7 @@ Coca Prado com pomar Altura - Altura acima do nível do mar + Elevação acima do nível do mar Torre de teleférico Torre de transmissão @@ -1346,4 +1346,9 @@ Nível Observatório de aves + Com acesso à Internet + Sem acesso à Internet + + Cadeira de rodas: não permitido + Cadeira de rodas: limitado diff --git a/OsmAnd/res/values-ru/phrases.xml b/OsmAnd/res/values-ru/phrases.xml index 00f31648d7..370b74c912 100644 --- a/OsmAnd/res/values-ru/phrases.xml +++ b/OsmAnd/res/values-ru/phrases.xml @@ -1028,8 +1028,6 @@ Источник энергии: мазут Источник энергии: дизельное топливо - Самообслуживание - Интернациональное название Общенациональное название Региональное название @@ -1404,4 +1402,93 @@ Взимается плата за интернет Плата за интернет не взимается + Место проведения мероприятий + + Только вегетарианское питание + Вегетарианское питание + Вегетарианское питание не предлагается + Вегетарианское питание: небольшой выбор + Только веганское питание + Веганское питание + Веганское питание не предлагается + Только безглютеновое питание + Безглютеновое питание + Безглютеновое питание не предлагается + Только кошерное питание + Кошерное питание + Кошерное питание не предлагается + Только халяльная пища + Халяльная пища + Халяльная пища не предлагается + Только безлактозные продукты + Безлактозные продукты + Безлактозные продукты не предлагаются + Пескетарианская диета + + Обслуживание клиентов сидящих в автомобиле + Клиенты, сидящие в автомобиле, не обслуживаются + Обслуживание клиентов сидящих в автомобиле + Клиенты, сидящие в автомобиле, не обслуживаются + + Пивоварня поставщик + Собственная пивоварня + Нет собственной пивоварни + + На вынос + На вынос: нет + Только на вынос + + С доставкой + Без доставки + Только с доставкой + + Места на открытом воздухе + Нет мест на открытом воздухе + Места на открытом воздухе: терраса + Места на открытом воздухе: тротуар + Места на открытом воздухе: пешеходная зона + Места на открытом воздухе: сад + Места на открытом воздухе: патио + + Коктейли + + Подержанный товар + Подержанный товар отсутствует + Только подержанный товар + + Запчасти + Дилер + Ремонт + Ремонт не производится + Ремонт электротранспорта + Ремонт мотоциклов + Самообслуживание + Самообслуживание: нет + Автоматизация + Без автоматизации + Полный комплекс услуг + Бесконтактная + Контактная + + Заправочная станция для воздушного транспорта + Общественная баня + + Для мужчин + Не для мужчин + Для женщин + Не для женщин + Внутри помещения + Снаружи + С туалетом + Без туалета + Доступ в туалет для инвалидных колясок: да + Доступ в туалет для инвалидных колясок: нет + Доступ в туалет: только для посетителей + Доступ в туалет: с разрешения владельца + Доступ в туалет: общественный + + Пеленальный столик + Пеленальный столик отсутствует + Пеленальная комната + \ No newline at end of file diff --git a/OsmAnd/res/values-ru/strings.xml b/OsmAnd/res/values-ru/strings.xml index 8d11f33b0b..4a30564b00 100644 --- a/OsmAnd/res/values-ru/strings.xml +++ b/OsmAnd/res/values-ru/strings.xml @@ -2101,4 +2101,6 @@ Все несохраненные изменения будут потеряны. Продолжить? Моделировать используя записанный GPX или рассчитанный маршрут Остановить моделирование + Добавить новую + Выберите категорию diff --git a/OsmAnd/res/values/phrases.xml b/OsmAnd/res/values/phrases.xml index a17642f96b..420c0e0e66 100644 --- a/OsmAnd/res/values/phrases.xml +++ b/OsmAnd/res/values/phrases.xml @@ -1239,8 +1239,6 @@ Energy source: oil Energy source: diesel - Self service - International name National name Regional name @@ -1553,4 +1551,94 @@ Internet access - fee charged Internet access - no fee + Events venue + + Only vegetarian diet + Vegetarian diet + Vegetarian diet: no + Vegetarian diet: few + Only vegan diet + Vegan diet + Vegan diet: no + Only gluten-free diet + Gluten-free diet + Gluten-free diet: no + Only kosher diet + Kosher diet + Kosher diet: no + Only halal diet + Halal diet + Halal diet: no + Only lactose-free diet + Lactose-free diet + Lactose-free diet: no + Pescetarian diet + + Drive-in: yes + Drive-in: no + Drive-through: yes + Drive-through: yes + + Brewery name + Microbrewery + No microbrewery + + Takeway + No takeway + Takeway only + + Delivery + No delivery + Delivery only + + Outdoor seating + No outdoor seating + Outdoor seating: terrace + Outdoor seating: sidewalk + Outdoor seating: pedestrian zone + Outdoor seating: garden + Outdoor seating: patio + + Cocktails + + Second-hand goods + No second-hand goods + Second-hand goods only + + Parts + Dealer + Repair + No repair + Repair of electrical vehicles + Motorcycle repair + Self-service + No self-service + Automated + Not automated + Full service + Brushless + Brushless: no + + Aircraft fuel station + Public bath + + Male + Forbidden for men + Female + Forbidden for female + Indoor + Outdoor + With toilets + Without toilets + Access to the toilets for wheelchairs: yes + Access to the toilets for wheelchairs: no + Toilets access: customers + Toilets access: permissive + Toilets access: community + Toilets access: public + + Diaper changing table + No diaper changing table + Diaper changing room + diff --git a/OsmAnd/src/net/osmand/plus/WorldRegion.java b/OsmAnd/src/net/osmand/plus/WorldRegion.java index 5eeceb5077..8e204ab095 100644 --- a/OsmAnd/src/net/osmand/plus/WorldRegion.java +++ b/OsmAnd/src/net/osmand/plus/WorldRegion.java @@ -10,6 +10,7 @@ import net.osmand.plus.download.DownloadActivityType; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -34,12 +35,12 @@ public class WorldRegion { private LatLon bboxTopLeft; private LatLon bboxBottomRight; - private LinkedList resourceTypes; + private List resourceTypes; // Hierarchy private WorldRegion superregion; - private LinkedList subregions; - private LinkedList flattenedSubregions; + private List subregions; + private List flattenedSubregions; private boolean purchased; private boolean isInPurchasedArea; @@ -64,19 +65,23 @@ public class WorldRegion { return bboxBottomRight; } - public LinkedList getResourceTypes() { + public List getResourceTypes() { return resourceTypes; } + public void setResourceTypes(List resourceTypes) { + this.resourceTypes = resourceTypes; + } + public WorldRegion getSuperregion() { return superregion; } - public LinkedList getSubregions() { + public List getSubregions() { return subregions; } - public LinkedList getFlattenedSubregions() { + public List getFlattenedSubregions() { return flattenedSubregions; } diff --git a/OsmAnd/src/net/osmand/plus/download/BaseDownloadActivity.java b/OsmAnd/src/net/osmand/plus/download/BaseDownloadActivity.java index 6673b5c139..d7418160df 100644 --- a/OsmAnd/src/net/osmand/plus/download/BaseDownloadActivity.java +++ b/OsmAnd/src/net/osmand/plus/download/BaseDownloadActivity.java @@ -118,6 +118,10 @@ public class BaseDownloadActivity extends ActionBarProgressActivity { } + public void onCategorizationFinished() { + + } + public boolean startDownload(IndexItem item) { if (downloadListIndexThread.getCurrentRunningTask() != null && getEntriesToDownload().get(item) == null) { downloadQueue.add(item); diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java b/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java index 2ca76cc790..252cc0ef90 100644 --- a/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java +++ b/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java @@ -32,6 +32,7 @@ import net.osmand.plus.activities.OsmandBaseExpandableListAdapter; import net.osmand.plus.activities.OsmandExpandableListFragment; import net.osmand.plus.activities.TabActivity; import net.osmand.plus.base.BasicProgressAsyncTask; +import net.osmand.plus.download.items.DownloadItemsFragment; import net.osmand.plus.download.newimplementation.IndexItemCategoryWithSubcat; import net.osmand.plus.download.newimplementation.NewLocalIndexesFragment; import net.osmand.plus.srtmplugin.SRTMPlugin; @@ -117,8 +118,10 @@ public class DownloadActivity extends BaseDownloadActivity { mTabs.add(new TabActivity.TabItem(R.string.download_tab_updates, getString(R.string.download_tab_updates), UpdatesIndexFragment.class)); +// mTabs.add(new TabActivity.TabItem(R.string.download_tab_local, +// getString(R.string.download_tab_local), NewLocalIndexesFragment.class)); mTabs.add(new TabActivity.TabItem(R.string.download_tab_local, - getString(R.string.download_tab_local), NewLocalIndexesFragment.class)); + getString(R.string.download_tab_local), DownloadItemsFragment.class)); viewPager.setAdapter(new TabActivity.OsmandFragmentPagerAdapter(getSupportFragmentManager(), mTabs)); mSlidingTabLayout.setViewPager(viewPager); @@ -324,6 +327,18 @@ public class DownloadActivity extends BaseDownloadActivity { } } + @Override + public void onCategorizationFinished() { + for (WeakReference ref : fragSet) { + Fragment f = ref.get(); + if (f instanceof DownloadItemsFragment) { + if (f.isAdded()) { + ((DownloadItemsFragment) f).onCategorizationFinished(); + } + } + } + } + public void downloadListUpdated() { for (WeakReference ref : fragSet) { Fragment f = ref.get(); diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadIndexesThread.java b/OsmAnd/src/net/osmand/plus/download/DownloadIndexesThread.java index b9bf648950..8eb4f09fc4 100644 --- a/OsmAnd/src/net/osmand/plus/download/DownloadIndexesThread.java +++ b/OsmAnd/src/net/osmand/plus/download/DownloadIndexesThread.java @@ -25,6 +25,7 @@ import net.osmand.plus.Version; import net.osmand.plus.base.BasicProgressAsyncTask; import net.osmand.plus.download.DownloadFileHelper.DownloadFileShowWarning; import net.osmand.plus.download.DownloadOsmandIndexesHelper.AssetIndexItem; +import net.osmand.plus.download.items.ItemsListBuilder; import net.osmand.plus.download.newimplementation.IndexItemCategoryWithSubcat; import net.osmand.plus.helpers.DatabaseHelper; import net.osmand.plus.resources.ResourceManager; @@ -411,11 +412,17 @@ public class DownloadIndexesThread { @Override protected IndexFileList doInBackground(Void... params) { - return DownloadOsmandIndexesHelper.getIndexesList(ctx); + IndexFileList indexFileList = DownloadOsmandIndexesHelper.getIndexesList(ctx); + indexFiles = indexFileList; + if (indexFileList != null) { + ItemsListBuilder builder = new ItemsListBuilder(app, app.getWorldRegion()); + builder.invalidate(); + builder.build(); + } + return indexFileList; } protected void onPostExecute(IndexFileList result) { - indexFiles = result; if (indexFiles != null && uiActivity != null) { prepareFilesToUpdate(); boolean basemapExists = uiActivity.getMyApplication().getResourceManager().containsBasemap(); @@ -445,6 +452,7 @@ public class DownloadIndexesThread { uiActivity.updateProgress(false); runCategorization(uiActivity.getDownloadType()); runCategorization(); // for new implementation + uiActivity.onCategorizationFinished(); } } diff --git a/OsmAnd/src/net/osmand/plus/download/items/DownloadItemsFragment.java b/OsmAnd/src/net/osmand/plus/download/items/DownloadItemsFragment.java new file mode 100644 index 0000000000..04a5f61ed3 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/download/items/DownloadItemsFragment.java @@ -0,0 +1,254 @@ +package net.osmand.plus.download.items; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.view.MenuItemCompat; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.TextView; + +import net.osmand.PlatformUtil; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.WorldRegion; +import net.osmand.plus.download.DownloadActivity; + +import org.apache.commons.logging.Log; + +import java.text.MessageFormat; +import java.util.Locale; + +public class DownloadItemsFragment extends Fragment { + private static final Log LOG = PlatformUtil.getLog(DownloadItemsFragment.class); + private static final MessageFormat formatGb = new MessageFormat("{0, number,#.##} GB", Locale.US); + + public static final int RELOAD_ID = 0; + + private ItemsListBuilder builder; + private WorldRegionsAdapter worldRegionsAdapter; + private WorldMapAdapter worldMapAdapter; + private VoicePromtsAdapter voicePromtsAdapter; + + private ListView worldRegionsListView; + private ListView worldMapListView; + private ListView voicePromtsListView; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.download_index_fragment, container, false); + + builder = new ItemsListBuilder(getMyApplication(), getMyApplication().getWorldRegion()); + boolean hasBuilt = builder.build(); + + worldRegionsListView = (ListView) view.findViewById(R.id.list_world_regions); + worldRegionsAdapter = new WorldRegionsAdapter(getActivity(), getMyApplication()); + worldRegionsListView.setAdapter(worldRegionsAdapter); + if (hasBuilt) { + fillWorldRegionsAdapter(); + } + + worldMapListView = (ListView) view.findViewById(R.id.list_world_map); + worldMapAdapter = new WorldMapAdapter(getActivity(), getMyApplication()); + worldMapListView.setAdapter(worldMapAdapter); + if (hasBuilt) { + fillWorldMapAdapter(); + } + + voicePromtsListView = (ListView) view.findViewById(R.id.list_voice_promts); + voicePromtsAdapter = new VoicePromtsAdapter(getActivity(), getMyApplication()); + voicePromtsListView.setAdapter(voicePromtsAdapter); + if (hasBuilt) { + fillVoicePromtsAdapter(); + } + + return view; + } + + public static void setListViewHeightBasedOnChildren(ListView listView) { + ListAdapter listAdapter = listView.getAdapter(); + if (listAdapter == null) { + // pre-condition + return; + } + + int totalHeight = 0; + for (int i = 0; i < listAdapter.getCount(); i++) { + View listItem = listAdapter.getView(i, null, listView); + listItem.measure(0, 0); + totalHeight += listItem.getMeasuredHeight(); + } + + ViewGroup.LayoutParams params = listView.getLayoutParams(); + params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); + listView.setLayoutParams(params); + listView.requestLayout(); + } + + public OsmandApplication getMyApplication() { + return (OsmandApplication)getActivity().getApplication(); + } + + private void fillWorldRegionsAdapter() { + if (worldRegionsAdapter != null) { + worldRegionsAdapter.clear(); + worldRegionsAdapter.addAll(builder.getRegionsFromAllItems()); + setListViewHeightBasedOnChildren(worldRegionsListView); + } + } + + private void fillWorldMapAdapter() { + if (worldMapAdapter != null) { + worldMapAdapter.clear(); + worldMapAdapter.addAll(builder.getRegionMapItems()); + setListViewHeightBasedOnChildren(worldMapListView); + } + } + + private void fillVoicePromtsAdapter() { + if (voicePromtsAdapter != null) { + voicePromtsAdapter.clear(); + //voicePromtsAdapter.addAll(cats); + } + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + MenuItem item = menu.add(0, RELOAD_ID, 0, R.string.shared_string_refresh); + item.setIcon(R.drawable.ic_action_refresh_dark); + MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == RELOAD_ID) { + // re-create the thread + DownloadActivity.downloadListIndexThread.runReloadIndexFiles(); + return true; + } + return super.onOptionsItemSelected(item); + } + + private DownloadActivity getDownloadActivity() { + return (DownloadActivity) getActivity(); + } + + public void onCategorizationFinished() { + if (builder.build()) { + fillWorldRegionsAdapter(); + fillWorldMapAdapter(); + fillVoicePromtsAdapter(); + } + } + + private static class WorldRegionsAdapter extends ArrayAdapter { + private final OsmandApplication osmandApplication; + + public WorldRegionsAdapter(Context context, OsmandApplication osmandApplication) { + super(context, R.layout.simple_list_menu_item); + this.osmandApplication = osmandApplication; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder; + if (convertView == null) { + convertView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.simple_list_menu_item, parent, false); + viewHolder = new ViewHolder(); + viewHolder.textView = (TextView) convertView.findViewById(R.id.title); + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + Drawable iconLeft = osmandApplication.getIconsCache() + .getContentIcon(R.drawable.ic_world_globe_dark); + viewHolder.textView.setCompoundDrawablesWithIntrinsicBounds(iconLeft, null, null, null); + viewHolder.textView.setText(getItem(position).getName()); + return convertView; + } + + private static class ViewHolder { + TextView textView; + } + } + + private static class WorldMapAdapter extends ArrayAdapter { + private final OsmandApplication osmandApplication; + + public WorldMapAdapter(Context context, OsmandApplication osmandApplication) { + super(context, R.layout.simple_list_menu_item); + this.osmandApplication = osmandApplication; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder; + if (convertView == null) { + convertView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.simple_list_menu_item, parent, false); + viewHolder = new ViewHolder(); + viewHolder.textView = (TextView) convertView.findViewById(R.id.title); + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + Drawable iconLeft = osmandApplication.getIconsCache() + .getContentIcon(R.drawable.ic_world_globe_dark); + viewHolder.textView.setCompoundDrawablesWithIntrinsicBounds(iconLeft, null, null, null); + viewHolder.textView.setText(getItem(position).getTitle()); + return convertView; + } + + private static class ViewHolder { + TextView textView; + } + } + + private static class VoicePromtsAdapter extends ArrayAdapter { + private final OsmandApplication osmandApplication; + + public VoicePromtsAdapter(Context context, OsmandApplication osmandApplication) { + super(context, R.layout.simple_list_menu_item); + this.osmandApplication = osmandApplication; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder; + if (convertView == null) { + convertView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.simple_list_menu_item, parent, false); + viewHolder = new ViewHolder(); + viewHolder.textView = (TextView) convertView.findViewById(R.id.title); + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + Drawable iconLeft = osmandApplication.getIconsCache() + .getContentIcon(R.drawable.ic_world_globe_dark); + viewHolder.textView.setCompoundDrawablesWithIntrinsicBounds(iconLeft, null, null, null); + viewHolder.textView.setText(getItem(position).toString()); + return convertView; + } + + private static class ViewHolder { + TextView textView; + } + } + +} diff --git a/OsmAnd/src/net/osmand/plus/download/items/ItemsListBuilder.java b/OsmAnd/src/net/osmand/plus/download/items/ItemsListBuilder.java new file mode 100644 index 0000000000..fb3d0dabf6 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/download/items/ItemsListBuilder.java @@ -0,0 +1,377 @@ +package net.osmand.plus.download.items; + +import android.content.Context; + +import net.osmand.PlatformUtil; +import net.osmand.map.OsmandRegions; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.WorldRegion; +import net.osmand.plus.download.DownloadActivity; +import net.osmand.plus.download.DownloadActivityType; +import net.osmand.plus.download.IndexItem; +import net.osmand.util.Algorithms; + +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class ItemsListBuilder { + + public class ResourceItem { + + private String resourceId; + private String title; + private long contentSize; + private long containerSize; + private boolean disabled; + + private IndexItem indexItem; + private WorldRegion worldRegion; + + public IndexItem getIndexItem() { + return indexItem; + } + + public WorldRegion getWorldRegion() { + return worldRegion; + } + + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public long getContentSize() { + return contentSize; + } + + public void setContentSize(long contentSize) { + this.contentSize = contentSize; + } + + public long getContainerSize() { + return containerSize; + } + + public void setContainerSize(long containerSize) { + this.containerSize = containerSize; + } + + public boolean isDisabled() { + return disabled; + } + + public void setDisabled(boolean disabled) { + this.disabled = disabled; + } + + public ResourceItem(IndexItem indexItem, WorldRegion worldRegion) { + this.indexItem = indexItem; + this.worldRegion = worldRegion; + } + } + + class ResourceItemComparator implements Comparator { + @Override + public int compare(Object obj1, Object obj2) { + String str1; + String str2; + + if (obj1 instanceof WorldRegion) { + str1 = ((WorldRegion)obj1).getName(); + } else { + ResourceItem item = (ResourceItem)obj1; + str1 = item.title + item.getIndexItem().getType().getTag(); + } + + if (obj2 instanceof WorldRegion) { + str2 = ((WorldRegion)obj2).getName(); + } else { + ResourceItem item = (ResourceItem)obj2; + str2 = item.title + item.getIndexItem().getType().getTag(); + } + + return str1.compareTo(str2); + } + } + + private static final org.apache.commons.logging.Log LOG = PlatformUtil.getLog(ItemsListBuilder.class); + + private static Map> resourcesByRegions = + new HashMap<>(); + private static List searchableWorldwideRegionItems = new LinkedList<>(); + + private List regionMapItems; + private List allResourceItems; + private List allSubregionItems; + + private OsmandApplication app; + private WorldRegion region; + + private boolean invalidated; + private boolean srtmDisabled; + private boolean hasSrtm; + + public List getRegionMapItems() { + return regionMapItems; + } + + public List getAllResourceItems() { + return allResourceItems; + } + + public List getRegionsFromAllItems() { + List list = new LinkedList<>(); + for (Object obj : allResourceItems) { + if (obj instanceof WorldRegion) { + list.add((WorldRegion)obj); + } + } + return list; + } + + public ItemsListBuilder(OsmandApplication app) { + this.app = app; + regionMapItems = new LinkedList(); + allResourceItems = new LinkedList(); + allSubregionItems = new LinkedList<>(); + } + + public ItemsListBuilder(OsmandApplication app, WorldRegion region) { + this(app); + this.region = region; + } + + public boolean build() { + return obtainDataAndItems(); + } + + private boolean obtainDataAndItems() { + if (invalidated) { + resourcesByRegions.clear(); + } + + if (resourcesByRegions.isEmpty()) { + if (!prepareData()) { + return false; + } + } + + collectSubregionsDataAndItems(); + collectResourcesDataAndItems(); + + LOG.warn("getRegionMapItems >>>"); + for (ResourceItem resourceItem : getRegionMapItems()) { + LOG.warn("resId=" + resourceItem.getIndexItem().getFileName() + " title=" + resourceItem.getTitle()); + } + + LOG.warn("getAllResourceItems >>>"); + for (Object obj : getAllResourceItems()) { + if (obj instanceof WorldRegion) { + WorldRegion item = (WorldRegion)obj; + LOG.warn("W resId=" + item.getRegionId() + " title=" + item.getName()); + } else if (obj instanceof ResourceItem) { + ResourceItem resourceItem = (ResourceItem)obj; + LOG.warn("R resId=" + resourceItem.getIndexItem().getFileName() + " title=" + resourceItem.getTitle()); + } + } + + invalidated = false; + + return true; + } + + public void invalidate() { + invalidated = true; + } + + private boolean prepareData() { + List resourcesInRepository = DownloadActivity.downloadListIndexThread.getCachedIndexFiles(); + if (resourcesInRepository == null) { + return false; + } + + boolean doInit = resourcesByRegions.isEmpty(); + boolean initSearchableRegions = searchableWorldwideRegionItems.isEmpty() || doInit; + + if (initSearchableRegions) { + searchableWorldwideRegionItems.clear(); + } + + List mergedRegions = app.getWorldRegion().getFlattenedSubregions(); + mergedRegions.add(app.getWorldRegion()); + for(WorldRegion region : mergedRegions) + { + if (initSearchableRegions) { + searchableWorldwideRegionItems.add(region); + } + + String downloadsIdPrefix = region.getDownloadsIdPrefix().toLowerCase(); + + Map regionResources = new HashMap<>(); + + if (!doInit) + { + regionResources.putAll(resourcesByRegions.get(region)); + } + + if (doInit) + { + List typesArray = new LinkedList<>(); + boolean hasSrtm = false; + for (IndexItem resource : resourcesInRepository) + { + if (!resource.getFileName().startsWith(downloadsIdPrefix)) + continue; + + if (resource.getType() == DownloadActivityType.SRTM_COUNTRY_FILE) { + hasSrtm = true; + } + + typesArray.add(resource.getType()); + + regionResources.put(resource.getFileName(), resource); + } + + if (region.getSuperregion() != null && hasSrtm && region.getSuperregion().getSuperregion() != app.getWorldRegion()) + { + if (!region.getSuperregion().getResourceTypes().contains(DownloadActivityType.SRTM_COUNTRY_FILE)) + { + region.getSuperregion().getResourceTypes().add(DownloadActivityType.SRTM_COUNTRY_FILE); + Collections.sort(region.getSuperregion().getResourceTypes(), new Comparator() { + @Override + public int compare(DownloadActivityType dat1, DownloadActivityType dat2) { + return dat1.getTag().compareTo(dat2.getTag()); + } + }); + } + } + + Collections.sort(typesArray, new Comparator() { + @Override + public int compare(DownloadActivityType dat1, DownloadActivityType dat2) { + return dat1.getTag().compareTo(dat2.getTag()); + } + }); + region.setResourceTypes(typesArray); + } + + resourcesByRegions.put(region, regionResources); + } + return true; + } + + private void collectSubregionsDataAndItems() { + srtmDisabled = false; //todo: check if srtm plugin disabled + hasSrtm = false; + + // Collect all regions (and their parents) that have at least one + // resource available in repository or locally. + + allResourceItems.clear(); + allSubregionItems.clear(); + regionMapItems.clear(); + + for (WorldRegion subregion : region.getFlattenedSubregions()) + { + if (subregion.getSuperregion() == region) + { + if (subregion.getFlattenedSubregions().size() > 0) { + allSubregionItems.add(subregion); + } else { + collectSubregionItems(subregion); + } + } + } + } + + private void collectSubregionItems(WorldRegion region) { + Map regionResources = resourcesByRegions.get(region); + + List regionMapArray = new LinkedList<>(); + List allResourcesArray = new LinkedList(); + + Context context = app.getApplicationContext(); + OsmandRegions osmandRegions = app.getRegions(); + + for (IndexItem indexItem : regionResources.values()) { + + String name = indexItem.getVisibleName(context, osmandRegions); + if (Algorithms.isEmpty(name)) { + continue; + } + + ResourceItem resItem = new ResourceItem(indexItem, region); + resItem.setResourceId(indexItem.getFileName()); + resItem.setTitle(name); + resItem.setContentSize(indexItem.getContentSize()); + resItem.setContainerSize(indexItem.getSize()); + + if (region != this.region && srtmDisabled) + { + if (hasSrtm && indexItem.getType() == DownloadActivityType.SRTM_COUNTRY_FILE) + continue; + + if (indexItem.getType() == DownloadActivityType.SRTM_COUNTRY_FILE) + { + resItem.setTitle("srtm_disabled"); // todo: constant + resItem.setContentSize(0); + resItem.setContainerSize(0); + } + + if (!hasSrtm && indexItem.getType() == DownloadActivityType.SRTM_COUNTRY_FILE) + hasSrtm = true; + } + + + if (region == this.region) { + regionMapArray.add(resItem); + } else { + allResourcesArray.add(resItem); + } + + } + + regionMapItems.addAll(regionMapArray); + + if (allResourcesArray.size() > 1) { + allSubregionItems.add(region); + } else { + allResourceItems.addAll(allResourcesArray); + } + } + + private void collectResourcesDataAndItems() { + collectSubregionItems(region); + + allResourceItems.addAll(allSubregionItems); + + Collections.sort(allResourceItems, new ResourceItemComparator()); + Collections.sort(regionMapItems, new ResourceItemComparator()); + + /* + * todo: remove seamarks if plugin is off + if (![[OAIAPHelper sharedInstance] productPurchased:kInAppId_Addon_Nautical]) { + for (ResourceItem *item in _regionMapItems) + if (item.resourceId.compare(QString(kWorldSeamarksKey)) == 0) { + [_regionMapItems removeObject:item]; + break; + } + } + */ + } +}