Merge branch 'master' into custom_routing_config

# Conflicts:
#	OsmAnd/src/net/osmand/plus/profiles/SelectProfileBottomSheetDialogFragment.java
This commit is contained in:
Vitaliy 2020-02-15 13:14:55 +02:00
commit 30d063f2af
53 changed files with 1973 additions and 275 deletions

View file

@ -12,6 +12,8 @@ public interface ITileSource {
public String getUrlToLoad(int x, int y, int zoom);
public String getUrlTemplate();
public byte[] getBytes(int x, int y, int zoom, String dirWithTiles) throws IOException;
public int getMinimumZoomSupported();
@ -32,4 +34,15 @@ public interface ITileSource {
public void deleteTiles(String path);
public int getAvgSize();
public String getRule();
public String getRandoms();
public boolean isInvertedYTile();
public boolean isTimeSupported();
public boolean getInversiveZoom();
}

View file

@ -174,6 +174,16 @@ public class TileSourceManager {
return invertedYTile;
}
@Override
public boolean isTimeSupported() {
return expirationTimeMillis != -1;
}
@Override
public boolean getInversiveZoom() {
return false;
}
public void setInvertedYTile(boolean invertedYTile) {
this.invertedYTile = invertedYTile;
}
@ -410,6 +420,11 @@ public class TileSourceManager {
}
}
}
@Override
public int getAvgSize() {
return this.avgSize;
}
}
private static Map<String, String> readMetaInfoFile(File dir) {

View file

@ -268,4 +268,5 @@
<string name="last_update_from_telegram_duration">Letzte Aktualisierung von Telegram: vor %1$s</string>
<string name="last_response_duration">Letzte Antwort: vor %1$s</string>
<string name="duration_ago">vor %1$s</string>
<string name="shared_string_error_short">ERR</string>
</resources>

View file

@ -38,8 +38,8 @@
<string name="yard">yd</string>
<string name="foot">ft</string>
<string name="mile">mi</string>
<string name="km">ک‌م</string>
<string name="m">متر</string>
<string name="km">km</string>
<string name="m">m</string>
<string name="nm">nmi</string>
<string name="min_mile">min/m</string>
<string name="min_km">min/km</string>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,3H18V7H14V17C14,19.2091 12.2091,21 10,21C7.7909,21 6,19.2091 6,17C6,14.7909 7.7909,13 10,13C10.7286,13 11.4117,13.1948 12,13.5351V3Z"
android:fillColor="#727272"/>
</vector>

View file

@ -11,6 +11,7 @@
android:id="@+id/button_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:duplicateParentState="true"
tools:ignore="UselessParent">
<net.osmand.plus.widgets.TextViewEx
@ -22,6 +23,7 @@
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
android:duplicateParentState="true"
tools:text="Button" />
</LinearLayout>

View file

@ -10,6 +10,7 @@
android:id="@+id/button_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:duplicateParentState="true"
tools:ignore="UselessParent">
<net.osmand.plus.widgets.TextViewEx
@ -21,6 +22,7 @@
android:gravity="center_vertical|start"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
android:duplicateParentState="true"
tools:text="Button" />
</LinearLayout>

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="20dp">
<android.support.v7.widget.SwitchCompat
android:id="@+id/switchItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:minHeight="48dp"
android:text="@string/shared_string_include_data"
android:textSize="@dimen/default_list_text_size"
tools:text="@string/shared_string_include_data" />
<ExpandableListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@null"
android:dividerHeight="0dp"
android:drawSelectorOnTop="false"
android:groupIndicator="@android:color/transparent"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout>

View file

@ -12,6 +12,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="@dimen/context_menu_controller_height"
android:duplicateParentState="true"
tools:ignore="UselessParent">
<net.osmand.plus.widgets.TextViewEx
@ -25,6 +26,7 @@
android:textAllCaps="true"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
android:duplicateParentState="true"
tools:text="Button" />
</LinearLayout>

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:minHeight="66dp">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_padding"
tools:src="@drawable/ic_action_info_dark" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/title_tv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
tools:text="Quick actions" />
<android.support.v7.widget.AppCompatCheckBox
android:id="@+id/check_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:focusable="false" />
</LinearLayout>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/list_divider"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout>

View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:minHeight="66dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/explist_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_padding"
android:src="@drawable/ic_action_arrow_down" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/title_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
tools:text="Quick actions" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/sub_text_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
tools:text="8 of 4" />
</LinearLayout>
<View
android:id="@+id/vertical_divider"
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/content_padding"
android:layout_marginBottom="@dimen/content_padding"
android:background="?attr/list_divider" />
<android.support.v7.widget.AppCompatCheckBox
android:id="@+id/check_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_padding"
android:focusable="false" />
</LinearLayout>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/list_divider"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout>

View file

@ -25,26 +25,40 @@
android:src="@drawable/ic_action_mode_back"
android:tint="?attr/default_icon_color" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/toolbar_title"
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:maxLines="2"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/dialog_header_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/routing_settings_2" />
android:paddingTop="@dimen/content_padding_half"
android:paddingBottom="@dimen/content_padding_half"
android:background="?attr/card_and_list_background_basic"
android:orientation="vertical">
<include
layout="@layout/profile_button_small"
android:layout_width="@dimen/route_info_toolbar_button_size"
android:layout_height="@dimen/route_info_toolbar_button_size"
android:layout_marginLeft="@dimen/content_padding_half"
android:layout_marginRight="@dimen/content_padding_half" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:maxLines="2"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/dialog_header_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/routing_settings_2" />
<TextView
android:id="@+id/toolbar_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:textAppearance="@style/TextAppearance.ContextMenuSubtitle"
tools:text="Some description" />
</LinearLayout>
</LinearLayout>

View file

@ -62,7 +62,6 @@
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:textAppearance="@style/TextAppearance.ContextMenuSubtitle"
android:visibility="gone"
tools:text="Some description" />
</LinearLayout>

View file

@ -1836,7 +1836,7 @@
<string name="osn_add_dialog_error">حدث استثناء: لم يتم إنشاء الملاحظة.</string>
<string name="osn_close_dialog_error">حدث استثناء: لم يتم غلق الملاحظة.</string>
<string name="osb_comment_dialog_error">لا يمكن إضافة تعليق.</string>
<string name="shared_string_commit">ارتكاب</string>
<string name="shared_string_commit">تقديم</string>
<string name="context_menu_item_delete_waypoint">حذف إحداثية GPX ؟</string>
<string name="context_menu_item_edit_waypoint">تعديل/حذف</string>
<string name="lang_nds">ألمانية منخفضة</string>
@ -3429,4 +3429,5 @@
\n</string>
<string name="copy_coordinates">نسخ الإحداثيات</string>
<string name="routing_profile_direct_to">مباشر إلى نقطة</string>
<string name="sort_by_category">الفرز حسب الفئة</string>
</resources>

View file

@ -2163,7 +2163,7 @@ Lon %2$s</string>
<string name="quick_action_map_source_title">Kartenquellen</string>
<string name="quick_action_map_source_action">Kartenquelle hinzufügen</string>
<string name="quick_action_map_source_switch">Die Kartenquelle wurde in „%s“ geändert.</string>
<string name="quick_action_btn_tutorial_title">Tastenposition ändern</string>
<string name="quick_action_btn_tutorial_title">Schaltflächenposition ändern</string>
<string name="quick_action_favorites_show">Favoriten anzeigen</string>
<string name="quick_action_favorites_hide">Favoriten ausblenden</string>
<string name="quick_action_category_descr">Kategorie, in der der Favorit gespeichert werden soll:</string>
@ -2173,7 +2173,7 @@ Lon %2$s</string>
<string name="quick_action_add_osm_bug_descr">Eine Schaltfläche, um eine OSM-Notiz in der Bildschirmmitte einzufügen.</string>
<string name="quick_action_add_poi_descr">Eine Schaltfläche, um einen POI in der Bildschirmmitte einzufügen.</string>
<string name="quick_action_navigation_voice_descr">Umschalter, um die Sprachansagen während der Navigation ein- oder auszuschalten.</string>
<string name="quick_action_add_parking_descr">Taste, um eine Parkposition in der Bildschirmmitte einzufügen.</string>
<string name="quick_action_add_parking_descr">Eine Schaltfläche, um eine Parkposition in der Bildschirmmitte einzufügen.</string>
<string name="quick_action_interim_dialog">Dialog zum Bearbeiten anzeigen</string>
<string name="favorite_autofill_toast_text">" gespeichert unter "</string>
<string name="quick_action_duplicates">Schnellaktion in %1$s umbenannt, um Duplikate zu vermeiden.</string>
@ -2182,7 +2182,7 @@ Lon %2$s</string>
<string name="quick_action_showhide_poi_descr">Umschalter, um POIs auf der Karte ein- oder auszublenden.</string>
<string name="quick_action_add_create_items">Objekte erstellen</string>
<string name="quick_action_bug_descr">Diese Nachricht wird ins Kommentarfeld eingetragen.</string>
<string name="quick_action_btn_tutorial_descr">Langes Drücken und Ziehen der Taste ändert ihre Bildschirmposition.</string>
<string name="quick_action_btn_tutorial_descr">Langes Drücken und Ziehen der Schaltfläche ändert ihre Bildschirmposition.</string>
<string name="quick_action_map_overlay_switch">Karten-Overlay wurde in „%s“ geändert.</string>
<string name="quick_action_map_underlay_switch">Karten-Underlay wurde in „%s“ geändert.</string>
<string name="navigate_point_olc_info_invalid">Ungültiger OLC
@ -2194,7 +2194,7 @@ Lon %2$s</string>
<string name="auto_split_recording_title">Aufzeichnungen bei Lücken automatisch trennen</string>
<string name="auto_split_recording_descr">Nach 6-minütiger Pause neues Segment, nach 2-stündiger Pause neuen Track und nach Pause mit Datumsänderung neue Datei beginnen.</string>
<string name="navigate_point_olc">Offener Standortcode (OLC)</string>
<string name="quick_action_page_list_descr">Taste, um durch die Liste unten zu blättern.</string>
<string name="quick_action_page_list_descr">Eine Schaltfläche, um durch die Liste unten zu blättern.</string>
<string name="routing_attr_height_obstacles_name">Höhendaten berücksichtigen</string>
<string name="routing_attr_height_obstacles_description">Faktor im Geländeprofil (über SRTM, ASTER und EU-DEM-Daten).</string>
<string name="rendering_attr_depthContours_name">Nautische Tiefenlinien</string>
@ -3484,10 +3484,10 @@ Lon %2$s</string>
<string name="multimedia_use_system_camera">System-App verwenden</string>
<string name="multimedia_photo_play_sound">Auslöseton der Kamera</string>
<string name="reset_to_default_category_button_promo">Durch das Zurücksetzen auf die Standardeinstellung wird die Sortierung auf den Standardzustand nach der Installation zurückgesetzt.</string>
<string name="accessibility_mode_disabled">Eingabehilfenmodus ist in ihrem System deaktiviert.</string>
<string name="accessibility_mode_disabled">Eingabehilfenmodus ist in Ihrem System deaktiviert.</string>
<string name="use_system_screen_timeout">Zeitlimit für den Systembildschirm verwenden</string>
<string name="use_system_screen_timeout_promo">Standardmäßig deaktiviert, wenn OsmAnd im Vordergrund läuft, wird der Bildschirm nicht ausgeblendet.
\n
<string name="use_system_screen_timeout_promo">Standardmäßig deaktiviert. Wenn OsmAnd im Vordergrund läuft, wird der Bildschirm nicht ausgeblendet.
\n
\nWenn aktiviert, verwendet OsmAnd das Zeitlimit für den Systembildschirm.</string>
<string name="live_monitoring">Online-Aufzeichnung</string>
<string name="clear_recorded_data">Aufgezeichnete Daten löschen</string>
@ -3524,4 +3524,5 @@ Lon %2$s</string>
\n
\n</string>
<string name="sort_by_category">Nach Kategorie sortieren</string>
<string name="tracks_view_descr">Ihre aufgezeichneten Tracks befinden sich in %1$s oder im OsmAnd-Ordner.</string>
</resources>

View file

@ -2784,7 +2784,7 @@
<string name="poi_aerialway_heating">Hejtado</string>
<string name="poi_pump">Pumpilo</string>
<string name="poi_observatory_designation">Apliko</string>
<string name="poi_telescope_type">Speco</string>
<string name="poi_telescope_type">Speco de teleskopo</string>
<string name="poi_animal_training_type">Dresado de</string>
<string name="poi_embassy_type">Speco de diplomata oficejo</string>
<string name="poi_city_capital">Ĉefurbo</string>
@ -2819,7 +2819,7 @@
<string name="poi_shelter_type">Speco de ŝirmejo</string>
<string name="poi_fireplace">Kameno</string>
<string name="poi_seasonal">Sezona</string>
<string name="poi_water_characteristic">Akvospeco</string>
<string name="poi_water_characteristic">Speco de akvo</string>
<string name="poi_beach_surface_type">Sablobordo</string>
<string name="poi_nudism">Nudeco</string>
<string name="poi_wheelchair_accessibility">Rulseĝa alireblo</string>
@ -3087,7 +3087,7 @@
<string name="poi_zoo_reptile">rampulejo</string>
<string name="poi_stands">Spektoteraso</string>
<string name="poi_motorcycle_services">Servo</string>
<string name="poi_motorcycle_type">Motorcikla speco</string>
<string name="poi_motorcycle_type">Speco de motorciklo</string>
<string name="poi_motorcycle_sales_yes">vendo</string>
<string name="poi_motorcycle_sales_no">vendo: ne</string>
<string name="poi_motorcycle_sales_yes_used">vendo, brokanto</string>
@ -3508,7 +3508,7 @@
<string name="poi_atm">Bankaŭtomato</string>
<string name="poi_shoe_repair">Ŝu-riparejo</string>
<string name="poi_bulk_purchase">Vendado sen pakumo</string>
<string name="poi_substation_type">Speco</string>
<string name="poi_substation_type">Speco de elektrosubcentralo</string>
<string name="poi_bulk_purchase_yes">jes</string>
<string name="poi_bulk_purchase_only">nur</string>
<string name="poi_pipeline_substation">Konduktuba substacio</string>

View file

@ -1844,7 +1844,7 @@ Lon: %2$s</string>
<string name="edit_filter_save_as_menu_item">Konservi kiel</string>
<string name="edit_filter_delete_dialog_title">Ĉu forigi tiun ĉi filtrilon\?</string>
<string name="edit_filter_delete_message">Forigis filtrilon “%1$s”</string>
<string name="edit_filter_create_message">Kreis filtrilon “%1$s”</string>
<string name="edit_filter_create_message">Kreis filtrilon \'%1$s\'</string>
<string name="email">retpoŝto</string>
<string name="av_camera_focus">Speco de fotila fokuso</string>
<string name="av_camera_focus_descr">Fokuso de fotilo:</string>
@ -3457,7 +3457,7 @@ Indikas lokon: %1$s x %2$s"</string>
<string name="monitoring_min_accuracy_descr">Registritaj estos nur punktoj mezuritaj kun la minimuma precizo (en metroj kiel raportitaj fare de Androido per la GPScirkvitaro). Precizo rilatas al disiĝo de valoro dum ripetaj mezuroj kaj ne ĉiam rilatas al ekzakteco, kiu determinas proksimecon de mezuroj al via vera pozicio.</string>
<string name="monitoring_min_accuracy_descr_side_effect">Kromefiko: pro filtri laŭ precizo, iuj punktoj mezuritaj ekz. sub pontoj aŭ arboj, inter altaj konstruaĵoj, aŭ dum malbonaj veteraj kondiĉoj povos manki.</string>
<string name="monitoring_min_accuracy_descr_recommendation">Konsilo: estas malfacile antaŭscii pri kio estos registra kaj kio estos filtrita, do estus bone ne aktivigi tiun ĉi filtrilon.</string>
<string name="shared_string_available">Disponebla</string>
<string name="shared_string_available">Disponeblaj</string>
<string name="add_custom_category">Aldoni propran kategorion</string>
<string name="rendering_attr_streetLightingNight_name">Montri nur dum nokto</string>
<string name="plugin_prefs_reset_successful">Rekomencigis ĉiujn agordojn pri kromprogramoj.</string>
@ -3479,31 +3479,32 @@ Indikas lokon: %1$s x %2$s"</string>
\n
\nAktivigu tion ĉi por ke OsmAnd uzu sisteman agordon pri malŝalti ekranon.</string>
<string name="clear_recorded_data">Forviŝi registritajn datumojn</string>
<string name="release_3_6">• profiloj: eblo ŝanĝi ilian ordigon, agordi emblemon por mapo, ŝanĝi ĉiujn agordojn por bazaj profiloj kaj restarigi implicitajn valorojn
<string name="release_3_6">• profiloj: eblo ŝanĝi ilian ordigon, agordi emblemon por mapo, ŝanĝi ĉiujn agordojn por bazaj profiloj kaj restarigi implicitajn valorojn
\n
\n• aldonis numeron de elveturejo dum navigadi
\n• aldonis numeron de elveturejo dum navigadi
\n
\n• rearanĝitaj agordoj pri kromprogramoj
\n• rearanĝitaj agordoj pri kromprogramoj
\n
\n• rearanĝita la ekrano de agordoj por rapide agordi ĉiun profilon
\n• rearanĝita ekrano de agordoj por rapide agordi ĉiun profilon
\n
\n• aldonis eblon kopii agordojn el alia profilo
\n• aldonis eblon kopii agordojn el alia profilo
\n
\n• aldonis eblon ŝanĝi ordigon kaj kaŝi kategoriojn de interesejoj dum serĉi
\n• aldonis eblon ŝanĝi ordigon kaj kaŝi kategoriojn de interesejoj dum serĉi
\n
\n• rektigis emblemojn de interesejoj sur la mapo
\n• rektigis emblemojn de interesejoj sur la mapo
\n
\n• aldonis informojn pri senleviĝo/sunsubiro al la ekrano “agordi mapon”
\n• aldonis informojn pri senleviĝo/sunsubiro al la ekrano “agordi mapon”
\n
\n• aldonis emblemojn de hejmo kaj laboro al la mapo
\n• aldonis emblemojn de hejmo kaj laboro al la mapo
\n
\n• aldonis subtenon por plurliniaj priskriboj al la agordoj
\n• aldonis subtenon por plurliniaj priskriboj al la agordoj
\n
\n• ĝusta transliterumo al la mapo de Japanujo
\n• ĝusta transliterumo al la mapo de Japanujo
\n
\n• aldonis mapon de Antarkto
\n
\n</string>
<string name="copy_coordinates">Kopii koordinatojn</string>
<string name="routing_profile_direct_to">Rekte al punkto</string>
<string name="sort_by_category">Ordigi laŭ kategorio</string>
</resources>

View file

@ -3525,4 +3525,5 @@ Lon %2$s</string>
\n</string>
<string name="copy_coordinates">Copiar coordenadas</string>
<string name="routing_profile_direct_to">Directo al punto</string>
<string name="sort_by_category">Ordenar por categoría</string>
</resources>

View file

@ -3524,4 +3524,5 @@ Lon %2$s</string>
\n</string>
<string name="copy_coordinates">Copiar coordenadas</string>
<string name="routing_profile_direct_to">Directo al punto</string>
<string name="sort_by_category">Ordenar por categoría</string>
</resources>

View file

@ -92,7 +92,7 @@
<string name="poi_musical_instrument">Instrumentu musikalak</string>
<string name="poi_newsagent">Berri agentzia</string>
<string name="poi_optician">Optometrista</string>
<string name="poi_organic">Janari organikoa</string>
<string name="poi_organic">Produktu organikoak</string>
<string name="poi_paint">Margo denda</string>
<string name="poi_pet">Animali denda</string>
<string name="poi_photo">Argazkilaritza denda</string>
@ -3633,4 +3633,20 @@
<string name="poi_cash_withdrawal_bank_card">Dirua ateratzea</string>
<string name="poi_bath_type">Mota</string>
<string name="poi_bath_open_air">Aire zabalean</string>
<string name="poi_bicycle_private">Bizikleta sarbidea: pribatua</string>
<string name="poi_bicycle_dismount">Bizikleta sarbidea: oinez</string>
<string name="poi_bicycle_destination">Bizikleta sarbidea: helmuga</string>
<string name="poi_bicycle_permissive">Bizikleta sarbidea: malgua</string>
<string name="poi_bicycle_customers">Bizikleta sarbidea: bezeroak</string>
<string name="poi_horse_private">Zaldi sarbidea: pribatua</string>
<string name="poi_horse_destination">Zaldi sarbidea: helmuga</string>
<string name="poi_horse_permissive">Zaldi sarbidea: malgua</string>
<string name="poi_foot_yes">Oinezkoentzako sarbidea: bai</string>
<string name="poi_foot_private">Oinezkoentzako sarbidea: pribatua</string>
<string name="poi_foot_no">Oinezkoentzako sarbidea: ez</string>
<string name="poi_foot_destination">Oinezkoentzako sarbidea: helmuga</string>
<string name="poi_foot_permissive">Oinezkoentzako sarbidea: malgua</string>
<string name="poi_foot_customers">Oinezkoentzako sarbidea: bezeroak</string>
<string name="poi_volcano_type">Mota</string>
<string name="poi_volcano_status">Egoera</string>
</resources>

View file

@ -560,7 +560,7 @@
<string name="unzipping_file">در حال استخراج فایل…</string>
<string name="network_provider">شبکه</string>
<string name="int_seconds">ثانیه</string>
<string name="int_min">دقیقه</string>
<string name="int_min">min.</string>
<string name="show_route">جزئیات مسیر</string>
<string name="poi_context_menu_modify">اصلاح POI</string>
<string name="poi_context_menu_delete">حذف POI</string>
@ -753,8 +753,8 @@
<string name="indexing_poi">نمایه‌کردن POI</string>
<string name="indexing_transport">در حال نمایه‌کردن حمل‌ونقل…</string>
<string name="shared_string_io_error">خطای ورودی/خروجی</string>
<string name="km">ک‌م</string>
<string name="m">متر</string>
<string name="km">km</string>
<string name="m">m</string>
<string name="map_tile_source">منبع کاشی‌های نقشه</string>
<string name="mark_point">هدف</string>
<string name="speak_speed_limit">سرعت مجاز</string>
@ -1261,8 +1261,8 @@
<string name="layer_amenity_label">برچسب‌های لایهٔ POI</string>
<string name="show_zoom_buttons_navigation_descr">هنگام ناوبری دکمه‌های بزرگ‌نمایی را نشان بده.</string>
<string name="show_zoom_buttons_navigation">نمایش دکمه‌های بزرگ‌نمایی</string>
<string name="sort_by_distance">ترتیب براساس مسافت</string>
<string name="sort_by_name">ترتیب براساس نام</string>
<string name="sort_by_distance">ترتیب بر اساس مسافت</string>
<string name="sort_by_name">ترتیب بر اساس نام</string>
<string name="none_selected_gpx">ابتدا یک فایل GPX را با لمس طولانی انتخاب کنید.</string>
<string name="local_index_select_gpx_file">یک رد انتخاب کنید</string>
<string name="no_index_file_to_download">فایلی برای دانلود پیدا نشد. لطفاً اتصال اینترنت را بررسی کنید.</string>
@ -1801,7 +1801,7 @@
<string name="rendering_value_medium_w_name">متوسط</string>
<string name="rendering_value_low_name">کم</string>
<string name="rendering_attr_hideWaterPolygons_description">آب</string>
<string name="rendering_attr_hideWaterPolygons_name">مخفی‌کردن آب</string>
<string name="rendering_attr_hideWaterPolygons_name">محدوده‌های آب</string>
<string name="shared_string_overview">مرور کلی</string>
<string name="nearest_cities">نزدیکترین شهرها</string>
<string name="quick_action_auto_zoom_desc">دکمه‌ای برای روشن/خاموش کردن زوم خودکار وابسته به سرعت.</string>
@ -2037,7 +2037,7 @@
<string name="shared_string_wikipedia">ویکی‌پدیا</string>
<string name="local_recordings_delete_all_confirm">از حدف این %1$d یادداشت مطمئن هستید؟</string>
<string name="osmand_parking_hour">س</string>
<string name="osmand_parking_minute">دق‍</string>
<string name="osmand_parking_minute">min</string>
<string name="shared_string_collapse">مخفی شود</string>
<string name="rendering_attr_roadStyle_description">ظاهر جاده</string>
<string name="navigate_point_olc">کدِ مکانی باز (OLC)</string>
@ -2680,7 +2680,7 @@
<string name="nautical_renderer">دریایی</string>
<string name="will_open_tomorrow_at">فردا باز می‌شود، در ساعت</string>
<string name="day_off_label">تعطیل</string>
<string name="copy_location_name">کپی‌کردن موقعیت/نام POI</string>
<string name="copy_location_name">کپی موقعیت/نام POI</string>
<string name="toast_empty_name_error">مکان بی‌نام</string>
<string name="show_closed_notes">دیدن یادداشت‌های بسته</string>
<string name="switch_osm_notes_visibility_desc">پنهان/آشکارکردن یادداشت‌های OSM.</string>
@ -2916,7 +2916,7 @@
<string name="voice_announcements">پیام‌های گفتاری</string>
<string name="intermediate_destinations">مقصدهای میانی</string>
<string name="arrive_at_time">زمان رسیدن: %1$s</string>
<string name="cubic_m">مترمکعب</string>
<string name="cubic_m"></string>
<string name="metric_ton">تن</string>
<string name="shared_string_capacity">ظرفیت</string>
<string name="shared_string_width">عرض</string>
@ -3523,31 +3523,32 @@
\n
\nاگر فعال باشد، OsmAnd از تنظیمات دستگاه برای زمان خاموش‌شدن صفحه استفاده می‌کند.</string>
<string name="clear_recorded_data">پاک‌سازی دادهٔ ضبط‌شده</string>
<string name="release_3_6">• پروفایل‌ها: اکنون می‌توانید ترتیب پروفایل‌ها و نماد آن‌ها را تنظیم کنید. تنظیمات پروفایل‌های پایه را تغییر دهید یا آن‌ها را به پیشفرض بازنشانی کنید.
\n
\n • شمارهٔ خروجی به ناوبری افزوده شد
\n
\n • تنظیمات افزونه‌ها بازسازی شد
\n
\n • صفحهٔ تنظیمات برای دسترسی فوری به همهٔ پروفایل‌ها بازسازی شد
\n
\n • گزینه‌ای برای کپی‌کردن تنظیمات از پروفایل دیکر افزوده شد
\n
\n • امکان تغییر، مرتب‌سازی یا مخفی‌کردن دسته‌بندی نقاط توجه (POI) هنگام جست‌وجو افزوده شد
\n
\n • چینش نماد نقاط توجه روی نقشه درست شد
\n
\n • دادهٔ غروب/طلوع خورشید به «پیکربندی نقشه» افزوده شد
\n
\n • نمادهای خانه/کار روی نقشه افزوده شد
\n
\n • از توضیحات چندخطی در تنظیمات پشتیبانی می‌شود
\n
\n • نویسه‌گردانیِ درست به نقشهٔ ژاپن افزوده شد
\n
<string name="release_3_6">• پروفایل‌ها: اکنون می‌توانید ترتیب پروفایل‌ها و نماد آن‌ها را تنظیم کنید. تنظیمات پروفایل‌های پایه را تغییر دهید یا آن‌ها را به پیشفرض بازنشانی کنید.
\n
\n • شمارهٔ خروجی به ناوبری افزوده شد
\n
\n • تنظیمات افزونه‌ها بازسازی شد
\n
\n • صفحهٔ تنظیمات برای دسترسی فوری به همهٔ پروفایل‌ها بازسازی شد
\n
\n • گزینه‌ای برای کپی‌کردن تنظیمات از پروفایل دیگر افزوده شد
\n
\n • امکان تغییر، مرتب‌سازی یا مخفی‌کردن دسته‌بندی نقاط توجه (POI) هنگام جست‌وجو افزوده شد
\n
\n • چینش نقاط توجه روی نقشه درست شد
\n
\n • دادهٔ غروب/طلوع خورشید به «پیکربندی نقشه» افزوده شد
\n
\n • نمادهای خانه/محل کار روی نقشه افزوده شد
\n
\n • از توضیحات چندخطی در تنظیمات پشتیبانی می‌شود
\n
\n • نویسه‌گردانیِ درست به نقشهٔ ژاپن افزوده شد
\n
\n • نقشهٔ جنوبگان افزوده شد
\n
\n</string>
<string name="copy_coordinates">کپی مختصات</string>
<string name="routing_profile_direct_to">مستقیم تا نقطه</string>
<string name="sort_by_category">ترتیب بر اساس دسته</string>
</resources>

View file

@ -3495,4 +3495,5 @@ représentant la zone : %1$s x %2$s</string>
\n</string>
<string name="copy_coordinates">Copier les coordonnées</string>
<string name="routing_profile_direct_to">Le plus direct</string>
<string name="sort_by_category">Trier par catégorie</string>
</resources>

View file

@ -1482,7 +1482,7 @@ Memoria in proporzione %4$s MB (limite di Android %5$s MB, Dalvik %6$s MB).</str
<string name="shared_string_clear_all">Cancella tutto</string>
<string name="shared_string_my_location">La mia posizione</string>
<string name="shared_string_my_favorites">Preferiti</string>
<string name="shared_string_tracks">Le mie tracce</string>
<string name="shared_string_tracks">Tracce</string>
<string name="shared_string_currently_recording_track">Traccia in corso di registrazione</string>
<string name="waypoint_visit_after">Visita dopo</string>
<string name="waypoint_visit_before">Visita prima</string>
@ -3456,4 +3456,70 @@ Rappresenta l\'area: %1$s x %2$s</string>
<string name="ltr_or_rtl_combine_via_slash">%1$s/%2$s</string>
<string name="sunset_at">Tramonto alle %1$s</string>
<string name="sunrise_at">Alba alle %1$s</string>
<string name="button_rate">Valuta</string>
<string name="monitoring_prefs_descr">Navigazione, accuratezza della registrazione</string>
<string name="accessibility_announce">Annunci</string>
<string name="select_map_icon_descr">Icona visualizzata da fermi.</string>
<string name="search_offline_geo_error">Impossibile analizzare il dato geo \'%s\'.</string>
<string name="monitoring_min_speed_descr">"Questo è un filtro delle basse velocità per non registrare i punti inferiori a una data velocità. Questo può permettere di registrare tracce dall\'aspetto più pulito quando visualizzate sulla mappa."</string>
<string name="monitoring_min_speed_descr_side_effect">Effetto collaterale: alle tue tracce mancheranno tutte le sezioni in cui il criterio della velocità non sarà soddisfatto (es. quando spingi la tua bici in una elevata pendenza). Altrettanto non ci saranno informazioni nei periodi di riposo o ristoro. Questo ha effetto su tutte le analisi ed elaborazione dei dati, come quando si prova a determinare la lunghezza totale del tuo percorso, il tempo in movimento, o la velocità media.</string>
<string name="monitoring_min_speed_descr_recommendation">Raccomandazione: prova prima a utilizzare il sensore del movimento attraverso la registrazione del filtro del minimo dislocamento (B), potrebbe produrre migliori risultati, e perderai meno dati. Se le tue tracce continuano a essere sporche a basse velocità, prova con valori maggiori di zero. Si prega di notare che alcune misurazioni possono non riportare nessuna velocità (alcuni metodi basti sulle reti), in questi casi non registrerai alcun dato.</string>
<string name="monitoring_min_speed_descr_remark">Osservazione: controllo velocità &gt; 0 : molti chip GPS riportano un valore di velocità solo se l\'algoritmo determina che tu sei in movimento, e nessuno invece se non lo sei. Quindi utilizzando l\'impostazione &gt; 0 nel filtro, in un certo senso utilizza il sensore di movimento del chip GPS. Ma anche se non filtrati qui nel momento della registrazione, comunque utilizziamo questa caratteristica nell\'analisi dei nostri file GPX per determinare al distanza corretta, es. il valore visualizzato in questo campo è la distanza registrata finché si è in movimento.</string>
<string name="monitoring_min_accuracy_descr">Questo registrerà solo punti misurati con un\'accuratezza minima (in metri/piedi, come riportati da Android per il tuo chipset). L\'accuratezza si riferisce alla variabilità di misure ripetute, e non è direttamente correlato alla precisione, che definisce quanto la tua misurazione è vicina alla vera posizione.</string>
<string name="monitoring_min_accuracy_descr_side_effect">Effetto collaterale: come conseguenza del filtraggio per accuratezza, i punti possono essere completamente mancanti per esempio sotto a ponti, alberi, in mezzo a edifici elevati o in certe condizioni meteo.</string>
<string name="monitoring_min_accuracy_descr_recommendation">Raccomandazione: è difficile da predire cosa verrà registrato e cosa no, potrebbe essere preferibile disattivare questo filtro.</string>
<string name="monitoring_min_accuracy_descr_remark">Osservazione: se il GPS è stato disattivato poco prima di una registrazione, i primi punti misurati potrebbero avere una minore accuratezza, perciò nel nostro codice noi possiamo voler attendere qualche secondo prima oppure prima di registrare dei punti (o registrare i 3 migliori punti consecutivi, ecc...), ma questo non è ancora implementato .</string>
<string name="monitoring_min_distance_descr">Questo filtro evita che punti duplicati siano registrati quando lo spostamento è troppo piccolo, crea un migliore aspetto delle tracce che non vengono successivamente elaborate.</string>
<string name="monitoring_min_distance_descr_side_effect">Effetto collaterale: periodi di riposo non sono registrati affatto oppure con un singolo punto. Piccoli (reali) movimenti (es. lateralmente, per marcare un possible spegnimento nel tuo viaggio) possono essere scartati dal filtro. Il file contiene meno informazioni per la post-elaborazione e presenta statistiche peggiori filtrando i punti ovviamente ridondanti al momento della registrazione, mantenendo potenzialmente artefatti causati da cattiva ricezione o effetti del chipset GPS.</string>
<string name="monitoring_min_distance_descr_recommendation">Raccomandazione: un valore di 5 metri potrebbe funzionare bene se non necessiti di registrare dettagli che hanno una misura inferiore di questo e non vuoi chiaramente registrare dati quando sei fermo.</string>
<string name="live_monitoring_time_buffer">Tempo tampone</string>
<string name="live_monitoring_tracking_interval">Intervallo di registrazione</string>
<string name="live_monitoring_adress">Indirizzo web</string>
<string name="live_monitoring_adress_descr">Specifica l\'indirizzo web con i parametri della sintassi: lat={0}, lon={1}, timestamp={2}, hdop={3}, altitude={4}, speed={5}, bearing={6}.</string>
<string name="monitoring_notification">Notifiche</string>
<string name="monitoring_min_speed">Velocità minima</string>
<string name="monitoring_min_accuracy">Accuratezza minima</string>
<string name="monitoring_min_distance">Minimo spostamento</string>
<string name="tracks_view_path">Menu — I miei luoghi — Tracce</string>
<string name="multimedia_notes_view_path">Menu — I miei luoghi — Note</string>
<string name="osm_edits_view_path">Menu — I miei luoghi — Modifiche OSM</string>
<string name="reset_plugin_to_default">Reimposta le impostazioni dei componenti aggiuntivi a quelle preimpostate</string>
<string name="multimedia_rec_split_title">Divisione delle registrazioni</string>
<string name="multimedia_use_system_camera">Usa l\'app di sistema</string>
<string name="multimedia_photo_play_sound">Sono otturatore fotocamera</string>
<string name="osm_authorization_success">L\'autorizzazione è andata a buon fine</string>
<string name="reset_to_default_category_button_promo">Il ripristino dei valori preimpostati ripristinerà all\'ordine preimpostato dopo l\'installazione l\'ordine di visualizzazione.</string>
<string name="accessibility_mode_disabled">La modalità accessibile è disabilitato nel tuo sistema.</string>
<string name="use_system_screen_timeout">Utilizza il salvaschermo di sistema</string>
<string name="use_system_screen_timeout_promo">Disabilitato per preimpostazione, se OsmAnd è eseguito in background, lo schermo non andrà in sospensione.
\n
\nSe abilitato OsmAnd userà le impostazioni di sospensione del sistema.</string>
<string name="clear_recorded_data">Elimina i dati registrati</string>
<string name="release_3_6">"• Profili: ora puoi cambiare l\'ordine, impostare l\'icona per le mappe, cambiare tutte le impostazioni dei profili di base e reimpostarle a quelle preimpostate
\n
\n • Aggiunto nella navigazione il numero delle uscite
\n
\n • Riorganizzate le impostazioni dei componenti aggiuntivi
\n
\n • Riorganizzate la finestra delle Impostazioni per un veloce accesso a tutti i profili
\n
\n • Aggiunta l\'opzione per copiare le impostazioni da un profilo a un altro
\n
\n • Aggiunta la possibilità di cambiare nella Ricerca l\'ordine delle categorie di PDI o di nasconderle
\n
\n • Corretto l\'allineamento dei icone dei PDI nella mappa
\n
\n • Aggiunti i dati alba/tramonto in Configura la mappa
\n
\n • Aggiunte alla mappa le icone Casa/Lavoro
\n
\n • Aggiunto il supporto per le descrizioni su più linee in Impostazioni
\n
\n • Aggiunto la traslitterazione corretta nella mappa del Giappone
\n
\n • Aggiunto la mappa dell\'Antartide
\n
\n"</string>
<string name="copy_coordinates">Copia le coordinate</string>
<string name="sort_by_category">Ordina per categoria</string>
</resources>

View file

@ -2233,7 +2233,7 @@
<string name="poi_horse_no">Kone nepovolené</string>
<string name="poi_animal_yes">Zvieratá povolené</string>
<string name="poi_animal_no">Zvieratá nepovolené</string>
<string name="poi_tomb_war_grave">Typ: vojenský cintorín</string>
<string name="poi_tomb_war_grave">Typ: vojnový hrob</string>
<string name="poi_tomb_tumulus">Typ: mohyla</string>
<string name="poi_tomb_rock_cut">Typ: skalná jaskyňa</string>
<string name="poi_tomb_hypogeum">Typ: hypogeum</string>

View file

@ -2,7 +2,7 @@
<resources>
<string name="close_changeset">Değişiklik listesini kapat</string>
<string name="zxing_barcode_scanner_not_found">ZXing Barcode Scanner uygulaması yüklü değil. Google Play\'de ara\?</string>
<string name="rendering_attr_roadColors_description">Yol renk şemasını seç:</string>
<string name="rendering_attr_roadColors_description">Bir yol rengi şeması seçin:</string>
<string name="rendering_attr_roadColors_name">Yol renk şeması</string>
<string name="map_widget_show_destination_arrow">Hedef yönü göster</string>
<string name="enable_plugin_monitoring_services">Konum günlüğü hizmetlerini kullanmak için \"Yolculuk kaydı\" eklentisini etkinleştirin (GPX günlüğü, çevrim içi izleme)</string>
@ -165,7 +165,7 @@
\n - Eksiksiz çevrim dışı işlevsellik (indirilen vektör veya döşeme haritalarını cihazda saklayın)
\n - Tüm dünya için kompakt çevrim dışı vektör haritaları mevcuttur
\n - Doğrudan uygulamadan ülke veya bölge haritalarını indirin
\n - GPX veya navigasyon rotaları, ilgi noktaları (points of interest), Sık Kullanılanlar, eş yükselti eğrileri, toplu taşıma durakları, özelleştirilebilir şeffaflığa sahip ek haritalar gibi birkaç harita katmanının üst üste konması
\n - GPX veya navigasyon rotaları, ilgi çekici noktalar (points of interest), Sık Kullanılanlar, eş yükselti eğrileri, toplu taşıma durakları, özelleştirilebilir şeffaflığa sahip ek haritalar gibi birkaç harita katmanının üst üste konması
\n - Adresleri ve yerleri çevrim dışı arama (POI\'ler)
\n - Orta menzilli mesafeler için çevrim dışı yönlendirme
\n - İsteğe bağlı olarak araba, bisiklet ve yaya modları:
@ -191,7 +191,7 @@
\n - Tüm dünya için kompakt çevrim dışı vektör haritaları mevcuttur
\n - Doğrudan uygulamadan sınırsız olarak ülke veya bölge haritalarını indirin
\n - Çevrim dışı Wikipedia özelliği (Wikipedia POI\'lerini indir), gezip görmek için harikadır
\n - GPX veya navigasyon rotaları, ilgi noktaları (points of interest), Sık Kullanılanlar, eş yükselti eğrileri, toplu taşıma durakları, özelleştirilebilir şeffaflığa sahip ek haritalar gibi birkaç harita katmanının üst üste konması
\n - GPX veya navigasyon rotaları, ilgi çekici noktalar (points of interest), Sık Kullanılanlar, eş yükselti eğrileri, toplu taşıma durakları, özelleştirilebilir şeffaflığa sahip ek haritalar gibi birkaç harita katmanının üst üste konması
\n
\n - Adresleri ve yerleri çevrim dışı arama (POI\'ler)
\n - Orta menzilli mesafeler için çevrim dışı yönlendirme
@ -203,7 +203,7 @@
\n</string>
<string name="day_night_info_description">Gün doğumu:%1$s
\nGün batımı:%2$s</string>
<string name="map_widget_vector_attributes">Öznitelikleri oluşturma</string>
<string name="map_widget_vector_attributes">Görselleştirme özellikleri</string>
<string name="map_widget_renderer">Harita tarzı</string>
<string name="layer_map_appearance">Ekran yapılandırma</string>
<string name="show_lanes">Şeritler</string>
@ -441,14 +441,14 @@
<string name="route_roundabout">Döner kavşak: %1$d çıkışa girin ve devam edin</string>
<string name="rendering_attr_noPolygons_description">Tüm arazi alan özelliklerini harita üzerinde şeffaf hale getirin.</string>
<string name="rendering_attr_noPolygons_name">Çokgenler</string>
<string name="rendering_attr_appMode_name">işleme modu</string>
<string name="rendering_attr_appMode_name">Görselleştirme modu</string>
<string name="rendering_attr_appMode_description">Için haritayı optimize et</string>
<string name="rendering_attr_contourLines_description">Yakınlaştırma seviyesinden görünüm (eş yükselti eğrisi verisi gerektirir):</string>
<string name="rendering_attr_contourLines_name">Eş yükselti eğrilerini göster</string>
<string name="rendering_attr_hmRendered_description">Haritanın gösterilen detay miktarını artırın.</string>
<string name="local_index_routing_data">Rota edilen veri</string>
<string name="navigate_point_format">Biçim</string>
<string name="poi_search_desc">İÇN (İhtiyaç Noktası) arama</string>
<string name="poi_search_desc">POI (Point of interest - İlgi çekici nokta) arama</string>
<string name="navpoint_search_desc">Koordinatlar</string>
<string name="transport_search_desc">Toplu taşıma için ara</string>
<string name="offline_navigation_not_available">OsmAnd çevrim dışı yolbul geçici olarak kullanılamıyor.</string>
@ -477,7 +477,7 @@
<string name="vector_maps_may_display_faster_on_some_devices">Vektörel haritalar daha hızlı görüntülenir. Bazı aygıtlarda düzgün çalışmayabilir.</string>
<string name="play_commands_of_currently_selected_voice">Bir ses seçin ve duyuruları oynayarak test edin:</string>
<string name="debugging_and_development">OsmAnd gelişimi</string>
<string name="native_rendering">Yerel render etme</string>
<string name="native_rendering">Yerel görselleştirme</string>
<string name="test_voice_prompts">Sesli uyarıları test et</string>
<string name="switch_to_raster_map_to_see">Bu konum için \'Ayarlar\' (\'Harita dosyalarını yönet\') kısmından çevrim dışı bir vektör haritası indirin veya \'Çevrim içi haritalar\' eklentisine geçin.</string>
<string name="send_files_to_osm">GPX dosyalarını OSM ye gönder?</string>
@ -586,7 +586,7 @@
<string name="auto_follow_route_navigation">Otomatik-sadece merkezi nav</string>
<string name="auto_follow_route_navigation_descr">Otomatik-navigasyon yaparken sadece merkezi harita görünümü.</string>
<string name="auto_follow_location_enabled">Haritayı kullanırken görünümü otomatik olarak ortala.</string>
<string name="pref_vector_rendering">Özel seçenekli vektör renderer etme</string>
<string name="pref_vector_rendering">Vektör görselleştiriciye özgü seçenekler</string>
<string name="pref_overlay">Üst katman / alt katman</string>
<string name="pref_raster_map">Harita kaynağı ayarları</string>
<string name="pref_vector_map">Vektör harita ayarları</string>
@ -649,8 +649,8 @@
<string name="local_indexes_cat_voice">Sesli uyarılar (kaydedilmiş)</string>
<string name="local_indexes_cat_poi">POI Verisi</string>
<string name="ttsvoice">TTS sesi</string>
<string name="trace_rendering">Hata ayıklama bilgisi dönüştürülüyor</string>
<string name="trace_rendering_descr">Rendering performansını görüntüleyin.</string>
<string name="trace_rendering">Görselleştirme hata ayıklama bilgisi</string>
<string name="trace_rendering_descr">Görselleştirme performansını görüntüleyin.</string>
<string name="installing_new_resources">Yeni veri(ler) açılıyor…</string>
<string name="internet_connection_required_for_online_route">Çevrim içi navigasyon çevrim dışı çalışmamaktadır.</string>
<string name="layer_hillshade">Tepe gölgesi katmanı</string>
@ -808,21 +808,21 @@
<string name="items_were_selected">{0} öğe seçildi</string>
<string name="filter_existing_indexes">İndirilen</string>
<string name="fast_route_mode_descr">En hızlı rotayı hesaplamayı etkinleştirin veya yakıt tasarrufu rotası için devre dışı bırakın.</string>
<string name="continuous_rendering">Devamlı işleme</string>
<string name="continuous_rendering">Sürekli görselleştirme</string>
<string name="rendering_exception">Seçilen alan çizilemedi.</string>
<string name="show_point_options">Konumu kullan…</string>
<string name="renderer_load_sucess">Oluşturucu yüklendi</string>
<string name="renderer_load_exception">Oluşturucu yüklenemedi.</string>
<string name="poi_context_menu_website">İÇN websitesini göster</string>
<string name="poi_context_menu_call">İÇN telefonunu göster</string>
<string name="download_type_to_filter">süzmek için yazın</string>
<string name="renderer_load_sucess">Görselleştirici yüklendi</string>
<string name="renderer_load_exception">Görselleştirici yüklenemedi.</string>
<string name="poi_context_menu_website">POI web sitesini göster</string>
<string name="poi_context_menu_call">POI telefonunu göster</string>
<string name="download_type_to_filter">filtrelemek için yazın</string>
<string name="context_menu_item_search_transport">Toplu taşıma ara</string>
<string name="transport_searching_transport">Ulaştırma sonuçları (hedef yok):</string>
<string name="transport_searching_route">Ulaşım sonuçları (hedefe {0}):</string>
<string name="transport_search_again">Taşıma aramasını sıfırla</string>
<string name="gpx_files_not_found">Tracks klasöründe GPX dosyası bulunamadı</string>
<string name="error_reading_gpx">GPX verileri okunamadı.</string>
<string name="poi_context_menu_modify">İÇN düzenle</string>
<string name="poi_context_menu_modify">POI düzenle</string>
<string name="rotate_map_compass_opt">Pusula yönü</string>
<string name="rotate_map_bearing_opt">Hareket yönü</string>
<string name="rotate_map_none_opt">Dönme yok (kuzey her zaman yukarı doğru)</string>
@ -870,10 +870,10 @@
<string name="show_transport_over_map_description">Toplu taşıma duraklarını haritada göster.</string>
<string name="show_transport_over_map">Taşıma duraklarını göster</string>
<string name="hello">OsmAnd yolbul uygulaması</string>
<string name="update_poi_success">İÇN verisi güncellendi ({0} yüklendi)</string>
<string name="update_poi_success">POI güncellendi ({0} yüklendi)</string>
<string name="update_poi_error_local">Yerel POI listesi güncellenemedi.</string>
<string name="update_poi_error_loading">Sunucudan veri yüklenemedi.</string>
<string name="update_poi_no_offline_poi_index">Bu alan için çevrim dışı İÇN verisi mevcut değil</string>
<string name="update_poi_no_offline_poi_index">Bu alan için çevrim dışı POI verisi mevcut değil</string>
<string name="search_history_city">Şehir: {0}</string>
<string name="search_history_street">Sokak: {0}, {1}</string>
<string name="search_history_building">Bina: {0}, {1}, {2}</string>
@ -984,7 +984,7 @@
<string name="amenity_type_seamark">Mark Deniz</string>
<string name="app_modes_choose_descr">Gösterilen profilleri seç.</string>
<string name="app_modes_choose">Uygulama profilleri</string>
<string name="map_widget_map_rendering">Harita oluşturma</string>
<string name="map_widget_map_rendering">Harita görselleştirme</string>
<string name="app_mode_hiking">Yürüyüş</string>
<string name="app_mode_motorcycle">Motosikletler</string>
<string name="app_mode_boat">Tekne</string>
@ -1454,8 +1454,8 @@
<string name="transport_to_go_after">Önceki mesafe</string>
<string name="transport_to_go_before">Sonraki mesafe</string>
<string name="transport_stops_to_pass">geçmek için durur</string>
<string name="update_poi_is_not_available_for_zoom">Yakınlaştırma, İÇN\'leri güncellemenizi sağlar</string>
<string name="context_menu_item_update_poi">Güncelleme POI</string>
<string name="update_poi_is_not_available_for_zoom">Yakınlaştırma, POI\'leri güncellemenizi sağlar</string>
<string name="context_menu_item_update_poi">POI güncelle</string>
<string name="fav_imported_sucessfully">Sık Kullanılanlar içe aktarıldı</string>
<string name="import_file_favourites">Verileri GPX dosyası olarak kaydedin ya da ara noktaları \'Sık Kullanılanlar\'a aktarın\?</string>
<string name="fav_file_to_load_not_found">{0} konumunda Sık Kullanılanlar içeren GPX dosyası bulunamadı</string>
@ -1479,9 +1479,9 @@
<string name="install_selected_build">OsmAnd Yükle - {1} {2} üzerinden {0} MB \?</string>
<string name="tiles_to_download_estimated_size">Yakınlaştırma {0} indirmek {1} fayans ({2} MB)</string>
<string name="select_max_zoom_preload_area">Önceden yükleme için maksimum zoom</string>
<string name="continuous_rendering_descr">Bir kerede görüntü yerine sürekli görüntü oluşturmayı göster.</string>
<string name="renderers">vektör render</string>
<string name="renderers_descr">Oluşturma görünümünü seçin</string>
<string name="continuous_rendering_descr">Tek seferde görüntü yerine sürekli görselleştirmeyi görüntüleyin.</string>
<string name="renderers">Vektör görselleştirici</string>
<string name="renderers_descr">Görselleştirme görünümünü seçin</string>
<string name="use_high_res_maps_descr">Yüksek yoğunluklu ekranlarda (döşeme) haritaları uzatma (ve bulanıklaştırma).</string>
<string name="indexing_address">Dizin Oluşturma adresi …</string>
<string name="indexing_map">Dizin Oluşturma haritası</string>
@ -1525,9 +1525,9 @@
<string name="arrival_distance">Varış bildirisi</string>
<string name="arrival_distance_descr">Varış bildirimini ne yakınlıkta istiyorsun?</string>
<string name="rendering_attr_alpineHiking_name">Alp yürüyüş ölçeği (SAC)</string>
<string name="rendering_attr_alpineHiking_description">SAC ölçeğine göre yolları oluşturun.</string>
<string name="rendering_attr_alpineHiking_description">SAC ölçeğine göre yolları görselleştir.</string>
<string name="rendering_attr_hikingRoutesOSMC_name">Yürüyüş sembolü üst katmanı</string>
<string name="rendering_attr_hikingRoutesOSMC_description">OSMC izlerine göre yolları oluşturun.</string>
<string name="rendering_attr_hikingRoutesOSMC_description">OSMC izlerine göre yolları görselleştir.</string>
<string name="monitoring_control_start">GPX</string>
<string name="interrupt_music_descr">Sesli uyarılar müzik çalmayı duraklatır.</string>
<string name="interrupt_music">Müziği duraklat</string>
@ -1727,8 +1727,8 @@
<string name="navigate_point_northing">Kuzeye doğru katedilen mesafe</string>
<string name="navigate_point_easting">doğuya doğru yönelme</string>
<string name="no_internet_connection">İndirilemedi, lütfen İnternet bağlantınızı kontrol edin.</string>
<string name="use_opengl_render">Kullanım OpenGL render</string>
<string name="use_opengl_render_descr">Donanım hızlandırmalı OpenGL renderleme kullanın (daha fazla pil kullanabilir, ya da çok eski cihazlarda çalışmayabilir).</string>
<string name="use_opengl_render">OpenGL görselleştirmeyi kullan</string>
<string name="use_opengl_render_descr">Donanım hızlandırmalı OpenGL görselleştirme kullan (daha fazla pil kullanabilir, ya da çok eski cihazlarda çalışmayabilir).</string>
<string name="error_avoid_specific_road">Bypass bulunamadı</string>
<string name="search_for">Arama</string>
<string name="rendering_attr_publicTransportMode_name">Otobüs, troleybüs, mekik yolları</string>
@ -1885,7 +1885,7 @@
<string name="active_markers">Etkin işaretleyiciler</string>
<string name="map_markers">Harita işaretleyicileri</string>
<string name="map_marker">Harita işaretleyici</string>
<string name="consider_turning_polygons_off">Poligon görüntülemeyi kapatmanız önerilir.</string>
<string name="consider_turning_polygons_off">Poligon görselleştirmeyi kapatmanız önerilir.</string>
<string name="donations">Bağışlar</string>
<string name="number_of_recipients">Alıcıların sayısı</string>
<string name="osm_user_stat">%1$s , rütbe %2$s , toplam düzenlemeleri %3$s düzenler</string>
@ -1980,7 +1980,7 @@
<string name="add_new_folder">Yeni klasör ekle</string>
<string name="points_delete_multiple_succesful">Nokta(lar) silindi.</string>
<string name="shared_string_gpx_track">Takip et</string>
<string name="track_points_category_name">Waypointler, ilgi noktaları, adlandırılmış özellikler</string>
<string name="track_points_category_name">Waypointler, ilgi çekici noktalar, adlandırılmış özellikler</string>
<string name="max_speed">Azami hız</string>
<string name="average_speed">Ortalama hız</string>
<string name="shared_string_max">Azami</string>
@ -2773,7 +2773,7 @@
\nTemsil ettiği alan: %1$s x %2$s</string>
<string name="auto_split_recording_title">Boşluktan sonra kayıtları otomatik bölme</string>
<string name="auto_split_recording_descr">6 dakikalık aralıktan sonra yeni segmenti, 2 saatlik aralıktan sonra yeni izlenen yolu veya tarih değiştiyse daha uzun aralıktan sonra yeni dosyayı başlatın.</string>
<string name="rendering_attr_depthContours_description">Derinlik çizgilerini ve noktalarını göster.</string>
<string name="rendering_attr_depthContours_description">Eş derinlik eğrilerini ve noktalarını göster.</string>
<string name="route_points_category_name">Bu rotadan geçmek için döner</string>
<string name="lang_ber">Berberice</string>
<string name="do_not_show_startup_messages_desc">Uygulama indirimlerini ve özel yerel etkinlik mesajlarını gösterme.</string>
@ -2880,12 +2880,12 @@
<string name="read_wikipedia_offline_description">Wikipedia ve Wikivoyage makalelerini çevrim dışı olarak okumak için OsmAnd Live üyeliği alın.</string>
<string name="how_to_open_link">Link nasıl açılır\?</string>
<string name="read_wikipedia_offline">Wikipedia\'yı çevrim dışı olarak oku</string>
<string name="nautical_render_descr">Deniz navigasyonu için. Şamandıralar, deniz fenerleri, nehir yolları, deniz şeritleri ve işaretleri, limanlar, deniz kenarı hizmetleri ve eş derinlik çizgileri içermektedir.</string>
<string name="nautical_render_descr">Deniz navigasyonu için. Şamandıralar, deniz fenerleri, nehir yolları, deniz şeritleri ve işaretleri, limanlar, deniz kenarı hizmetleri ve eş derinlik eğrilerini içermektedir.</string>
<string name="ski_map_render_descr">Kayak yapmak için. Pistler, telesiyejler, kros kayak yolları vb. içermektedir. İkincil harita nesnelerini karartır.</string>
<string name="light_rs_render_descr">Basit sürüş tarzı. Yumuşak gece modu, eş yükselti eğrileri, turuncu tarzdaki zıtlaştırılmış yollar, ikincil harita nesnelerini karartma.</string>
<string name="topo_render_descr">Yürüyüş, doğa yürüyüşü ve doğa bisikleti için. Dış mekanda okunabilir. Zıtlaştırılmış yollar ve doğal nesneler, farklı rota tipleri, gelişmiş eş yükselti eğrisi seçenekleri, ekstra detaylar. Yüzey bütünlüğünün ayarlanması yol kalitesini ayırt eder. Gece modu yok.</string>
<string name="mapnik_render_descr">Eski varsayılan \'Mapnik\' tarzı. \'Mapnik\' ile benzer renkler.</string>
<string name="default_render_descr">Genel amaçlı stil. Yoğun şehirler temiz bir şekilde gösterilmiştir. Eş yükselti eğrileri, rotalar, yüzey kalitesi, erişim kısıtlamaları, yol kalkanları, SAC ölçeğine göre yol görüntüleme, akarsu sporları öğeleri içermektedir.</string>
<string name="default_render_descr">Genel amaçlı stil. Yoğun şehirler temiz bir şekilde gösterilmiştir. Eş yükselti eğrileri, rotalar, yüzey kalitesi, erişim kısıtlamaları, yol kalkanları, SAC ölçeğine göre yol görselleştirme, akarsu sporları öğeleri içermektedir.</string>
<string name="touring_view_render_descr">Yüksek zıtlık ve maksimum ayrıntı ile turne tarzı. OsmAnd varsayılan stilinin tüm seçenekleri ile birlikte, mümkün olduğu kadar çok ayrıntıyı, özellikle de yolları, patikaları ve seyahat etmenin diğer yollarını gösterir. Yol tipleri arasındaki \"touring atlas\" ayrımını temizleyin. Gündüz, gece ve dış mekan kullanımı için uygundur.</string>
<string name="off_road_render_descr">\'Topo\' stiline dayalı arazi sürüşleri ve yeşil uydu görüntüleriyle alt tabaka olarak kullanım için. Ana yol kalınlığı azaltılmış, izlenen yollar, patikalar, bisiklet ve diğer rotaların kalınlığı arttırılmıştır.</string>
<string name="unirs_render_descr">Yaya ve bisiklet yollarının kontrastını artırmak için varsayılan stilin değiştirilmesi. Eski Mapnik renklerini kullanır.</string>
@ -2922,7 +2922,7 @@
<string name="transfers">Transferler</string>
<string name="on_foot">Yürüyerek</string>
<string name="route_way">Yol</string>
<string name="points_of_interests">İlgi noktaları (POI)</string>
<string name="points_of_interests">İlgi çekici noktalar (Points of interest - POI)</string>
<string name="avoid_roads_descr">Haritada veya aşağıdaki listeden navigasyon sırasında kaçınmak istediğiniz bir yol seçin:</string>
<string name="choose_track_file_to_follow">İzlenecek yol dosyasını seçin</string>
<string name="arrive_at_time">%1$s\'de ulaş</string>
@ -3108,7 +3108,7 @@
\n • Konumunuzu ve yönünüzü gösterin
\n • İsteğe bağlı olarak resmi pusulaya veya hareket yönünüze göre hizalayın
\n • En önemli yerlerinizi Sık Kullanılanlar olarak kaydedin
\n • Çevrenizdeki POI\'leri (ilgi noktaları) görüntüleyin
\n • Çevrenizdeki POI\'leri (points of interest - ilgi çekici noktaları) görüntüleyin
\n • Özel çevrim içi döşemeleri, uydu görüntüsünü (Bing\'den), tur/gezinme GPX parkurları gibi farklı üst katmanları ve ayarlanabilir şeffaflığı olan ek katmanları görüntüleyin
\n • İsteğe bağlı olarak yer adlarını İngilizce, yerel veya fonetik yazım biçiminde görüntüleyin
\n</string>
@ -3223,7 +3223,7 @@
<string name="routing_attr_allow_classic_only_name">Sadece-klasik rotalarına izin ver</string>
<string name="routing_attr_allow_classic_only_description">Paten yolları olmadan sadece klasik stil için düzenlenmiş rotalar. Buna daha gevşek bir palete sahip daha küçük bir kar arabasıyla düzenlenen rotalar ve kayakçılar tarafından manuel olarak yapılan pistler dahildir.</string>
<string name="routing_attr_difficulty_preference_name">Tercih edilen zorluk</string>
<string name="routing_attr_difficulty_preference_description">Daha zor ya da daha kolay pistler üzerinde yönlendirme daha kısa ise hala mümkün olmasına rağmen, bu zorluktaki yolları tercih edin.</string>
<string name="routing_attr_difficulty_preference_description">Bu zorluktaki rotaları tercih et, ancak eğer daha kısa ise daha zor veya daha kolay pistler üzerinden yönlendirmek yine de mümkündür.</string>
<string name="routing_attr_freeride_policy_name">Pist dışı</string>
<string name="routing_attr_freeride_policy_description">\'Serbest\' ve \'pist dışı sürüşler\', resmi olmayan yollar ve geçitlerdir. Tipik olarak düzenlenmemiş, bakımı yapılmamış ve akşamları kontrol edilmemiştir. Riski göze alarak girin.</string>
<string name="external_input_device">Harici giriş cihazları</string>
@ -3480,4 +3480,5 @@
\n</string>
<string name="copy_coordinates">Koordinatları kopyala</string>
<string name="routing_profile_direct_to">Doğrudan noktaya</string>
<string name="sort_by_category">Kategoriye göre sırala</string>
</resources>

View file

@ -3515,4 +3515,5 @@
\n</string>
<string name="copy_coordinates">Скопіювати координати</string>
<string name="routing_profile_direct_to">Пряма точка</string>
<string name="sort_by_category">Впорядкувати за категоріями</string>
</resources>

View file

@ -1302,7 +1302,7 @@
<string name="routing_attr_avoid_stairs_description">避免阶梯</string>
<string name="routing_attr_avoid_borders_name">避开边界穿越</string>
<string name="routing_attr_avoid_borders_description">避免穿越边境线进入其它国家</string>
<string name="routing_attr_weight_description">指定路线上允许的车辆重量</string>
<string name="routing_attr_weight_description">指定路线上允许的车辆重量</string>
<string name="routing_attr_height_name">高度限制</string>
<string name="routing_attr_height_description">指定路线上允许的车辆高度。</string>
<string name="android_19_location_disabled">Android 4.4 版KitKat之后您无法使用先前的存储文件夹%s下载或更新地图。您是否想要修改为允许的存储位置并将所有 OsmAnd 文件复制到新位置?
@ -2810,4 +2810,12 @@
<string name="reset_all_profile_settings">要将所有配置设置重置为默认值吗?</string>
<string name="permission_is_required">使用此选项需要授权。</string>
<string name="shared_string_available">可用</string>
<string name="routing_attr_width_name">宽度限制</string>
<string name="routing_attr_width_description">指定路线上允许的车辆宽度。</string>
<string name="import_from_file">从文件导入</string>
<string name="multimedia_notes_prefs_descr">照片尺寸、音频和视频质量</string>
<string name="login_and_pass">用户名和密码</string>
<string name="multimedia_use_system_camera">使用系统应用程序</string>
<string name="multimedia_photo_play_sound">相机快门声音</string>
<string name="osm_authorization_success">授权成功</string>
</resources>

View file

@ -3515,4 +3515,5 @@
\n</string>
<string name="copy_coordinates">複製座標</string>
<string name="routing_profile_direct_to">點對點</string>
<string name="sort_by_category">按分類排序</string>
</resources>

View file

@ -11,6 +11,7 @@
Thx - Hardy
-->
<string name="please_provide_profile_name_message">Please provide a name for the profile</string>
<string name="open_settings">Open settings</string>
<string name="plugin_disabled">Plugin disabled</string>
<string name="plugin_disabled_descr">This plugin is a separate application, you will need to remove it separately if you no longer plan to use it.\n\nThe plugin will remain on the device after removing OsmAnd.</string>
@ -48,6 +49,11 @@
<string name="ltr_or_rtl_combine_via_slash">%1$s/%2$s</string>
<string name="sunset_at">Sunset at %1$s</string>
<string name="sunrise_at">Sunrise at %1$s</string>
<string name="shared_string_routing">Routing</string>
<string name="shared_string_custom_rendering_style">Custom rendering style</string>
<string name="shared_string_include_data">Include additional data</string>
<string name="import_profile_dialog_description">The imported profile contains additional data. Click Import to import only profile data or select additional data to import.</string>
<string name="export_profile_dialog_description">You can select additional data to export along with the profile.</string>
<string name="permission_is_required">Permission is required to use this option.</string>
<string name="logcat_buffer_descr">Check and share detailed logs of the application</string>
<string name="file_does_not_contain_routing_rules">No routing rules in \'%1$s\'. Please choose another file.</string>

View file

@ -1,5 +1,6 @@
package net.osmand.plus;
import android.database.SQLException;
import android.database.sqlite.SQLiteDiskIOException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@ -22,22 +23,34 @@ import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
import static net.osmand.IndexConstants.SQLITE_EXT;
import static net.osmand.IndexConstants.TILES_INDEX_DIR;
public class SQLiteTileSource implements ITileSource {
public static final String EXT = IndexConstants.SQLITE_EXT;
private static final Log LOG = PlatformUtil.getLog(SQLiteTileSource.class);
private static final String MAXZOOM_FIELD = "maxzoom";
private static final String MINZOOM_FIELD = "minzoom";
private static final String ELLIPSOID_FIELD = "ellipsoid";
private static final String URL_FIELD = "url";
private static final String EXPIREMINUTES_FIELD = "expireminutes";
private static final String MIN_ZOOM = "minzoom";
private static final String MAX_ZOOM = "maxzoom";
private static final String URL = "url";
private static final String RANDOMS = "randoms";
private static final String ELLIPSOID = "ellipsoid";
private static final String INVERTED_Y = "inverted_y";
private static final String REFERER = "referer";
private static final String TIME_COLUMN = "timecolumn";
private static final String EXPIRE_MINUTES = "expireminutes";
private static final String RULE = "rule";
private static final String TILENUMBERING = "tilenumbering";
private static final String BIG_PLANET_TILE_NUMBERING = "BigPlanet";
private static final String TILESIZE = "tilesize";
private ITileSource base;
private String urlTemplate = null;
private String name;
private SQLiteConnection db = null;
private final File file;
private File file = null;
private int minZoom = 1;
private int maxZoom = 17;
private boolean inversiveZoom = true; // BigPlanet
@ -76,6 +89,45 @@ public class SQLiteTileSource implements ITileSource {
}
}
public SQLiteTileSource(OsmandApplication ctx, String name, int minZoom, int maxZoom, String urlTemplate,
String randoms, boolean isEllipsoid, boolean invertedY, String referer,
boolean timeSupported, long expirationTimeMillis, boolean inversiveZoom) {
this.ctx = ctx;
this.name = name;
this.urlTemplate = urlTemplate;
this.maxZoom = maxZoom;
this.minZoom = minZoom;
this.isEllipsoid = isEllipsoid;
this.expirationTimeMillis = expirationTimeMillis;
this.randoms = randoms;
this.referer = referer;
this.invertedY = invertedY;
this.timeSupported = timeSupported;
this.inversiveZoom = inversiveZoom;
}
public void createDataBase() {
db = ctx.getSQLiteAPI().getOrCreateDatabase(
ctx.getAppPath(TILES_INDEX_DIR).getAbsolutePath() + "/" + name + SQLITE_EXT, true);
db.execSQL("CREATE TABLE tiles (x int, y int, z int, s int, image blob, time long, PRIMARY KEY (x,y,z,s))");
db.execSQL("CREATE INDEX IND on tiles (x,y,z,s)");
db.execSQL("CREATE TABLE info(tilenumbering,minzoom,maxzoom)");
db.execSQL("CREATE TABLE android_metadata (locale TEXT)");
db.execSQL("INSERT INTO info (tilenumbering,minzoom,maxzoom) VALUES ('simple','" + minZoom + "','" + maxZoom + "');");
addInfoColumn(URL, urlTemplate);
addInfoColumn(RANDOMS, randoms);
addInfoColumn(ELLIPSOID, isEllipsoid ? "1" : "0");
addInfoColumn(INVERTED_Y, invertedY ? "1" : "0");
addInfoColumn(REFERER, referer);
addInfoColumn(TIME_COLUMN, timeSupported ? "yes" : "no");
addInfoColumn(EXPIRE_MINUTES, String.valueOf(getExpirationTimeMinutes()));
db.close();
}
@Override
public int getBitDensity() {
@ -121,6 +173,20 @@ public class SQLiteTileSource implements ITileSource {
return TileSourceTemplate.buildUrlToLoad(urlTemplate, randomsArray, x, y, zoom);
}
@Override
public String getUrlTemplate() {
if (this.urlTemplate != null) {
return this.urlTemplate;
} else {
SQLiteConnection db = getDatabase();
if (db == null || urlTemplate == null) {
return null;
} else {
return this.urlTemplate;
}
}
}
@Override
public int hashCode() {
final int prime = 31;
@ -167,36 +233,36 @@ public class SQLiteTileSource implements ITileSource {
if(cursor.moveToFirst()) {
String[] columnNames = cursor.getColumnNames();
List<String> list = Arrays.asList(columnNames);
int url = list.indexOf(URL_FIELD);
int url = list.indexOf(URL);
if(url != -1) {
String template = cursor.getString(url);
if(!Algorithms.isEmpty(template)){
urlTemplate = TileSourceTemplate.normalizeUrl(template);
}
}
int ruleId = list.indexOf("rule");
int ruleId = list.indexOf(RULE);
if(ruleId != -1) {
rule = cursor.getString(ruleId);
}
int refererId = list.indexOf("referer");
int refererId = list.indexOf(REFERER);
if(refererId != -1) {
referer = cursor.getString(refererId);
}
int tnumbering = list.indexOf("tilenumbering");
int tnumbering = list.indexOf(TILENUMBERING);
if(tnumbering != -1) {
inversiveZoom = "BigPlanet".equalsIgnoreCase(cursor.getString(tnumbering));
inversiveZoom = BIG_PLANET_TILE_NUMBERING.equalsIgnoreCase(cursor.getString(tnumbering));
} else {
inversiveZoom = true;
addInfoColumn("tilenumbering", "BigPlanet");
addInfoColumn(TILENUMBERING, BIG_PLANET_TILE_NUMBERING);
}
int timecolumn = list.indexOf("timecolumn");
int timecolumn = list.indexOf(TIME_COLUMN);
if (timecolumn != -1) {
timeSupported = "yes".equalsIgnoreCase(cursor.getString(timecolumn));
} else {
timeSupported = hasTimeColumn();
addInfoColumn("timecolumn", timeSupported? "yes" : "no");
addInfoColumn(TIME_COLUMN, timeSupported? "yes" : "no");
}
int expireminutes = list.indexOf(EXPIREMINUTES_FIELD);
int expireminutes = list.indexOf(EXPIRE_MINUTES);
this.expirationTimeMillis = -1;
if(expireminutes != -1) {
int minutes = (int) cursor.getInt(expireminutes);
@ -204,39 +270,39 @@ public class SQLiteTileSource implements ITileSource {
this.expirationTimeMillis = minutes * 60 * 1000l;
}
} else {
addInfoColumn(EXPIREMINUTES_FIELD, "0");
addInfoColumn(EXPIRE_MINUTES, "0");
}
int tsColumn = list.indexOf("tilesize");
int tsColumn = list.indexOf(TILESIZE);
this.tileSizeSpecified = tsColumn != -1;
if(tileSizeSpecified) {
this.tileSize = (int) cursor.getInt(tsColumn);
}
int ellipsoid = list.indexOf(ELLIPSOID_FIELD);
int ellipsoid = list.indexOf(ELLIPSOID);
if(ellipsoid != -1) {
int set = (int) cursor.getInt(ellipsoid);
if(set == 1){
this.isEllipsoid = true;
}
}
int invertedY = list.indexOf("inverted_y");
int invertedY = list.indexOf(INVERTED_Y);
if(invertedY != -1) {
int set = (int) cursor.getInt(invertedY);
if(set == 1){
this.invertedY = true;
}
}
int randomsId = list.indexOf("randoms");
int randomsId = list.indexOf(RANDOMS);
if(randomsId != -1) {
this.randoms = cursor.getString(randomsId);
this.randomsArray = TileSourceTemplate.buildRandomsArray(this.randoms);
}
//boolean inversiveInfoZoom = tnumbering != -1 && "BigPlanet".equals(cursor.getString(tnumbering));
boolean inversiveInfoZoom = inversiveZoom;
int mnz = list.indexOf(MINZOOM_FIELD);
int mnz = list.indexOf(MIN_ZOOM);
if(mnz != -1) {
minZoom = (int) cursor.getInt(mnz);
}
int mxz = list.indexOf(MAXZOOM_FIELD);
int mxz = list.indexOf(MAX_ZOOM);
if(mxz != -1) {
maxZoom = (int) cursor.getInt(mxz);
}
@ -264,27 +330,31 @@ public class SQLiteTileSource implements ITileSource {
maxZoom = 17 - mnz;
}
if (getUrlTemplate() != null && !getUrlTemplate().equals(r.getUrlTemplate())) {
db.execSQL("update info set " + URL_FIELD + " = '" + r.getUrlTemplate() + "'");
db.execSQL("update info set " + URL + " = '" + r.getUrlTemplate() + "'");
}
if (r.getMinimumZoomSupported() != minZoom) {
db.execSQL("update info set " + MINZOOM_FIELD + " = '" + minZoom + "'");
db.execSQL("update info set " + MIN_ZOOM + " = '" + minZoom + "'");
}
if (r.getMaximumZoomSupported() != maxZoom) {
db.execSQL("update info set " + MAXZOOM_FIELD + " = '" + maxZoom + "'");
db.execSQL("update info set " + MAX_ZOOM + " = '" + maxZoom + "'");
}
if (r.isEllipticYTile() != isEllipticYTile()) {
db.execSQL("update info set " + ELLIPSOID_FIELD + " = '" + (r.isEllipticYTile() ? 1 : 0) + "'");
db.execSQL("update info set " + ELLIPSOID + " = '" + (r.isEllipticYTile() ? 1 : 0) + "'");
}
if (r.getExpirationTimeMinutes() != getExpirationTimeMinutes()) {
db.execSQL("update info set " + EXPIREMINUTES_FIELD + " = '" + r.getExpirationTimeMinutes() + "'");
db.execSQL("update info set " + EXPIRE_MINUTES + " = '" + r.getExpirationTimeMinutes() + "'");
}
}
}
private void addInfoColumn(String columnName, String value) {
if (!onlyReadonlyAvailable) {
db.execSQL("alter table info add column " + columnName + " TEXT");
db.execSQL("update info set " + columnName + " = '" + value + "'");
if(!onlyReadonlyAvailable) {
try {
db.execSQL("alter table info add column " + columnName + " TEXT");
} catch (SQLException e) {
LOG.info("Error adding column " + e);
}
db.execSQL("update info set "+columnName+" = '"+value+"'");
}
}
@ -459,7 +529,37 @@ public class SQLiteTileSource implements ITileSource {
}
db.execSQL("DELETE FROM tiles");
}
@Override
public int getAvgSize() {
return base != null ? base.getAvgSize() : -1;
}
@Override
public String getRule() {
return rule;
}
@Override
public String getRandoms() {
return randoms;
}
@Override
public boolean isInvertedYTile() {
return invertedY;
}
@Override
public boolean isTimeSupported() {
return timeSupported;
}
@Override
public boolean getInversiveZoom() {
return inversiveZoom;
}
/**
* Makes method synchronized to give a little more time for get methods and
* let all writing attempts to wait outside of this method
@ -547,9 +647,4 @@ public class SQLiteTileSource implements ITileSource {
return referer;
}
public String getUrlTemplate() {
return urlTemplate;
}
}

View file

@ -9,10 +9,21 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import net.osmand.PlatformUtil;
import net.osmand.map.ITileSource;
import net.osmand.map.TileSourceManager;
import net.osmand.osm.MapPoiTypes;
import net.osmand.osm.PoiCategory;
import net.osmand.plus.ApplicationMode.ApplicationModeBean;
import net.osmand.plus.ApplicationMode.ApplicationModeBuilder;
import net.osmand.plus.OsmandSettings.OsmandPreference;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.quickaction.QuickAction;
import net.osmand.plus.quickaction.QuickActionFactory;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
@ -33,11 +44,14 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -46,6 +60,7 @@ import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import static net.osmand.IndexConstants.OSMAND_SETTINGS_FILE_EXT;
import static net.osmand.IndexConstants.TILES_INDEX_DIR;
/*
Usage:
@ -83,6 +98,7 @@ public class SettingsHelper {
private boolean importing;
private boolean importSuspended;
private boolean collectOnly;
private ImportAsyncTask importTask;
public interface SettingsImportListener {
@ -103,7 +119,7 @@ public class SettingsHelper {
public void setActivity(Activity activity) {
this.activity = activity;
if (importing) {
if (importing && !collectOnly) {
importTask.processNextItem();
}
}
@ -128,6 +144,9 @@ public class SettingsHelper {
PLUGIN,
DATA,
FILE,
QUICK_ACTION,
POI_UI_FILTERS,
MAP_SOURCES,
}
public abstract static class SettingsItem {
@ -157,6 +176,10 @@ public class SettingsHelper {
@NonNull
public abstract String getFileName();
public Boolean shouldReadOnCollecting() {
return false;
}
static SettingsItemType parseItemType(@NonNull JSONObject json) throws IllegalArgumentException, JSONException {
return SettingsItemType.valueOf(json.getString("type"));
}
@ -307,7 +330,6 @@ public class SettingsHelper {
}
}
});
}
}
@ -419,6 +441,10 @@ public class SettingsHelper {
appModeBeanPrefsIds = new HashSet<>(Arrays.asList(settings.appModeBeanPrefsIds));
}
public ApplicationMode getAppMode() {
return appMode;
}
@NonNull
@Override
public String getName() {
@ -472,7 +498,6 @@ public class SettingsHelper {
json.put("appMode", new JSONObject(appMode.toJson()));
}
@NonNull
@Override
SettingsItemReader getReader() {
@ -706,6 +731,443 @@ public class SettingsHelper {
}
}
public static class QuickActionSettingsItem extends OsmandSettingsItem {
private List<QuickAction> quickActions;
private OsmandApplication app;
public QuickActionSettingsItem(@NonNull OsmandApplication app,
@NonNull List<QuickAction> quickActions) {
super(SettingsItemType.QUICK_ACTION, app.getSettings());
this.app = app;
this.quickActions = quickActions;
}
public QuickActionSettingsItem(@NonNull OsmandApplication app,
@NonNull JSONObject jsonObject) throws JSONException {
super(SettingsItemType.QUICK_ACTION, app.getSettings(), jsonObject);
this.app = app;
}
public List<QuickAction> getQuickActions() {
return quickActions;
}
@Override
public void apply() {
if (!quickActions.isEmpty()) {
QuickActionFactory factory = new QuickActionFactory();
List<QuickAction> savedActions = factory.parseActiveActionsList(getSettings().QUICK_ACTION_LIST.get());
List<QuickAction> newActions = new ArrayList<>(savedActions);
for (QuickAction action : quickActions) {
for (QuickAction savedAction : savedActions) {
if (action.getName(app).equals(savedAction.getName(app))) {
newActions.remove(savedAction);
}
}
}
newActions.addAll(quickActions);
((MapActivity) app.getSettingsHelper().getActivity()).getMapLayers().getQuickActionRegistry().updateQuickActions(newActions);
}
}
@Override
public Boolean shouldReadOnCollecting() {
return true;
}
@NonNull
@Override
public String getName() {
return "quick_actions";
}
@NonNull
@Override
public String getPublicName(@NonNull Context ctx) {
return "quick_actions";
}
@NonNull
@Override
public String getFileName() {
return getName() + ".json";
}
@NonNull
@Override
SettingsItemReader getReader() {
return new OsmandSettingsItemReader(this, getSettings()) {
@Override
protected void readPreferenceFromJson(@NonNull OsmandPreference<?> preference, @NonNull JSONObject json) throws JSONException {
}
@Override
public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException {
StringBuilder buf = new StringBuilder();
try {
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
String str;
while ((str = in.readLine()) != null) {
buf.append(str);
}
} catch (IOException e) {
throw new IOException("Cannot read json body", e);
}
String jsonStr = buf.toString();
if (Algorithms.isEmpty(jsonStr)) {
throw new IllegalArgumentException("Cannot find json body");
}
final JSONObject json;
try {
quickActions = new ArrayList<>();
Gson gson = new Gson();
Type type = new TypeToken<HashMap<String, String>>() {
}.getType();
json = new JSONObject(jsonStr);
JSONArray items = json.getJSONArray("items");
for (int i = 0; i < items.length(); i++) {
JSONObject object = items.getJSONObject(i);
String name = object.getString("name");
int actionType = object.getInt("type");
String paramsString = object.getString("params");
HashMap<String, String> params = gson.fromJson(paramsString, type);
QuickAction quickAction = new QuickAction(actionType);
quickAction.setName(name);
quickAction.setParams(params);
quickActions.add(quickAction);
}
} catch (JSONException e) {
throw new IllegalArgumentException("Json parse error", e);
}
}
};
}
@NonNull
@Override
SettingsItemWriter getWriter() {
return new OsmandSettingsItemWriter(this, getSettings()) {
@Override
protected void writePreferenceToJson(@NonNull OsmandPreference<?> preference, @NonNull JSONObject json) throws JSONException {
JSONArray items = new JSONArray();
Gson gson = new Gson();
Type type = new TypeToken<HashMap<String, String>>() {
}.getType();
if (!quickActions.isEmpty()) {
for (QuickAction action : quickActions) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", action.getName(app));
jsonObject.put("type", action.getType());
jsonObject.put("params", gson.toJson(action.getParams(), type));
items.put(jsonObject);
}
json.put("items", items);
}
}
};
}
}
public static class PoiUiFilterSettingsItem extends OsmandSettingsItem {
private List<PoiUIFilter> poiUIFilters;
private OsmandApplication app;
public PoiUiFilterSettingsItem(OsmandApplication app, List<PoiUIFilter> poiUIFilters) {
super(SettingsItemType.POI_UI_FILTERS, app.getSettings());
this.app = app;
this.poiUIFilters = poiUIFilters;
}
public PoiUiFilterSettingsItem(OsmandApplication app, JSONObject jsonObject) throws JSONException {
super(SettingsItemType.POI_UI_FILTERS, app.getSettings(), jsonObject);
this.app = app;
}
public List<PoiUIFilter> getPoiUIFilters() {
return this.poiUIFilters != null ? this.poiUIFilters : new ArrayList<PoiUIFilter>();
}
@Override
public void apply() {
if (!poiUIFilters.isEmpty()) {
for (PoiUIFilter filter : poiUIFilters) {
app.getPoiFilters().createPoiFilter(filter, false);
}
app.getSearchUICore().refreshCustomPoiFilters();
}
}
@NonNull
@Override
public String getName() {
return "poi_ui_filters";
}
@NonNull
@Override
public String getPublicName(@NonNull Context ctx) {
return null;
}
@Override
public Boolean shouldReadOnCollecting() {
return true;
}
@NonNull
@Override
public String getFileName() {
return getName() + ".json";
}
@NonNull
@Override
SettingsItemReader getReader() {
return new OsmandSettingsItemReader(this, getSettings()) {
@Override
protected void readPreferenceFromJson(@NonNull OsmandPreference<?> preference, @NonNull JSONObject json) throws JSONException {
}
@Override
public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException {
StringBuilder buf = new StringBuilder();
try {
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
String str;
while ((str = in.readLine()) != null) {
buf.append(str);
}
} catch (IOException e) {
throw new IOException("Cannot read json body", e);
}
String jsonStr = buf.toString();
if (Algorithms.isEmpty(jsonStr)) {
throw new IllegalArgumentException("Cannot find json body");
}
final JSONObject json;
try {
poiUIFilters = new ArrayList<>();
json = new JSONObject(jsonStr);
JSONArray items = json.getJSONArray("items");
Gson gson = new Gson();
Type type = new TypeToken<HashMap<String, LinkedHashSet<String>>>() {
}.getType();
MapPoiTypes poiTypes = app.getPoiTypes();
for (int i = 0; i < items.length(); i++) {
JSONObject object = items.getJSONObject(i);
String name = object.getString("name");
String filterId = object.getString("filterId");
String acceptedTypesString = object.getString("acceptedTypes");
HashMap<String, LinkedHashSet<String>> acceptedTypes = gson.fromJson(acceptedTypesString, type);
Map<PoiCategory, LinkedHashSet<String>> acceptedTypesDone = new HashMap<>();
for (Map.Entry<String, LinkedHashSet<String>> mapItem : acceptedTypes.entrySet()) {
final PoiCategory a = poiTypes.getPoiCategoryByName(mapItem.getKey());
acceptedTypesDone.put(a, mapItem.getValue());
}
PoiUIFilter filter = new PoiUIFilter(name, filterId, acceptedTypesDone, app);
poiUIFilters.add(filter);
}
} catch (JSONException e) {
throw new IllegalArgumentException("Json parse error", e);
}
}
};
}
@NonNull
@Override
SettingsItemWriter getWriter() {
return new OsmandSettingsItemWriter(this, getSettings()) {
@Override
protected void writePreferenceToJson(@NonNull OsmandPreference<?> preference, @NonNull JSONObject json) throws JSONException {
JSONArray items = new JSONArray();
Gson gson = new Gson();
Type type = new TypeToken<HashMap<PoiCategory, LinkedHashSet<String>>>() {
}.getType();
if (!poiUIFilters.isEmpty()) {
for (PoiUIFilter filter : poiUIFilters) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", filter.getName());
jsonObject.put("filterId", filter.getFilterId());
jsonObject.put("acceptedTypes", gson.toJson(filter.getAcceptedTypes(), type));
items.put(jsonObject);
}
json.put("items", items);
}
}
};
}
}
public static class MapSourcesSettingsItem extends OsmandSettingsItem {
private OsmandApplication app;
private List<ITileSource> mapSources;
public MapSourcesSettingsItem(OsmandApplication app, List<ITileSource> mapSources) {
super(SettingsItemType.MAP_SOURCES, app.getSettings());
this.app = app;
this.mapSources = mapSources;
}
public MapSourcesSettingsItem(OsmandApplication app, JSONObject jsonObject) throws JSONException {
super(SettingsItemType.MAP_SOURCES, app.getSettings(), jsonObject);
this.app = app;
}
public List<ITileSource> getMapSources() {
return this.mapSources;
}
@Override
public void apply() {
if (!mapSources.isEmpty()) {
for (ITileSource template : mapSources) {
if (template instanceof TileSourceManager.TileSourceTemplate) {
getSettings().installTileSource((TileSourceManager.TileSourceTemplate) template);
} else {
((SQLiteTileSource) template).createDataBase();
}
}
}
}
@NonNull
@Override
public String getName() {
return "map_sources";
}
@NonNull
@Override
public String getPublicName(@NonNull Context ctx) {
return null;
}
@Override
public Boolean shouldReadOnCollecting() {
return true;
}
@NonNull
@Override
public String getFileName() {
return getName() + ".json";
}
@NonNull
@Override
SettingsItemReader getReader() {
return new OsmandSettingsItemReader(this, getSettings()) {
@Override
protected void readPreferenceFromJson(@NonNull OsmandPreference<?> preference, @NonNull JSONObject json) throws JSONException {
}
@Override
public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException {
StringBuilder buf = new StringBuilder();
try {
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
String str;
while ((str = in.readLine()) != null) {
buf.append(str);
}
} catch (IOException e) {
throw new IOException("Cannot read json body", e);
}
String jsonStr = buf.toString();
if (Algorithms.isEmpty(jsonStr)) {
throw new IllegalArgumentException("Cannot find json body");
}
final JSONObject json;
try {
mapSources = new ArrayList<>();
json = new JSONObject(jsonStr);
JSONArray items = json.getJSONArray("items");
for (int i = 0; i < items.length(); i++) {
JSONObject object = items.getJSONObject(i);
boolean sql = object.optBoolean("sql");
String name = object.optString("name");
int minZoom = object.optInt("minZoom");
int maxZoom = object.optInt("maxZoom");
String url = object.optString("url");
String randoms = object.optString("randoms");
boolean ellipsoid = object.optBoolean("ellipsoid", false);
boolean invertedY = object.optBoolean("inverted_y", false);
String referer = object.optString("referer");
boolean timesupported = object.optBoolean("timesupported", false);
long expire = object.optLong("expire");
boolean inversiveZoom = object.optBoolean("inversiveZoom", false);
String ext = object.optString("ext");
int tileSize = object.optInt("tileSize");
int bitDensity = object.optInt("bitDensity");
int avgSize = object.optInt("avgSize");
String rule = object.optString("rule");
ITileSource template;
if (!sql) {
template = new TileSourceManager.TileSourceTemplate(name, url, ext, maxZoom, minZoom, tileSize, bitDensity, avgSize);
} else {
template = new SQLiteTileSource(app, name, minZoom, maxZoom, url, randoms, ellipsoid, invertedY, referer, timesupported, expire, inversiveZoom);
}
mapSources.add(template);
}
} catch (JSONException e) {
throw new IllegalArgumentException("Json parse error", e);
}
}
};
}
@NonNull
@Override
SettingsItemWriter getWriter() {
return new OsmandSettingsItemWriter(this, getSettings()) {
@Override
protected void writePreferenceToJson(@NonNull OsmandPreference<?> preference, @NonNull JSONObject json) throws JSONException {
JSONArray items = new JSONArray();
if (!mapSources.isEmpty()) {
for (ITileSource template : mapSources) {
JSONObject jsonObject = new JSONObject();
boolean sql = template instanceof SQLiteTileSource;
jsonObject.put("sql", sql);
jsonObject.put("name", template.getName());
jsonObject.put("minZoom", template.getMinimumZoomSupported());
jsonObject.put("maxZoom", template.getMaximumZoomSupported());
jsonObject.put("url", template.getUrlTemplate());
jsonObject.put("randoms", template.getRandoms());
jsonObject.put("ellipsoid", template.isEllipticYTile());
jsonObject.put("inverted_y", template.isInvertedYTile());
jsonObject.put("referer", template.getReferer());
jsonObject.put("timesupported", template.isTimeSupported());
jsonObject.put("expire", template.getExpirationTimeMillis());
jsonObject.put("inversiveZoom", template.getInversiveZoom());
jsonObject.put("ext", template.getTileFormat());
jsonObject.put("tileSize", template.getTileSize());
jsonObject.put("bitDensity", template.getBitDensity());
jsonObject.put("avgSize", template.getAvgSize());
jsonObject.put("rule", template.getRule());
items.put(jsonObject);
}
json.put("items", items);
}
}
};
}
}
private static class SettingsItemsFactory {
private OsmandApplication app;
@ -762,6 +1224,15 @@ public class SettingsHelper {
case FILE:
item = new FileSettingsItem(app, json);
break;
case QUICK_ACTION:
item = new QuickActionSettingsItem(app, json);
break;
case POI_UI_FILTERS:
item = new PoiUiFilterSettingsItem(app, json);
break;
case MAP_SOURCES:
item = new MapSourcesSettingsItem(app, json);
break;
}
return item;
}
@ -873,10 +1344,11 @@ public class SettingsHelper {
LOG.error("Error parsing items: " + itemsJson, e);
throw new IllegalArgumentException("No items");
}
while (!collecting && (entry = zis.getNextEntry()) != null) {
while ((entry = zis.getNextEntry()) != null) {
String fileName = entry.getName();
SettingsItem item = itemsFactory.getItemByFileName(fileName);
if (item != null) {
if (item != null && collecting && item.shouldReadOnCollecting()
|| item != null && !collecting && !item.shouldReadOnCollecting()) {
try {
item.getReader().readFromStream(ois);
} catch (IllegalArgumentException e) {
@ -924,6 +1396,17 @@ public class SettingsHelper {
this.version = version;
this.askBeforeImport = askBeforeImport;
importer = new SettingsImporter(app);
collectOnly = true;
}
ImportAsyncTask(@NonNull File settingsFile, @NonNull List<SettingsItem> items, String latestChanges, int version, @Nullable SettingsImportListener listener) {
this.file = settingsFile;
this.listener = listener;
this.items = items;
this.latestChanges = latestChanges;
this.version = version;
importer = new SettingsImporter(app);
collectOnly = false;
}
@Override
@ -938,12 +1421,16 @@ public class SettingsHelper {
@Override
protected List<SettingsItem> doInBackground(Void... voids) {
try {
return importer.collectItems(file);
} catch (IllegalArgumentException e) {
LOG.error("Failed to collect items from: " + file.getName(), e);
} catch (IOException e) {
LOG.error("Failed to collect items from: " + file.getName(), e);
if (collectOnly) {
try {
return importer.collectItems(file);
} catch (IllegalArgumentException e) {
LOG.error("Failed to collect items from: " + file.getName(), e);
} catch (IOException e) {
LOG.error("Failed to collect items from: " + file.getName(), e);
}
} else {
return this.items;
}
return null;
}
@ -951,8 +1438,12 @@ public class SettingsHelper {
@Override
protected void onPostExecute(List<SettingsItem> items) {
this.items = items;
if (items != null && items.size() > 0) {
processNextItem();
if (collectOnly) {
listener.onSettingsImportFinished(true, false, items);
} else {
if (items != null && items.size() > 0) {
processNextItem();
}
}
}
@ -1045,6 +1536,24 @@ public class SettingsHelper {
processedItems.add(item);
processNextItem();
}
public List<SettingsItem> getItems() {
return this.items;
}
public File getFile() {
return this.file;
}
}
@Nullable
public List<SettingsItem> getSettingsItems() {
return this.importTask.getItems();
}
@Nullable
public File getSettingsFile() {
return this.importTask.getFile();
}
@SuppressLint("StaticFieldLeak")
@ -1136,6 +1645,10 @@ public class SettingsHelper {
new ImportAsyncTask(settingsFile, latestChanges, version, askBeforeImport, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void importSettings(@NonNull File settingsFile, @NonNull List<SettingsItem> items, String latestChanges, int version, @Nullable SettingsImportListener listener) {
new ImportAsyncTask(settingsFile, items, latestChanges, version, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void exportSettings(@NonNull File fileDir, @NonNull String fileName,
@Nullable SettingsExportListener listener,
@NonNull List<SettingsItem> items) {
@ -1147,4 +1660,4 @@ public class SettingsHelper {
@NonNull SettingsItem... items) {
exportSettings(fileDir, fileName, listener, new ArrayList<>(Arrays.asList(items)));
}
}
}

View file

@ -369,7 +369,7 @@ public class UiUtilities {
activeColor = ContextCompat.getColor(app, appMode.getIconColorInfo().getColor(nightMode));
break;
case TOOLBAR:
activeColor = ContextCompat.getColor(app, nightMode ? R.color.text_color_tab_active_dark : R.color.text_color_tab_active_light);
activeColor = Color.WHITE;
inactiveColorPrimary = activeColor;
inactiveColorSecondary = UiUtilities.getColorWithAlpha(Color.BLACK, 0.25f);
break;

View file

@ -15,6 +15,7 @@ import android.provider.OpenableColumns;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.style.ForegroundColorSpan;
@ -33,6 +34,7 @@ import net.osmand.data.FavouritePoint;
import net.osmand.plus.AppInitializer;
import net.osmand.plus.AppInitializer.AppInitializeListener;
import net.osmand.plus.AppInitializer.InitEvents;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.GPXDatabase;
import net.osmand.plus.OsmandApplication;
@ -49,6 +51,9 @@ import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerHalfItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.ShortDescriptionItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.profiles.AdditionalDataWrapper;
import net.osmand.plus.profiles.ExportImportProfileBottomSheet;
import net.osmand.plus.quickaction.QuickAction;
import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.router.RoutingConfiguration;
@ -767,7 +772,7 @@ public class ImportHelper {
@Override
protected void onPostExecute(String error) {
File tempDir = app.getAppPath(IndexConstants.TEMP_DIR);
File file = new File(tempDir, name);
final File file = new File(tempDir, name);
if (error == null && file.exists()) {
app.getSettingsHelper().importSettings(file, latestChanges, version, askBeforeImport, new SettingsImportListener() {
@Override
@ -776,11 +781,15 @@ public class ImportHelper {
progress.dismiss();
}
if (succeed) {
app.showShortToastMessage(app.getString(R.string.file_imported_successfully, name));
if (callback != null) {
callback.processResult(items);
FragmentManager fragmentManager = activity.getSupportFragmentManager();
if (fragmentManager != null) {
ExportImportProfileBottomSheet.showInstance(
fragmentManager,
ExportImportProfileBottomSheet.State.IMPORT,
file,
items);
}
} else if (!empty) {
} else {
app.showShortToastMessage(app.getString(R.string.file_import_error, name, app.getString(R.string.shared_string_unexpected_error)));
}
}

View file

@ -167,6 +167,10 @@ public abstract class PointEditorFragment extends BaseOsmAndFragment {
descriptionEdit.setHint(R.string.access_hint_enter_description);
}
if (Build.VERSION.SDK_INT >= 21) {
AndroidUtils.addStatusBarPadding21v(app, view);
}
return view;
}
@ -234,11 +238,6 @@ public abstract class PointEditorFragment extends BaseOsmAndFragment {
return R.color.status_bar_color_light;
}
@Override
protected boolean isFullScreenAllowed() {
return false;
}
private void hideKeyboard() {
FragmentActivity activity = getActivity();
if (activity != null) {

View file

@ -0,0 +1,35 @@
package net.osmand.plus.profiles;
import java.util.List;
public class AdditionalDataWrapper {
private Type type;
private List<?> items;
public AdditionalDataWrapper(Type type, List<?> items) {
this.type = type;
this.items = items;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public List<?> getItems() {
return items;
}
public enum Type {
QUICK_ACTIONS,
POI_TYPES,
MAP_SOURCES,
CUSTOM_RENDER_STYLE,
CUSTOM_ROUTING
}
}

View file

@ -2,6 +2,7 @@ package net.osmand.plus.profiles;
import android.annotation.SuppressLint;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@ -174,12 +175,11 @@ public class EditProfilesFragment extends BaseOsmAndFragment {
}
});
return mainView;
}
if (Build.VERSION.SDK_INT >= 21) {
AndroidUtils.addStatusBarPadding21v(app, mainView);
}
@Override
protected boolean isFullScreenAllowed() {
return false;
return mainView;
}
@Override

View file

@ -0,0 +1,711 @@
package net.osmand.plus.profiles;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.CompoundButtonCompat;
import android.support.v7.widget.SwitchCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import net.osmand.AndroidUtils;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.map.ITileSource;
import net.osmand.map.TileSourceManager;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.SQLiteTileSource;
import net.osmand.plus.SettingsHelper;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.OsmandBaseExpandableListAdapter;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.quickaction.QuickAction;
import net.osmand.plus.quickaction.QuickActionFactory;
import net.osmand.plus.render.RenderingIcons;
import net.osmand.plus.settings.BaseSettingsFragment;
import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet;
import org.apache.commons.logging.Log;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class ExportImportProfileBottomSheet extends BasePreferenceBottomSheet {
private static final Log LOG = PlatformUtil.getLog(ExportImportProfileBottomSheet.class);
public static final String TAG = ExportImportProfileBottomSheet.class.getSimpleName();
private static final String STATE_KEY = "EXPORT_IMPORT_DIALOG_STATE_KEY";
private static final String INCLUDE_ADDITIONAL_DATA_KEY = "INCLUDE_ADDITIONAL_DATA_KEY";
private boolean includeAdditionalData = false;
private boolean containsAdditionalData = false;
private OsmandApplication app;
private ApplicationMode profile;
private State state;
private List<AdditionalDataWrapper> dataList = new ArrayList<>();
private List<? super Object> dataToOperate = new ArrayList<>();
private List<SettingsHelper.SettingsItem> settingsItems;
private ExpandableListView listView;
private ProfileAdditionalDataAdapter adapter;
private SettingsHelper.ProfileSettingsItem profileSettingsItem;
private File file;
@Override
public void onCreate(Bundle savedInstanceState) {
if (savedInstanceState != null) {
includeAdditionalData = savedInstanceState.getBoolean(INCLUDE_ADDITIONAL_DATA_KEY);
}
super.onCreate(savedInstanceState);
app = requiredMyApplication();
Bundle bundle = getArguments();
if (bundle != null) {
this.state = (State) getArguments().getSerializable(STATE_KEY);
}
if (state == State.IMPORT) {
if (settingsItems == null) {
settingsItems = app.getSettingsHelper().getSettingsItems();
}
if (file == null) {
file = app.getSettingsHelper().getSettingsFile();
}
containsAdditionalData = checkAdditionalDataContains();
} else {
dataList = getAdditionalData();
for (AdditionalDataWrapper dataWrapper : dataList) {
dataToOperate.addAll(dataWrapper.getItems());
}
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(INCLUDE_ADDITIONAL_DATA_KEY, includeAdditionalData);
}
@Override
public void createMenuItems(Bundle savedInstanceState) {
final Context context = getContext();
if (context == null) {
return;
}
LayoutInflater inflater = UiUtilities.getInflater(app, nightMode);
profile = state == State.IMPORT ? getAppModeFromSettingsItems() : getAppMode();
int profileColor = profile.getIconColorInfo().getColor(nightMode);
int colorNoAlpha = ContextCompat.getColor(context, profileColor);
Drawable backgroundIcon = UiUtilities.getColoredSelectableDrawable(context, colorNoAlpha, 0.3f);
Drawable[] layers = {new ColorDrawable(UiUtilities.getColorWithAlpha(colorNoAlpha, 0.10f)), backgroundIcon};
items.add(new TitleItem(state == State.EXPORT ?
getString(R.string.export_profile)
: getString(R.string.import_profile)));
BaseBottomSheetItem profileItem = new BottomSheetItemWithCompoundButton.Builder()
.setChecked(true)
.setCompoundButtonColorId(profileColor)
.setButtonTintList(ColorStateList.valueOf(getResolvedColor(profileColor)))
.setDescription(BaseSettingsFragment.getAppModeDescription(context, profile))
.setIcon(getIcon(profile.getIconRes(), profileColor))
.setTitle(profile.toHumanString())
.setBackground(new LayerDrawable(layers))
.setLayoutId(R.layout.preference_profile_item_with_radio_btn)
.create();
items.add(profileItem);
if (state == State.IMPORT && containsAdditionalData || state == State.EXPORT && !dataList.isEmpty()) {
BaseBottomSheetItem descriptionItem = new BottomSheetItemWithDescription.Builder()
.setDescription(state == State.EXPORT ?
getString(R.string.export_profile_dialog_description)
: getString(R.string.import_profile_dialog_description))
.setLayoutId(R.layout.bottom_sheet_item_pref_info)
.create();
items.add(descriptionItem);
final View additionalDataView = inflater.inflate(R.layout.bottom_sheet_item_additional_data, null);
listView = additionalDataView.findViewById(R.id.list);
SwitchCompat switchItem = additionalDataView.findViewById(R.id.switchItem);
switchItem.setTextColor(getResources().getColor(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light));
switchItem.setChecked(includeAdditionalData);
switchItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
includeAdditionalData = !includeAdditionalData;
listView.setVisibility(includeAdditionalData ?
View.VISIBLE : View.GONE);
if (includeAdditionalData && state == State.IMPORT) {
updateDataToOperateFromSettingsItems();
}
setupHeightAndBackground(getView());
}
});
listView.setVisibility(includeAdditionalData ? View.VISIBLE : View.GONE);
adapter = new ProfileAdditionalDataAdapter(app, dataList, profileColor);
listView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
@Override
public void onGroupExpand(int i) {
setupHeightAndBackground(getView());
}
});
listView.setAdapter(adapter);
final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder()
.setCustomView(additionalDataView)
.create();
items.add(titleItem);
}
}
@Override
protected int getRightBottomButtonTextId() {
return state == State.EXPORT ? R.string.shared_string_export : R.string.shared_string_import;
}
@Override
protected void onRightBottomButtonClick() {
super.onRightBottomButtonClick();
if (state == State.EXPORT) {
prepareFile();
} else {
importSettings();
}
}
@Override
protected int getDismissButtonTextId() {
return R.string.shared_string_cancel;
}
@Override
protected boolean useScrollableItemsContainer() {
return false;
}
private ApplicationMode getAppModeFromSettingsItems() {
for (SettingsHelper.SettingsItem item : settingsItems) {
if (item.getType().equals(SettingsHelper.SettingsItemType.PROFILE)) {
profileSettingsItem = ((SettingsHelper.ProfileSettingsItem) item);
return ((SettingsHelper.ProfileSettingsItem) item).getAppMode();
}
}
return getAppMode();
}
private List<AdditionalDataWrapper> getAdditionalData() {
List<AdditionalDataWrapper> dataList = new ArrayList<>();
QuickActionFactory factory = new QuickActionFactory();
List<QuickAction> actionsList = factory.parseActiveActionsList(app.getSettings().QUICK_ACTION_LIST.get());
if (!actionsList.isEmpty()) {
dataList.add(new AdditionalDataWrapper(
AdditionalDataWrapper.Type.QUICK_ACTIONS, actionsList));
}
List<PoiUIFilter> poiList = app.getPoiFilters().getUserDefinedPoiFilters(false);
if (!poiList.isEmpty()) {
dataList.add(new AdditionalDataWrapper(
AdditionalDataWrapper.Type.POI_TYPES,
poiList
));
}
List<ITileSource> iTileSources = new ArrayList<>();
final LinkedHashMap<String, String> tileSourceEntries = new LinkedHashMap<>(app.getSettings().getTileSourceEntries(true));
for (Map.Entry<String, String> entry : tileSourceEntries.entrySet()) {
File f = app.getAppPath(IndexConstants.TILES_INDEX_DIR + entry.getKey());
if (f != null) {
ITileSource template;
if (f.getName().endsWith(SQLiteTileSource.EXT)) {
template = new SQLiteTileSource(app, f, TileSourceManager.getKnownSourceTemplates());
} else {
template = TileSourceManager.createTileSourceTemplate(f);
}
if (template != null && template.getUrlTemplate() != null) {
iTileSources.add(template);
}
}
}
if (!iTileSources.isEmpty()) {
dataList.add(new AdditionalDataWrapper(
AdditionalDataWrapper.Type.MAP_SOURCES,
iTileSources
));
}
Map<String, File> externalRenderers = app.getRendererRegistry().getExternalRenderers();
if (!externalRenderers.isEmpty()) {
dataList.add(new AdditionalDataWrapper(
AdditionalDataWrapper.Type.CUSTOM_RENDER_STYLE,
new ArrayList<>(externalRenderers.values())
));
}
File routingProfilesFolder = app.getAppPath(IndexConstants.ROUTING_PROFILES_DIR);
if (routingProfilesFolder.exists() && routingProfilesFolder.isDirectory()) {
File[] fl = routingProfilesFolder.listFiles();
if (fl != null && fl.length > 0) {
dataList.add(new AdditionalDataWrapper(
AdditionalDataWrapper.Type.CUSTOM_ROUTING,
Arrays.asList(fl)
));
}
}
return dataList;
}
private List<SettingsHelper.SettingsItem> prepareSettingsItemsForExport() {
List<SettingsHelper.SettingsItem> settingsItems = new ArrayList<>();
settingsItems.add(new SettingsHelper.ProfileSettingsItem(app.getSettings(), profile));
if (includeAdditionalData) {
settingsItems.addAll(prepareAdditionalSettingsItems());
}
return settingsItems;
}
private List<SettingsHelper.SettingsItem> prepareAdditionalSettingsItems() {
List<SettingsHelper.SettingsItem> settingsItems = new ArrayList<>();
List<QuickAction> quickActions = new ArrayList<>();
List<PoiUIFilter> poiUIFilters = new ArrayList<>();
List<ITileSource> tileSourceTemplates = new ArrayList<>();
for (Object object : dataToOperate) {
if (object instanceof QuickAction) {
quickActions.add((QuickAction) object);
} else if (object instanceof PoiUIFilter) {
poiUIFilters.add((PoiUIFilter) object);
} else if (object instanceof TileSourceManager.TileSourceTemplate
|| object instanceof SQLiteTileSource) {
tileSourceTemplates.add((ITileSource) object);
} else if (object instanceof File) {
settingsItems.add(new SettingsHelper.FileSettingsItem(app, (File) object));
}
}
if (!quickActions.isEmpty()) {
settingsItems.add(new SettingsHelper.QuickActionSettingsItem(app, quickActions));
}
if (!poiUIFilters.isEmpty()) {
settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app, poiUIFilters));
}
if (!tileSourceTemplates.isEmpty()) {
settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app, tileSourceTemplates));
}
return settingsItems;
}
private Boolean checkAdditionalDataContains() {
boolean containsData = false;
for (SettingsHelper.SettingsItem item : settingsItems) {
containsData = item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION)
|| item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS)
|| item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES)
|| item.getType().equals(SettingsHelper.SettingsItemType.FILE);
if (containsData) {
break;
}
}
return containsData;
}
private void updateDataToOperateFromSettingsItems() {
List<AdditionalDataWrapper> dataList = new ArrayList<>();
List<QuickAction> quickActions = new ArrayList<>();
List<PoiUIFilter> poiUIFilters = new ArrayList<>();
List<ITileSource> tileSourceTemplates = new ArrayList<>();
List<File> routingFilesList = new ArrayList<>();
List<File> renderFilesList = new ArrayList<>();
for (SettingsHelper.SettingsItem item : settingsItems) {
if (item.getType().equals(SettingsHelper.SettingsItemType.QUICK_ACTION)) {
quickActions.addAll(((SettingsHelper.QuickActionSettingsItem) item).getQuickActions());
} else if (item.getType().equals(SettingsHelper.SettingsItemType.POI_UI_FILTERS)) {
poiUIFilters.addAll(((SettingsHelper.PoiUiFilterSettingsItem) item).getPoiUIFilters());
} else if (item.getType().equals(SettingsHelper.SettingsItemType.MAP_SOURCES)) {
tileSourceTemplates.addAll(((SettingsHelper.MapSourcesSettingsItem) item).getMapSources());
} else if (item.getType().equals(SettingsHelper.SettingsItemType.FILE)) {
if (item.getName().startsWith("/rendering/")) {
renderFilesList.add(((SettingsHelper.FileSettingsItem) item).getFile());
} else if (item.getName().startsWith("/routing/")) {
routingFilesList.add(((SettingsHelper.FileSettingsItem) item).getFile());
}
}
}
if (!quickActions.isEmpty()) {
dataList.add(new AdditionalDataWrapper(
AdditionalDataWrapper.Type.QUICK_ACTIONS,
quickActions));
dataToOperate.addAll(quickActions);
}
if (!poiUIFilters.isEmpty()) {
dataList.add(new AdditionalDataWrapper(
AdditionalDataWrapper.Type.POI_TYPES,
poiUIFilters));
dataToOperate.addAll(poiUIFilters);
}
if (!tileSourceTemplates.isEmpty()) {
dataList.add(new AdditionalDataWrapper(
AdditionalDataWrapper.Type.MAP_SOURCES,
tileSourceTemplates
));
dataToOperate.addAll(tileSourceTemplates);
}
if (!renderFilesList.isEmpty()) {
dataList.add(new AdditionalDataWrapper(
AdditionalDataWrapper.Type.CUSTOM_RENDER_STYLE,
renderFilesList
));
dataToOperate.addAll(renderFilesList);
}
if (!routingFilesList.isEmpty()) {
dataList.add(new AdditionalDataWrapper(
AdditionalDataWrapper.Type.CUSTOM_ROUTING,
routingFilesList
));
dataToOperate.addAll(routingFilesList);
}
adapter.updateList(dataList);
}
private void importSettings() {
List<SettingsHelper.SettingsItem> list = new ArrayList<>();
list.add(profileSettingsItem);
if (includeAdditionalData) {
list.addAll(prepareAdditionalSettingsItems());
}
app.getSettingsHelper().importSettings(file, list, "", 1, new SettingsHelper.SettingsImportListener() {
@Override
public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List<SettingsHelper.SettingsItem> items) {
if (succeed) {
app.showShortToastMessage(app.getString(R.string.file_imported_successfully, file.getName()));
} else if (empty) {
app.showShortToastMessage(app.getString(R.string.file_import_error, file.getName(), app.getString(R.string.shared_string_unexpected_error)));
}
}
});
dismiss();
}
private void prepareFile() {
if (app != null) {
File tempDir = app.getAppPath(IndexConstants.TEMP_DIR);
if (!tempDir.exists()) {
tempDir.mkdirs();
}
String fileName = profile.toHumanString();
app.getSettingsHelper().exportSettings(tempDir, fileName, new SettingsHelper.SettingsExportListener() {
@Override
public void onSettingsExportFinished(@NonNull File file, boolean succeed) {
if (succeed) {
shareProfile(file, profile);
} else {
app.showToastMessage(R.string.export_profile_failed);
}
}
}, prepareSettingsItemsForExport());
}
}
private void shareProfile(@NonNull File file, @NonNull ApplicationMode profile) {
try {
final Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.exported_osmand_profile, profile.toHumanString()));
sendIntent.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), file));
sendIntent.setType("*/*");
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(sendIntent);
dismiss();
} catch (Exception e) {
Toast.makeText(requireContext(), R.string.export_profile_failed, Toast.LENGTH_SHORT).show();
LOG.error("Share profile error", e);
}
}
public static boolean showInstance(@NonNull FragmentManager fragmentManager,
State state,
Fragment target,
@NonNull ApplicationMode appMode) {
try {
Bundle bundle = new Bundle();
bundle.putSerializable(STATE_KEY, state);
ExportImportProfileBottomSheet fragment = new ExportImportProfileBottomSheet();
fragment.setArguments(bundle);
fragment.setAppMode(appMode);
fragment.setTargetFragment(target, 0);
fragment.show(fragmentManager, TAG);
return true;
} catch (RuntimeException e) {
return false;
}
}
public static boolean showInstance(@NonNull FragmentManager fragmentManager,
State state,
File file,
List<SettingsHelper.SettingsItem> items) {
try {
Bundle bundle = new Bundle();
bundle.putSerializable(STATE_KEY, state);
ExportImportProfileBottomSheet fragment = new ExportImportProfileBottomSheet();
fragment.setArguments(bundle);
fragment.setSettingsItems(items);
fragment.setFile(file);
fragment.show(fragmentManager, TAG);
return true;
} catch (RuntimeException e) {
return false;
}
}
public void setSettingsItems(List<SettingsHelper.SettingsItem> settingsItems) {
this.settingsItems = settingsItems;
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public enum State {
EXPORT,
IMPORT
}
class ProfileAdditionalDataAdapter extends OsmandBaseExpandableListAdapter {
private OsmandApplication app;
private List<AdditionalDataWrapper> list;
private int profileColor;
ProfileAdditionalDataAdapter(OsmandApplication app, List<AdditionalDataWrapper> list, int profileColor) {
this.app = app;
this.list = list;
this.profileColor = profileColor;
}
public void updateList(List<AdditionalDataWrapper> list) {
this.list = list;
notifyDataSetChanged();
}
@Override
public int getGroupCount() {
return list.size();
}
@Override
public int getChildrenCount(int i) {
return list.get(i).getItems().size();
}
@Override
public Object getGroup(int i) {
return list.get(i);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return list.get(groupPosition).getItems().get(childPosition);
}
@Override
public long getGroupId(int i) {
return i;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return groupPosition * 10000 + childPosition;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
View group = convertView;
if (group == null) {
LayoutInflater inflater = UiUtilities.getInflater(app, nightMode);
group = inflater.inflate(R.layout.profile_data_list_item_group, parent, false);
}
boolean isLastGroup = groupPosition == getGroupCount() - 1;
final AdditionalDataWrapper.Type type = list.get(groupPosition).getType();
TextView titleTv = group.findViewById(R.id.title_tv);
TextView subTextTv = group.findViewById(R.id.sub_text_tv);
final CheckBox checkBox = group.findViewById(R.id.check_box);
ImageView expandIv = group.findViewById(R.id.explist_indicator);
View divider = group.findViewById(R.id.divider);
titleTv.setText(getGroupTitle(type));
divider.setVisibility(isExpanded || isLastGroup ? View.GONE : View.VISIBLE);
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, profileColor)));
final List<?> listItems = list.get(groupPosition).getItems();
subTextTv.setText(String.valueOf(listItems.size()));
checkBox.setChecked(dataToOperate.containsAll(listItems));
checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (checkBox.isChecked()) {
for (Object object : listItems) {
if (!dataToOperate.contains(object)) {
dataToOperate.add(object);
}
}
} else {
dataToOperate.removeAll(listItems);
}
notifyDataSetInvalidated();
}
});
adjustIndicator(app, groupPosition, isExpanded, group, true);
return group;
}
@Override
public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
View child = convertView;
if (child == null) {
LayoutInflater inflater = UiUtilities.getInflater(app, nightMode);
child = inflater.inflate(R.layout.profile_data_list_item_child, parent, false);
}
final Object currentItem = list.get(groupPosition).getItems().get(childPosition);
boolean isLastGroup = groupPosition == getGroupCount() - 1;
final AdditionalDataWrapper.Type type = list.get(groupPosition).getType();
TextView title = child.findViewById(R.id.title_tv);
final CheckBox checkBox = child.findViewById(R.id.check_box);
ImageView icon = child.findViewById(R.id.icon);
View divider = child.findViewById(R.id.divider);
divider.setVisibility(isLastChild && !isLastGroup ? View.VISIBLE : View.GONE);
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, profileColor)));
checkBox.setChecked(dataToOperate.contains(currentItem));
checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (checkBox.isChecked()) {
dataToOperate.add(currentItem);
} else {
dataToOperate.remove(currentItem);
}
notifyDataSetInvalidated();
}
});
switch (type) {
case QUICK_ACTIONS:
title.setText(((QuickAction) currentItem).getName(app.getApplicationContext()));
icon.setVisibility(View.INVISIBLE);
icon.setImageResource(R.drawable.ic_action_info_dark);
break;
case POI_TYPES:
title.setText(((PoiUIFilter) currentItem).getName());
icon.setVisibility(View.VISIBLE);
int iconRes = RenderingIcons.getBigIconResourceId(((PoiUIFilter) currentItem).getIconId());
icon.setImageDrawable(app.getUIUtilities().getIcon(iconRes != 0 ? iconRes : R.drawable.ic_person, profileColor));
break;
case MAP_SOURCES:
title.setText(((ITileSource) currentItem).getName());
icon.setVisibility(View.INVISIBLE);
icon.setImageResource(R.drawable.ic_action_info_dark);
break;
case CUSTOM_RENDER_STYLE:
String renderName = ((File) currentItem).getName();
renderName = renderName.replace('_', ' ').replaceAll(".render.xml", "");
title.setText(renderName);
icon.setVisibility(View.INVISIBLE);
icon.setImageResource(R.drawable.ic_action_info_dark);
break;
case CUSTOM_ROUTING:
String routingName = ((File) currentItem).getName();
routingName = routingName.replace('_', ' ').replaceAll(".xml", "");
title.setText(routingName);
icon.setVisibility(View.INVISIBLE);
icon.setImageResource(R.drawable.ic_action_info_dark);
break;
default:
return child;
}
return child;
}
@Override
public boolean isChildSelectable(int i, int i1) {
return false;
}
private int getGroupTitle(AdditionalDataWrapper.Type type) {
switch (type) {
case QUICK_ACTIONS:
return R.string.configure_screen_quick_action;
case POI_TYPES:
return R.string.poi_dialog_poi_type;
case MAP_SOURCES:
return R.string.quick_action_map_source_title;
case CUSTOM_RENDER_STYLE:
return R.string.shared_string_custom_rendering_style;
case CUSTOM_ROUTING:
return R.string.shared_string_routing;
default:
return R.string.access_empty_list;
}
}
}
}

View file

@ -22,7 +22,6 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.LongDescriptionItem;
@ -30,6 +29,7 @@ import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.settings.MainSettingsFragment;
import net.osmand.plus.settings.NavigationFragment;
import net.osmand.plus.settings.ProfileAppearanceFragment;
import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet;
import net.osmand.router.RoutingConfiguration;
import org.apache.commons.logging.Log;
@ -39,7 +39,7 @@ import java.util.List;
import static net.osmand.plus.helpers.ImportHelper.ImportType.ROUTING;
public class SelectProfileBottomSheetDialogFragment extends MenuBottomSheetDialogFragment {
public class SelectProfileBottomSheetDialogFragment extends BasePreferenceBottomSheet {
private static final Log LOG = PlatformUtil
.getLog(SelectProfileBottomSheetDialogFragment.class);
@ -182,7 +182,7 @@ public class SelectProfileBottomSheetDialogFragment extends MenuBottomSheetDialo
int activeColorResId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light;
int iconDefaultColorResId = nightMode ? R.color.icon_color_default_dark : R.color.icon_color_default_light;
View itemView = View.inflate(getContext(), R.layout.bottom_sheet_item_with_descr_and_radio_btn, null);
View itemView = UiUtilities.getInflater(getContext(), nightMode).inflate(R.layout.bottom_sheet_item_with_descr_and_radio_btn, null);
TextView tvTitle = itemView.findViewById(R.id.title);
TextView tvDescription = itemView.findViewById(R.id.description);
ImageView ivIcon = itemView.findViewById(R.id.icon);

View file

@ -41,7 +41,7 @@ public class QuickAction {
this.type = type;
}
protected QuickAction(int type) {
public QuickAction(int type) {
this.id = System.currentTimeMillis();
this.type = type;
this.nameRes = QuickActionFactory.getActionName(type);

View file

@ -3,6 +3,7 @@ package net.osmand.plus.quickaction;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@ -24,6 +25,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import net.osmand.AndroidUtils;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
@ -73,6 +75,10 @@ public class QuickActionListFragment extends BaseOsmAndFragment implements Quick
}
});
if (Build.VERSION.SDK_INT >= 21) {
AndroidUtils.addStatusBarPadding21v(getContext(), view);
}
return view;
}
@ -145,11 +151,6 @@ public class QuickActionListFragment extends BaseOsmAndFragment implements Quick
quickActionRegistry.setUpdatesListener(null);
}
@Override
protected boolean isFullScreenAllowed() {
return false;
}
@Override
public int getStatusBarColorId() {
return isLightContent ? R.color.status_bar_color_light : R.color.status_bar_color_dark;

View file

@ -343,4 +343,8 @@ public class RendererRegistry {
}
return null;
}
public Map<String, File> getExternalRenderers() {
return externalRenderers;
}
}

View file

@ -259,9 +259,11 @@ public class RouteProvider {
// first of all check tracks
if (!useIntermediatePointsRTE) {
for (Track tr : file.tracks) {
for (TrkSegment tkSeg : tr.segments) {
for (WptPt pt : tkSeg.points) {
points.add(createLocation(pt));
if (!tr.generalTrack) {
for (TrkSegment tkSeg : tr.segments) {
for (WptPt pt : tkSeg.points) {
points.add(createLocation(pt));
}
}
}
}

View file

@ -104,7 +104,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
GLOBAL_SETTINGS(GlobalSettingsFragment.class.getName(), false, R.xml.global_settings, R.layout.global_preference_toolbar),
CONFIGURE_PROFILE(ConfigureProfileFragment.class.getName(), true, R.xml.configure_profile, R.layout.profile_preference_toolbar_with_switch),
PROXY_SETTINGS(ProxySettingsFragment.class.getName(), false, R.xml.proxy_preferences, R.layout.global_preferences_toolbar_with_switch),
GENERAL_PROFILE(GeneralProfileSettingsFragment.class.getName(), true, R.xml.general_profile_settings, R.layout.profile_preference_toolbar_big),
GENERAL_PROFILE(GeneralProfileSettingsFragment.class.getName(), true, R.xml.general_profile_settings, R.layout.profile_preference_toolbar),
NAVIGATION(NavigationFragment.class.getName(), true, R.xml.navigation_settings_new, R.layout.profile_preference_toolbar),
COORDINATES_FORMAT(CoordinatesFormatFragment.class.getName(), true, R.xml.coordinates_format, R.layout.profile_preference_toolbar),
ROUTE_PARAMETERS(RouteParametersFragment.class.getName(), true, R.xml.route_parameters, R.layout.profile_preference_toolbar),
@ -117,10 +117,10 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
DIALOGS_AND_NOTIFICATIONS_SETTINGS(DialogsAndNotificationsSettingsFragment.class.getName(), false, R.xml.dialogs_and_notifications_preferences, R.layout.global_preferences_toolbar_with_switch),
PROFILE_APPEARANCE(ProfileAppearanceFragment.TAG, true, R.xml.profile_appearance, R.layout.profile_preference_toolbar),
OPEN_STREET_MAP_EDITING(OsmEditingFragment.class.getName(), false, R.xml.osm_editing, R.layout.global_preference_toolbar),
MULTIMEDIA_NOTES(MultimediaNotesFragment.class.getName(), true, R.xml.multimedia_notes, R.layout.profile_preference_toolbar_big),
MONITORING_SETTINGS(MonitoringSettingsFragment.class.getName(), true, R.xml.monitoring_settings, R.layout.profile_preference_toolbar_big),
MULTIMEDIA_NOTES(MultimediaNotesFragment.class.getName(), true, R.xml.multimedia_notes, R.layout.profile_preference_toolbar),
MONITORING_SETTINGS(MonitoringSettingsFragment.class.getName(), true, R.xml.monitoring_settings, R.layout.profile_preference_toolbar),
LIVE_MONITORING(LiveMonitoringFragment.class.getName(), false, R.xml.live_monitoring, R.layout.global_preferences_toolbar_with_switch),
ACCESSIBILITY_SETTINGS(AccessibilitySettingsFragment.class.getName(), true, R.xml.accessibility_settings, R.layout.profile_preference_toolbar_big),
ACCESSIBILITY_SETTINGS(AccessibilitySettingsFragment.class.getName(), true, R.xml.accessibility_settings, R.layout.profile_preference_toolbar),
DEVELOPMENT_SETTINGS(DevelopmentSettingsFragment.class.getName(), false, R.xml.development_settings, R.layout.global_preference_toolbar);
public final String fragmentName;
@ -165,7 +165,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
updateTheme();
View view = super.onCreateView(inflater, container, savedInstanceState);
if (view != null) {
if (getPreferenceScreen() != null) {
if (getPreferenceScreen() != null && currentScreenType != null) {
PreferenceManager prefManager = getPreferenceManager();
PreferenceScreen preferenceScreen = prefManager.inflateFromResource(prefManager.getContext(), currentScreenType.preferencesResId, null);
if (prefManager.setPreferences(preferenceScreen)) {
@ -178,6 +178,9 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
createToolbar(inflater, view);
setDivider(null);
view.setBackgroundColor(ContextCompat.getColor(app, getBackgroundColorRes()));
if (Build.VERSION.SDK_INT >= 21) {
AndroidUtils.addStatusBarPadding21v(app, view);
}
}
return view;
}
@ -250,9 +253,6 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
activity.getWindow().setStatusBarColor(ContextCompat.getColor(activity, colorId));
}
}
if (activity instanceof MapActivity) {
((MapActivity) activity).exitFromFullScreen(getView());
}
}
}
}
@ -271,9 +271,6 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
if (!(activity instanceof MapActivity) && statusBarColor != -1) {
activity.getWindow().setStatusBarColor(statusBarColor);
}
if (activity instanceof MapActivity) {
((MapActivity) activity).enterToFullScreen();
}
}
}
}
@ -293,7 +290,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
@ColorRes
public int getStatusBarColorId() {
boolean nightMode = isNightMode();
if (currentScreenType.profileDependent) {
if (isProfileDependent()) {
View view = getView();
if (view != null && Build.VERSION.SDK_INT >= 23 && !nightMode) {
view.setSystemUiVisibility(view.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
@ -314,6 +311,10 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
return false;
}
public boolean isProfileDependent() {
return currentScreenType != null && currentScreenType.profileDependent;
}
@Override
public void onDisplayPreferenceDialog(Preference preference) {
FragmentManager fragmentManager = getFragmentManager();
@ -323,13 +324,13 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
ApplicationMode appMode = getSelectedAppMode();
if (preference instanceof ListPreferenceEx) {
SingleSelectPreferenceBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode, currentScreenType.profileDependent, false);
SingleSelectPreferenceBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode, isProfileDependent(), false);
} else if (preference instanceof SwitchPreferenceEx) {
BooleanPreferenceBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode, currentScreenType.profileDependent);
BooleanPreferenceBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode, isProfileDependent());
} else if (preference instanceof EditTextPreference) {
EditTextPreferenceBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode);
} else if (preference instanceof MultiSelectBooleanPreference) {
MultiSelectPreferencesBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode, currentScreenType.profileDependent);
MultiSelectPreferencesBottomSheet.showInstance(fragmentManager, preference.getKey(), this, false, appMode, isProfileDependent());
} else {
super.onDisplayPreferenceDialog(preference);
}
@ -359,7 +360,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
public void recreate() {
FragmentActivity activity = getActivity();
if (activity != null) {
if (activity != null && currentScreenType != null) {
Fragment fragment = Fragment.instantiate(activity, currentScreenType.fragmentName);
fragment.setArguments(buildArguments());
FragmentManager fm = activity.getSupportFragmentManager();
@ -386,7 +387,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
titleView.setSingleLine(false);
}
boolean enabled = preference.isEnabled();
if (currentScreenType.profileDependent) {
if (isProfileDependent()) {
View cb = holder.itemView.findViewById(R.id.switchWidget);
if (cb == null) {
cb = holder.findViewById(android.R.id.checkbox);
@ -423,22 +424,33 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
AppBarLayout appBarLayout = (AppBarLayout) view.findViewById(R.id.appbar);
ViewCompat.setElevation(appBarLayout, 5.0f);
View toolbarContainer = UiUtilities.getInflater(getActivity(), isNightMode()).inflate(currentScreenType.toolbarResId, appBarLayout);
View toolbarContainer = currentScreenType == null ? null :
UiUtilities.getInflater(getActivity(), isNightMode()).inflate(currentScreenType.toolbarResId, appBarLayout);
TextView toolbarTitle = (TextView) view.findViewById(R.id.toolbar_title);
toolbarTitle.setText(getPreferenceScreen().getTitle());
if (toolbarTitle != null) {
toolbarTitle.setText(getPreferenceScreen().getTitle());
}
TextView toolbarSubtitle = (TextView) view.findViewById(R.id.toolbar_subtitle);
if (toolbarSubtitle != null) {
toolbarSubtitle.setText(getSelectedAppMode().toHumanString());
}
View closeButton = view.findViewById(R.id.close_button);
closeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.onBackPressed();
if (closeButton != null) {
closeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.onBackPressed();
}
}
}
});
View switchProfile = toolbarContainer.findViewById(R.id.profile_button);
});
}
View switchProfile = toolbarContainer == null ? null : toolbarContainer.findViewById(R.id.profile_button);
if (switchProfile != null) {
switchProfile.setContentDescription(getString(R.string.switch_profile));
switchProfile.setOnClickListener(new View.OnClickListener() {
@ -451,6 +463,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
}
}
});
switchProfile.setVisibility(View.GONE);
}
}
@ -487,7 +500,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
}
View profileButton = view.findViewById(R.id.profile_button);
if (profileButton != null) {
if (profileButton != null && currentScreenType != null) {
int toolbarRes = currentScreenType.toolbarResId;
int iconColor = getActiveProfileColor();
int bgColor = UiUtilities.getColorWithAlpha(iconColor, 0.1f);
@ -521,7 +534,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
}
private void updatePreferencesScreen() {
if (getSelectedAppMode() != null) {
if (getSelectedAppMode() != null && currentScreenType != null) {
int resId = currentScreenType.preferencesResId;
if (resId != -1) {
addPreferencesFromResource(resId);

View file

@ -41,6 +41,7 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.openseamapsplugin.NauticalMapsPlugin;
import net.osmand.plus.profiles.ExportImportProfileBottomSheet;
import net.osmand.plus.profiles.SelectCopyAppModeBottomSheet;
import net.osmand.plus.profiles.SelectCopyAppModeBottomSheet.CopyAppModePrefsListener;
import net.osmand.plus.settings.bottomsheets.ResetProfilePrefsBottomSheet;
@ -111,6 +112,11 @@ public class ConfigureProfileFragment extends BaseSettingsFragment implements Co
updateToolbarSwitch();
}
});
View switchProfile = view.findViewById(R.id.profile_button);
if (switchProfile != null) {
switchProfile.setVisibility(View.VISIBLE);
}
}
@Override
@ -395,23 +401,14 @@ public class ConfigureProfileFragment extends BaseSettingsFragment implements Co
ResetProfilePrefsBottomSheet.showInstance(fragmentManager, prefId, this, false, getSelectedAppMode());
}
} else if (EXPORT_PROFILE.equals(prefId)) {
Context ctx = requireContext();
final ApplicationMode profile = getSelectedAppMode();
File tempDir = app.getAppPath(IndexConstants.TEMP_DIR);
if (!tempDir.exists()) {
tempDir.mkdirs();
FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager != null) {
ExportImportProfileBottomSheet.showInstance(
fragmentManager,
ExportImportProfileBottomSheet.State.EXPORT,
this,
getSelectedAppMode());
}
String fileName = profile.toHumanString();
app.getSettingsHelper().exportSettings(tempDir, fileName, new SettingsHelper.SettingsExportListener() {
@Override
public void onSettingsExportFinished(@NonNull File file, boolean succeed) {
if (succeed) {
shareProfile(file, profile);
} else {
app.showToastMessage(R.string.export_profile_failed);
}
}
}, new ProfileSettingsItem(app.getSettings(), profile));
} else if (DELETE_PROFILE.equals(prefId)) {
onDeleteProfileClick();
}

View file

@ -118,6 +118,8 @@ public class MainSettingsFragment extends BaseSettingsFragment {
Bundle bundle = new Bundle();
bundle.putString(DIALOG_TYPE, TYPE_BASE_APP_PROFILE);
dialog.setArguments(bundle);
dialog.setUsedOnMap(false);
dialog.setAppMode(getSelectedAppMode());
if (getActivity() != null) {
getActivity().getSupportFragmentManager().beginTransaction()
.add(dialog, "select_base_profile").commitAllowingStateLoss();

View file

@ -1,12 +1,9 @@
package net.osmand.plus.settings;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.preference.Preference;
import android.support.v7.preference.SwitchPreferenceCompat;
import android.view.LayoutInflater;
import android.view.View;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.OsmandApplication;
@ -51,12 +48,6 @@ public class NavigationFragment extends BaseSettingsFragment {
routingProfileDataObjects = getRoutingProfiles(app);
}
@Override
protected void createToolbar(LayoutInflater inflater, View view) {
super.createToolbar(inflater, view);
view.findViewById(R.id.profile_button).setVisibility(View.GONE);
}
@Override
protected void setupPreferences() {
navigationType = findPreference(NAVIGATION_TYPE);
@ -120,6 +111,7 @@ public class NavigationFragment extends BaseSettingsFragment {
bundle.putString(DIALOG_TYPE, TYPE_NAV_PROFILE);
dialog.setArguments(bundle);
dialog.setUsedOnMap(false);
dialog.setAppMode(getSelectedAppMode());
if (getActivity() != null) {
getActivity().getSupportFragmentManager().beginTransaction()
.add(dialog, "select_nav_type").commitAllowingStateLoss();
@ -256,11 +248,15 @@ public class NavigationFragment extends BaseSettingsFragment {
}
}
public static List<ProfileDataObject> getBaseProfiles(Context ctx) {
public static List<ProfileDataObject> getBaseProfiles(OsmandApplication app) {
List<ProfileDataObject> profiles = new ArrayList<>();
for (ApplicationMode mode : ApplicationMode.getDefaultValues()) {
for (ApplicationMode mode : ApplicationMode.allPossibleValues()) {
if (mode != ApplicationMode.DEFAULT) {
profiles.add(new ProfileDataObject(mode.toHumanString(), mode.getDescription(),
String description = mode.getDescription();
if (Algorithms.isEmpty(description)) {
description = getAppModeDescription(app, mode);
}
profiles.add(new ProfileDataObject(mode.toHumanString(), description,
mode.getStringKey(), mode.getIconRes(), false, mode.getIconColorInfo()));
}
}

View file

@ -251,13 +251,6 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
return !profile.equals(changedProfile);
}
@Override
protected void createToolbar(LayoutInflater inflater, View view) {
super.createToolbar(inflater, view);
View profileIcon = view.findViewById(R.id.profile_button);
profileIcon.setVisibility(View.VISIBLE);
}
@Override
public void onSaveInstanceState(Bundle outState) {
saveState(outState);
@ -327,15 +320,16 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
@Override
public void afterTextChanged(Editable s) {
changedProfile.name = s.toString();
if (hasNameDuplicate()) {
saveButton.setEnabled(false);
profileNameOtfb.setError(app.getString(R.string.profile_alert_duplicate_name_msg), true);
if (nameIsEmpty()) {
disableSaveButtonWithErrorMessage(app.getString(R.string.please_provide_profile_name_message));
} else if (hasNameDuplicate()) {
disableSaveButtonWithErrorMessage(app.getString(R.string.profile_alert_duplicate_name_msg));
} else {
saveButton.setEnabled(true);
}
}
});
if (getSelectedAppMode().equals(ApplicationMode.DEFAULT)) {
if (getSelectedAppMode().equals(ApplicationMode.DEFAULT) && !isNewProfile) {
profileName.setFocusableInTouchMode(false);
profileName.setFocusable(false);
} else {
@ -354,10 +348,12 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
selectNavTypeBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (getSelectedAppMode().isCustomProfile()) {
if (isNewProfile) {
hideKeyboard();
final SelectProfileBottomSheetDialogFragment fragment = new SelectProfileBottomSheetDialogFragment();
Bundle bundle = new Bundle();
fragment.setUsedOnMap(false);
fragment.setAppMode(getSelectedAppMode());
if (getSelectedAppMode() != null) {
bundle.putString(SELECTED_KEY, getSelectedAppMode().getRoutingProfile());
}
@ -638,11 +634,8 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
}
private void setupBaseProfileView(String stringKey) {
for (ApplicationMode am : ApplicationMode.getDefaultValues()) {
if (am.getStringKey().equals(stringKey)) {
baseProfileName.setText(Algorithms.capitalizeFirstLetter(am.toHumanString()));
}
}
ApplicationMode mode = ApplicationMode.valueOfStringKey(stringKey, ApplicationMode.DEFAULT);
baseProfileName.setText(Algorithms.capitalizeFirstLetter(mode.toHumanString()));
}
private boolean saveProfile() {
@ -686,13 +679,22 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
private boolean hasNameDuplicate() {
for (ApplicationMode m : ApplicationMode.allPossibleValues()) {
if (m.toHumanString().equals(changedProfile.name) &&
!m.getStringKey().equals(profile.stringKey)) {
if (m.toHumanString().trim().equals(changedProfile.name.trim()) &&
!m.getStringKey().trim().equals(profile.stringKey.trim())) {
return true;
}
}
return false;
}
private boolean nameIsEmpty() {
return changedProfile.name.trim().equals("");
}
private void disableSaveButtonWithErrorMessage(String errorMessage) {
saveButton.setEnabled(false);
profileNameOtfb.setError(errorMessage, true);
}
public boolean isProfileAppearanceChanged(final MapActivity mapActivity) {
hideKeyboard();

View file

@ -24,7 +24,7 @@ public abstract class BasePreferenceBottomSheet extends MenuBottomSheetDialogFra
private ApplicationMode appMode;
private boolean profileDependent;
protected void setAppMode(ApplicationMode appMode) {
public void setAppMode(ApplicationMode appMode) {
this.appMode = appMode;
}

View file

@ -1,9 +1,6 @@
package net.osmand.plus.widgets;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;
@ -91,6 +88,13 @@ public class OsmandTextFieldBoxes extends TextFieldBoxes {
return editText;
}
@Override
protected void makeCursorBlink() {
CharSequence hintCache = this.editText.getHint();
this.editText.setHint(" ");
this.editText.setHint(hintCache);
}
@Override
public void setError(String errorText, boolean giveFocus) {
super.setError(errorText, giveFocus);