Merge pull request #10733 from osmandapp/master

update test branch
This commit is contained in:
Hardy 2021-02-01 18:49:37 +01:00 committed by GitHub
commit 8c34f24f54
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 770 additions and 567 deletions

View file

@ -8,6 +8,7 @@ import net.osmand.aidlapi.AidlParams;
import net.osmand.aidlapi.profile.AExportSettingsType; import net.osmand.aidlapi.profile.AExportSettingsType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import static net.osmand.aidlapi.profile.ExportProfileParams.SETTINGS_TYPE_KEY; import static net.osmand.aidlapi.profile.ExportProfileParams.SETTINGS_TYPE_KEY;
@ -15,17 +16,17 @@ public class ProfileSettingsParams extends AidlParams {
public static final String VERSION_KEY = "version"; public static final String VERSION_KEY = "version";
public static final String REPLACE_KEY = "replace"; public static final String REPLACE_KEY = "replace";
public static final String SILENT_IMPORT_KEY = "silent_import"; public static final String SILENT_IMPORT_KEY = "silentImport";
public static final String LATEST_CHANGES_KEY = "latestChanges"; public static final String LATEST_CHANGES_KEY = "latestChanges";
public static final String PROFILE_SETTINGS_URI_KEY = "profileSettingsUri"; public static final String PROFILE_SETTINGS_URI_KEY = "profileSettingsUri";
private Uri profileSettingsUri; private Uri profileSettingsUri;
private String latestChanges; private String latestChanges;
private int version; private int version;
private ArrayList<String> settingsTypeKeyList = new ArrayList<>(); private List<String> settingsTypeKeyList = new ArrayList<>();
private boolean silent; private boolean silent;
private boolean replace; private boolean replace;
public ProfileSettingsParams(Uri profileSettingsUri, ArrayList<AExportSettingsType> settingsTypeList, boolean replace, public ProfileSettingsParams(Uri profileSettingsUri, List<AExportSettingsType> settingsTypeList, boolean replace,
boolean silent, String latestChanges, int version) { boolean silent, String latestChanges, int version) {
this.profileSettingsUri = profileSettingsUri; this.profileSettingsUri = profileSettingsUri;
for (AExportSettingsType settingsType : settingsTypeList) { for (AExportSettingsType settingsType : settingsTypeList) {
@ -65,7 +66,7 @@ public class ProfileSettingsParams extends AidlParams {
return profileSettingsUri; return profileSettingsUri;
} }
public ArrayList<String> getSettingsTypeKeys() { public List<String> getSettingsTypeKeys() {
return settingsTypeKeyList; return settingsTypeKeyList;
} }
@ -82,7 +83,7 @@ public class ProfileSettingsParams extends AidlParams {
bundle.putInt(VERSION_KEY, version); bundle.putInt(VERSION_KEY, version);
bundle.putString(LATEST_CHANGES_KEY, latestChanges); bundle.putString(LATEST_CHANGES_KEY, latestChanges);
bundle.putParcelable(PROFILE_SETTINGS_URI_KEY, profileSettingsUri); bundle.putParcelable(PROFILE_SETTINGS_URI_KEY, profileSettingsUri);
bundle.putStringArrayList(SETTINGS_TYPE_KEY, settingsTypeKeyList); bundle.putStringArrayList(SETTINGS_TYPE_KEY, new ArrayList<>(settingsTypeKeyList));
bundle.putBoolean(REPLACE_KEY, replace); bundle.putBoolean(REPLACE_KEY, replace);
bundle.putBoolean(SILENT_IMPORT_KEY, silent); bundle.putBoolean(SILENT_IMPORT_KEY, silent);
} }

View file

@ -140,7 +140,7 @@ public class TurnType {
r.setTurnAngle(angle); r.setTurnAngle(angle);
return r; return r;
} }
private TurnType(int vl) { private TurnType(int vl) {
this.value = vl; this.value = vl;
@ -156,6 +156,10 @@ public class TurnType {
return value == RNLB || value == TRU; return value == RNLB || value == TRU;
} }
public void setExitOut(int exitOut) {
this.exitOut = exitOut;
}
public void setTurnAngle(float turnAngle) { public void setTurnAngle(float turnAngle) {
this.turnAngle = turnAngle; this.turnAngle = turnAngle;
} }

View file

@ -668,8 +668,13 @@ public class MapUtils {
public static boolean areLatLonEqual(Location l1, Location l2) { public static boolean areLatLonEqual(Location l1, Location l2) {
return l1 == null && l2 == null return l1 == null && l2 == null
|| (l1 != null && l2 != null && Math.abs(l1.getLatitude() - l2.getLatitude()) < 0.00001 || (l2 != null && areLatLonEqual(l1, l2.getLatitude(), l2.getLongitude()));
&& Math.abs(l1.getLongitude() - l2.getLongitude()) < 0.00001); }
public static boolean areLatLonEqual(Location l, double lat, double lon) {
return l != null
&& Math.abs(l.getLatitude() - lat) < 0.00001
&& Math.abs(l.getLongitude() - lon) < 0.00001;
} }
public static LatLon rhumbDestinationPoint(LatLon latLon, double distance, double bearing){ public static LatLon rhumbDestinationPoint(LatLon latLon, double distance, double bearing){

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/center_button_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/tab_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/altitude" />
</FrameLayout>

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/custom_radio_buttons" android:id="@+id/custom_radio_buttons"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -13,59 +12,22 @@
android:orientation="horizontal" android:orientation="horizontal"
tools:showIn="@layout/fragment_route_between_points_bottom_sheet_dialog"> tools:showIn="@layout/fragment_route_between_points_bottom_sheet_dialog">
<FrameLayout <include
android:id="@+id/left_button_container" layout="@layout/left_button_container"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1"> android:layout_weight="1" />
<net.osmand.plus.widgets.TextViewEx <include
android:id="@+id/left_button" layout="@layout/center_button_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/shared_string_left"/>
</FrameLayout>
<FrameLayout
android:id="@+id/center_button_container"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1" />
android:visibility="gone">
<net.osmand.plus.widgets.TextViewEx <include
android:id="@+id/center_button" layout="@layout/right_button_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/position_on_map_center"/>
</FrameLayout>
<FrameLayout
android:id="@+id/right_button_container"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1"> android:layout_weight="1" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/right_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/shared_string_right"/>
</FrameLayout>
</LinearLayout> </LinearLayout>

View file

@ -1,24 +1,32 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
android:orientation="vertical" android:layout_height="wrap_content"
android:layout_width="match_parent" android:orientation="vertical">
android:layout_height="wrap_content">
<include layout="@layout/list_item_divider"/> <include layout="@layout/list_item_divider" />
<net.osmand.plus.views.controls.PagerSlidingTabStrip <LinearLayout
android:id="@+id/sliding_tabs" android:layout_width="match_parent"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_height="48dp" android:background="?attr/bg_color"
android:background="?attr/bg_color"/> android:orientation="vertical">
<net.osmand.plus.views.controls.PagerSlidingTabStrip
android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:minHeight="@dimen/dialog_button_height"
android:paddingTop="@dimen/content_padding" />
<net.osmand.plus.views.controls.WrapContentHeightViewPager <net.osmand.plus.views.controls.WrapContentHeightViewPager
android:id="@+id/pager" android:id="@+id/pager"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/bg_color" android:paddingTop="4dp" />
android:paddingTop="4dp"/>
</LinearLayout>
</LinearLayout> </LinearLayout>

View file

@ -10,43 +10,59 @@
android:orientation="horizontal"> android:orientation="horizontal">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginEnd="@dimen/content_padding" android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding" android:layout_marginRight="@dimen/content_padding"
android:gravity="center_vertical"
android:maxWidth="@dimen/grid_menu_item_width"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:gravity="center_vertical"
android:orientation="horizontal"
android:weightSum="2">
<net.osmand.plus.widgets.TextViewEx <net.osmand.plus.widgets.TextViewEx
android:id="@+id/value" android:id="@+id/value"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:layout_weight="1"
android:background="@null" android:background="@null"
android:lines="1"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_desc_text_size" android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" osmand:typeface="@string/font_roboto_medium"
tools:text="700 km" /> tools:text="700 km" />
<androidx.appcompat.widget.AppCompatImageView <FrameLayout
android:id="@+id/image" android:layout_width="wrap_content"
android:layout_width="@dimen/context_menu_transport_icon_size" android:layout_height="match_parent"
android:layout_height="@dimen/context_menu_transport_icon_size" android:layout_marginStart="@dimen/content_padding_half"
android:layout_gravity="center_vertical" android:layout_marginLeft="@dimen/content_padding_half"
android:layout_marginStart="@dimen/context_menu_first_line_top_margin" android:layout_weight="1">
android:layout_marginLeft="@dimen/context_menu_first_line_top_margin"
tools:src="@drawable/ic_action_track_16" /> <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/image"
android:layout_width="@dimen/context_menu_transport_icon_size"
android:layout_height="@dimen/context_menu_transport_icon_size"
android:layout_gravity="center_vertical|end"
tools:src="@drawable/ic_action_track_16" />
</FrameLayout>
</LinearLayout> </LinearLayout>
<TextView <TextView
android:id="@+id/title" android:id="@+id/title"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@null" android:background="@null"
android:ellipsize="end"
android:lines="1"
android:maxWidth="@dimen/grid_menu_item_width"
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/default_desc_text_size" android:textSize="@dimen/default_desc_text_size"
tools:text="@string/distance" /> tools:text="@string/distance" />

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/left_button_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/tab_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/shared_string_overview" />
</FrameLayout>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/right_button_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/tab_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/map_widget_speed" />
</FrameLayout>

View file

@ -2296,11 +2296,11 @@ public class OsmandAidlApi {
return false; return false;
} }
public boolean importProfileV2(final Uri profileUri, ArrayList<String> settingsTypeKeys, boolean replace, public boolean importProfileV2(final Uri profileUri, List<String> settingsTypeKeys, boolean replace,
boolean silent, String latestChanges, int version) { boolean silent, String latestChanges, int version) {
if (profileUri != null) { if (profileUri != null) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putStringArrayList(SettingsHelper.SETTINGS_TYPE_LIST_KEY, settingsTypeKeys); bundle.putStringArrayList(SettingsHelper.SETTINGS_TYPE_LIST_KEY, new ArrayList<>(settingsTypeKeys));
bundle.putBoolean(REPLACE_KEY, replace); bundle.putBoolean(REPLACE_KEY, replace);
bundle.putBoolean(SILENT_IMPORT_KEY, silent); bundle.putBoolean(SILENT_IMPORT_KEY, silent);
bundle.putString(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY, latestChanges); bundle.putString(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY, latestChanges);

View file

@ -87,6 +87,7 @@ public class UiUtilities {
public enum CustomRadioButtonType { public enum CustomRadioButtonType {
START, START,
CENTER,
END, END,
} }
@ -454,10 +455,10 @@ public class UiUtilities {
int radius = AndroidUtils.dpToPx(app, 4); int radius = AndroidUtils.dpToPx(app, 4);
boolean isLayoutRtl = AndroidUtils.isLayoutRtl(app); boolean isLayoutRtl = AndroidUtils.isLayoutRtl(app);
TextView startButtonText = buttonsView.findViewById(R.id.left_button);
View startButtonContainer = buttonsView.findViewById(R.id.left_button_container); View startButtonContainer = buttonsView.findViewById(R.id.left_button_container);
TextView endButtonText = buttonsView.findViewById(R.id.right_button); View centerButtonContainer = buttonsView.findViewById(R.id.center_button_container);
View endButtonContainer = buttonsView.findViewById(R.id.right_button_container); View endButtonContainer = buttonsView.findViewById(R.id.right_button_container);
GradientDrawable background = new GradientDrawable(); GradientDrawable background = new GradientDrawable();
background.setColor(UiUtilities.getColorWithAlpha(activeColor, 0.1f)); background.setColor(UiUtilities.getColorWithAlpha(activeColor, 0.1f));
background.setStroke(AndroidUtils.dpToPx(app, 1), UiUtilities.getColorWithAlpha(activeColor, 0.5f)); background.setStroke(AndroidUtils.dpToPx(app, 1), UiUtilities.getColorWithAlpha(activeColor, 0.5f));
@ -467,20 +468,54 @@ public class UiUtilities {
} else { } else {
background.setCornerRadii(new float[]{radius, radius, 0, 0, 0, 0, radius, radius}); background.setCornerRadii(new float[]{radius, radius, 0, 0, 0, 0, radius, radius});
} }
TextView startButtonText = startButtonContainer.findViewById(R.id.tab_title);
TextView endButtonText = endButtonContainer.findViewById(R.id.tab_title);
endButtonContainer.setBackgroundColor(Color.TRANSPARENT); endButtonContainer.setBackgroundColor(Color.TRANSPARENT);
endButtonText.setTextColor(activeColor); endButtonText.setTextColor(activeColor);
startButtonContainer.setBackgroundDrawable(background); startButtonContainer.setBackgroundDrawable(background);
startButtonText.setTextColor(textColor); startButtonText.setTextColor(textColor);
if (centerButtonContainer != null) {
TextView centerButtonText = centerButtonContainer.findViewById(R.id.tab_title);
centerButtonText.setTextColor(activeColor);
centerButtonContainer.setBackgroundColor(Color.TRANSPARENT);
}
} else if (buttonType == CustomRadioButtonType.CENTER) {
background.setCornerRadii(new float[] {0, 0, 0, 0, 0, 0, 0, 0});
centerButtonContainer.setBackgroundDrawable(background);
TextView centerButtonText = centerButtonContainer.findViewById(R.id.tab_title);
centerButtonText.setTextColor(textColor);
if (endButtonContainer != null) {
TextView endButtonText = endButtonContainer.findViewById(R.id.tab_title);
endButtonText.setTextColor(activeColor);
endButtonContainer.setBackgroundColor(Color.TRANSPARENT);
}
if (startButtonContainer != null) {
TextView startButtonText = startButtonContainer.findViewById(R.id.tab_title);
startButtonText.setTextColor(activeColor);
startButtonContainer.setBackgroundColor(Color.TRANSPARENT);
}
} else { } else {
if (isLayoutRtl) { if (isLayoutRtl) {
background.setCornerRadii(new float[]{radius, radius, 0, 0, 0, 0, radius, radius}); background.setCornerRadii(new float[] {radius, radius, 0, 0, 0, 0, radius, radius});
} else { } else {
background.setCornerRadii(new float[]{0, 0, radius, radius, radius, radius, 0, 0}); background.setCornerRadii(new float[]{0, 0, radius, radius, radius, radius, 0, 0});
} }
TextView startButtonText = startButtonContainer.findViewById(R.id.tab_title);
TextView endButtonText = endButtonContainer.findViewById(R.id.tab_title);
endButtonContainer.setBackgroundDrawable(background); endButtonContainer.setBackgroundDrawable(background);
endButtonText.setTextColor(textColor); endButtonText.setTextColor(textColor);
startButtonContainer.setBackgroundColor(Color.TRANSPARENT); startButtonContainer.setBackgroundColor(Color.TRANSPARENT);
startButtonText.setTextColor(activeColor); startButtonText.setTextColor(activeColor);
if (centerButtonContainer != null) {
TextView centerButtonText = centerButtonContainer.findViewById(R.id.tab_title);
centerButtonText.setTextColor(activeColor);
centerButtonContainer.setBackgroundColor(Color.TRANSPARENT);
}
} }
} }

View file

@ -651,7 +651,9 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
protected void onNewIntent(final Intent intent) { protected void onNewIntent(final Intent intent) {
super.onNewIntent(intent); super.onNewIntent(intent);
setIntent(intent); setIntent(intent);
intentHelper.parseLaunchIntents(); if (!intentHelper.parseLaunchIntents()) {
intentHelper.parseContentIntent();
}
} }
@Override @Override

View file

@ -38,10 +38,10 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
public class SavingTrackHelper extends SQLiteOpenHelper { public class SavingTrackHelper extends SQLiteOpenHelper {
public final static String DATABASE_NAME = "tracks"; //$NON-NLS-1$ public final static String DATABASE_NAME = "tracks"; //$NON-NLS-1$
public final static int DATABASE_VERSION = 6; public final static int DATABASE_VERSION = 7;
public final static String TRACK_NAME = "track"; //$NON-NLS-1$ public final static String TRACK_NAME = "track"; //$NON-NLS-1$
public final static String TRACK_COL_DATE = "date"; //$NON-NLS-1$ public final static String TRACK_COL_DATE = "date"; //$NON-NLS-1$
public final static String TRACK_COL_LAT = "lat"; //$NON-NLS-1$ public final static String TRACK_COL_LAT = "lat"; //$NON-NLS-1$
@ -50,7 +50,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
public final static String TRACK_COL_SPEED = "speed"; //$NON-NLS-1$ public final static String TRACK_COL_SPEED = "speed"; //$NON-NLS-1$
public final static String TRACK_COL_HDOP = "hdop"; //$NON-NLS-1$ public final static String TRACK_COL_HDOP = "hdop"; //$NON-NLS-1$
public final static String TRACK_COL_HEADING = "heading"; //$NON-NLS-1$ public final static String TRACK_COL_HEADING = "heading"; //$NON-NLS-1$
public final static String POINT_NAME = "point"; //$NON-NLS-1$ public final static String POINT_NAME = "point"; //$NON-NLS-1$
public final static String POINT_COL_DATE = "date"; //$NON-NLS-1$ public final static String POINT_COL_DATE = "date"; //$NON-NLS-1$
public final static String POINT_COL_LAT = "lat"; //$NON-NLS-1$ public final static String POINT_COL_LAT = "lat"; //$NON-NLS-1$
@ -59,7 +59,9 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
public final static String POINT_COL_CATEGORY = "category"; //$NON-NLS-1$ public final static String POINT_COL_CATEGORY = "category"; //$NON-NLS-1$
public final static String POINT_COL_DESCRIPTION = "description"; //$NON-NLS-1$ public final static String POINT_COL_DESCRIPTION = "description"; //$NON-NLS-1$
public final static String POINT_COL_COLOR = "color"; //$NON-NLS-1$ public final static String POINT_COL_COLOR = "color"; //$NON-NLS-1$
public final static String POINT_COL_ICON = "icon"; //$NON-NLS-1$
public final static String POINT_COL_BACKGROUND = "background"; //$NON-NLS-1$
public final static float NO_HEADING = -1.0f; public final static float NO_HEADING = -1.0f;
public final static Log log = PlatformUtil.getLog(SavingTrackHelper.class); public final static Log log = PlatformUtil.getLog(SavingTrackHelper.class);
@ -76,8 +78,8 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
private SelectedGpxFile currentTrack; private SelectedGpxFile currentTrack;
private int points; private int points;
private int trkPoints = 0; private int trkPoints = 0;
public SavingTrackHelper(OsmandApplication ctx){ public SavingTrackHelper(OsmandApplication ctx) {
super(ctx, DATABASE_NAME, null, DATABASE_VERSION); super(ctx, DATABASE_NAME, null, DATABASE_VERSION);
this.ctx = ctx; this.ctx = ctx;
this.currentTrack = new SelectedGpxFile(); this.currentTrack = new SelectedGpxFile();
@ -88,11 +90,14 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
prepareCurrentTrackForRecording(); prepareCurrentTrackForRecording();
updateScript = "INSERT INTO " + TRACK_NAME + " (" + TRACK_COL_LAT + ", " + TRACK_COL_LON + ", " updateScript = "INSERT INTO " + TRACK_NAME + " (" + TRACK_COL_LAT + ", " + TRACK_COL_LON + ", "
+ TRACK_COL_ALTITUDE + ", " + TRACK_COL_SPEED + ", " + TRACK_COL_HDOP + ", " + TRACK_COL_ALTITUDE + ", " + TRACK_COL_SPEED + ", " + TRACK_COL_HDOP + ", "
+ TRACK_COL_DATE + ", " + TRACK_COL_HEADING + ")" + TRACK_COL_DATE + ", " + TRACK_COL_HEADING + ")"
+ " VALUES (?, ?, ?, ?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$ + " VALUES (?, ?, ?, ?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$
insertPointsScript = "INSERT INTO " + POINT_NAME + " VALUES (?, ?, ?, ?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$ insertPointsScript = "INSERT INTO " + POINT_NAME + " (" + POINT_COL_LAT + ", " + POINT_COL_LON + ", "
+ POINT_COL_DATE + ", " + POINT_COL_DESCRIPTION + ", " + POINT_COL_NAME + ", "
+ POINT_COL_CATEGORY + ", " + POINT_COL_COLOR + ", " + POINT_COL_ICON + ", "
+ POINT_COL_BACKGROUND + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$
} }
@Override @Override
@ -100,19 +105,19 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
createTableForTrack(db); createTableForTrack(db);
createTableForPoints(db); createTableForPoints(db);
} }
private void createTableForTrack(SQLiteDatabase db){ private void createTableForTrack(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TRACK_NAME + " (" + TRACK_COL_LAT + " double, " + TRACK_COL_LON + " double, " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ db.execSQL("CREATE TABLE " + TRACK_NAME + " (" + TRACK_COL_LAT + " double, " + TRACK_COL_LON + " double, " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ TRACK_COL_ALTITUDE + " double, " + TRACK_COL_SPEED + " double, " //$NON-NLS-1$ //$NON-NLS-2$ + TRACK_COL_ALTITUDE + " double, " + TRACK_COL_SPEED + " double, " //$NON-NLS-1$ //$NON-NLS-2$
+ TRACK_COL_HDOP + " double, " + TRACK_COL_DATE + " long, " + TRACK_COL_HDOP + " double, " + TRACK_COL_DATE + " long, "
+ TRACK_COL_HEADING + " float )"); //$NON-NLS-1$ //$NON-NLS-2$ + TRACK_COL_HEADING + " float )"); //$NON-NLS-1$ //$NON-NLS-2$
} }
private void createTableForPoints(SQLiteDatabase db){ private void createTableForPoints(SQLiteDatabase db) {
try { try {
db.execSQL("CREATE TABLE " + POINT_NAME + " (" + POINT_COL_LAT + " double, " + POINT_COL_LON + " double, " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ db.execSQL("CREATE TABLE " + POINT_NAME + " (" + POINT_COL_LAT + " double, " + POINT_COL_LON + " double, " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ POINT_COL_DATE + " long, " + POINT_COL_DESCRIPTION + " text, " + POINT_COL_NAME + " text, " + POINT_COL_DATE + " long, " + POINT_COL_DESCRIPTION + " text, " + POINT_COL_NAME + " text, "
+ POINT_COL_CATEGORY + " text, " + POINT_COL_COLOR + " long" + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + POINT_COL_CATEGORY + " text, " + POINT_COL_COLOR + " long, " + POINT_COL_ICON + " text, " + POINT_COL_BACKGROUND + " text )"); //$NON-NLS-1$ //$NON-NLS-2$
} catch (RuntimeException e) { } catch (RuntimeException e) {
// ignore if already exists // ignore if already exists
} }
@ -120,25 +125,29 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
@Override @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(oldVersion < 2){ if (oldVersion < 2) {
createTableForPoints(db); createTableForPoints(db);
} }
if(oldVersion < 3){ if (oldVersion < 3) {
db.execSQL("ALTER TABLE " + TRACK_NAME + " ADD " + TRACK_COL_HDOP + " double"); db.execSQL("ALTER TABLE " + TRACK_NAME + " ADD " + TRACK_COL_HDOP + " double");
} }
if(oldVersion < 4){ if (oldVersion < 4) {
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_NAME + " text"); db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_NAME + " text");
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_CATEGORY + " text"); db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_CATEGORY + " text");
} }
if(oldVersion < 5){ if (oldVersion < 5) {
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_COLOR + " long"); db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_COLOR + " long");
} }
if(oldVersion < 6){ if (oldVersion < 6) {
db.execSQL("ALTER TABLE " + TRACK_NAME + " ADD " + TRACK_COL_HEADING + " float"); db.execSQL("ALTER TABLE " + TRACK_NAME + " ADD " + TRACK_COL_HEADING + " float");
}
if (oldVersion < 7) {
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_ICON + " text");
db.execSQL("ALTER TABLE " + POINT_NAME + " ADD " + POINT_COL_BACKGROUND + " text");
} }
} }
public long getLastTrackPointTime() { public long getLastTrackPointTime() {
long res = 0; long res = 0;
try { try {
@ -146,7 +155,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
if (db != null) { if (db != null) {
try { try {
Cursor query = db.rawQuery("SELECT " + TRACK_COL_DATE + " FROM " + TRACK_NAME + " ORDER BY " + TRACK_COL_DATE + " DESC", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ Cursor query = db.rawQuery("SELECT " + TRACK_COL_DATE + " FROM " + TRACK_NAME + " ORDER BY " + TRACK_COL_DATE + " DESC", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if(query.moveToFirst()) { if (query.moveToFirst()) {
res = query.getLong(0); res = query.getLong(0);
} }
query.close(); query.close();
@ -154,11 +163,11 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
db.close(); db.close();
} }
} }
} catch(RuntimeException e) { } catch (RuntimeException e) {
} }
return res; return res;
} }
public synchronized boolean hasDataToSave() { public synchronized boolean hasDataToSave() {
try { try {
SQLiteDatabase db = getWritableDatabase(); SQLiteDatabase db = getWritableDatabase();
@ -172,11 +181,11 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
} }
q = db.query(false, POINT_NAME, new String[]{POINT_COL_LAT, POINT_COL_LON}, null, null, null, null, null, null); q = db.query(false, POINT_NAME, new String[]{POINT_COL_LAT, POINT_COL_LON}, null, null, null, null, null, null);
has = q.moveToFirst(); has = q.moveToFirst();
while(has) { while (has) {
if(q.getDouble(0) != 0 || q.getDouble(1) != 0) { if (q.getDouble(0) != 0 || q.getDouble(1) != 0) {
break; break;
} }
if(!q.moveToNext()) { if (!q.moveToNext()) {
has = false; has = false;
break; break;
} }
@ -189,7 +198,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
db.close(); db.close();
} }
} }
} catch(RuntimeException e) { } catch (RuntimeException e) {
return false; return false;
} }
@ -294,7 +303,8 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
private void collectDBPoints(SQLiteDatabase db, Map<String, GPXFile> dataTracks) { private void collectDBPoints(SQLiteDatabase db, Map<String, GPXFile> dataTracks) {
Cursor query = db.rawQuery("SELECT " + POINT_COL_LAT + "," + POINT_COL_LON + "," + POINT_COL_DATE + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ Cursor query = db.rawQuery("SELECT " + POINT_COL_LAT + "," + POINT_COL_LON + "," + POINT_COL_DATE + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ POINT_COL_DESCRIPTION + "," + POINT_COL_NAME + "," + POINT_COL_CATEGORY + "," + POINT_COL_COLOR + " FROM " + POINT_NAME+" ORDER BY " + POINT_COL_DATE +" ASC", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + POINT_COL_DESCRIPTION + "," + POINT_COL_NAME + "," + POINT_COL_CATEGORY + "," + POINT_COL_COLOR + ","
+ POINT_COL_ICON + "," + POINT_COL_BACKGROUND + " FROM " + POINT_NAME + " ORDER BY " + POINT_COL_DATE + " ASC", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if (query.moveToFirst()) { if (query.moveToFirst()) {
do { do {
WptPt pt = new WptPt(); WptPt pt = new WptPt();
@ -309,18 +319,20 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
if (color != 0) { if (color != 0) {
pt.setColor(color); pt.setColor(color);
} }
pt.setIconName(query.getString(7));
pt.setBackgroundType(query.getString(8));
// check if name is extension (needed for audio/video plugin & josm integration) // check if name is extension (needed for audio/video plugin & josm integration)
if(pt.name != null && pt.name.length() > 4 && pt.name.charAt(pt.name.length() - 4) == '.') { if (pt.name != null && pt.name.length() > 4 && pt.name.charAt(pt.name.length() - 4) == '.') {
pt.link = pt.name; pt.link = pt.name;
} }
String date = DateFormat.format("yyyy-MM-dd", time).toString(); //$NON-NLS-1$ String date = DateFormat.format("yyyy-MM-dd", time).toString(); //$NON-NLS-1$
GPXFile gpx; GPXFile gpx;
if (dataTracks.containsKey(date)) { if (dataTracks.containsKey(date)) {
gpx = dataTracks.get(date); gpx = dataTracks.get(date);
} else { } else {
gpx = new GPXFile(Version.getFullVersion(ctx)); gpx = new GPXFile(Version.getFullVersion(ctx));
dataTracks.put(date, gpx); dataTracks.put(date, gpx);
} }
ctx.getSelectedGpxHelper().addPoint(pt, gpx); ctx.getSelectedGpxHelper().addPoint(pt, gpx);
@ -329,10 +341,10 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
} }
query.close(); query.close();
} }
private void collectDBTracks(SQLiteDatabase db, Map<String, GPXFile> dataTracks) { private void collectDBTracks(SQLiteDatabase db, Map<String, GPXFile> dataTracks) {
Cursor query = db.rawQuery("SELECT " + TRACK_COL_LAT + "," + TRACK_COL_LON + "," + TRACK_COL_ALTITUDE + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ Cursor query = db.rawQuery("SELECT " + TRACK_COL_LAT + "," + TRACK_COL_LON + "," + TRACK_COL_ALTITUDE + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ TRACK_COL_SPEED + "," + TRACK_COL_HDOP + "," + TRACK_COL_DATE + "," + TRACK_COL_HEADING + " FROM " + TRACK_NAME +" ORDER BY " + TRACK_COL_DATE +" ASC", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + TRACK_COL_SPEED + "," + TRACK_COL_HDOP + "," + TRACK_COL_DATE + "," + TRACK_COL_HEADING + " FROM " + TRACK_NAME + " ORDER BY " + TRACK_COL_DATE + " ASC", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
long previousTime = 0; long previousTime = 0;
long previousInterval = 0; long previousInterval = 0;
TrkSegment segment = null; TrkSegment segment = null;
@ -351,14 +363,14 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
pt.heading = heading == NO_HEADING ? Float.NaN : heading; pt.heading = heading == NO_HEADING ? Float.NaN : heading;
long currentInterval = Math.abs(time - previousTime); long currentInterval = Math.abs(time - previousTime);
boolean newInterval = pt.lat == 0 && pt.lon == 0; boolean newInterval = pt.lat == 0 && pt.lon == 0;
if (track != null && !newInterval && (!ctx.getSettings().AUTO_SPLIT_RECORDING.get() || currentInterval < 6 * 60 * 1000 || currentInterval < 10 * previousInterval)) { if (track != null && !newInterval && (!ctx.getSettings().AUTO_SPLIT_RECORDING.get() || currentInterval < 6 * 60 * 1000 || currentInterval < 10 * previousInterval)) {
// 6 minute - same segment // 6 minute - same segment
segment.points.add(pt); segment.points.add(pt);
} else if (track != null && (ctx.getSettings().AUTO_SPLIT_RECORDING.get() && currentInterval < 2 * 60 * 60 * 1000)) { } else if (track != null && (ctx.getSettings().AUTO_SPLIT_RECORDING.get() && currentInterval < 2 * 60 * 60 * 1000)) {
// 2 hour - same track // 2 hour - same track
segment = new TrkSegment(); segment = new TrkSegment();
if(!newInterval) { if (!newInterval) {
segment.points.add(pt); segment.points.add(pt);
} }
track.segments.add(segment); track.segments.add(segment);
@ -367,10 +379,10 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
track = new Track(); track = new Track();
segment = new TrkSegment(); segment = new TrkSegment();
track.segments.add(segment); track.segments.add(segment);
if(!newInterval) { if (!newInterval) {
segment.points.add(pt); segment.points.add(pt);
} }
String date = new SimpleDateFormat("yyyy-MM-dd", Locale.US).format(new Date(time));; //$NON-NLS-1$ String date = new SimpleDateFormat("yyyy-MM-dd", Locale.US).format(new Date(time)); //$NON-NLS-1$
if (dataTracks.containsKey(date)) { if (dataTracks.containsKey(date)) {
GPXFile gpx = dataTracks.get(date); GPXFile gpx = dataTracks.get(date);
gpx.tracks.add(track); gpx.tracks.add(track);
@ -411,14 +423,14 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
dataTracks.remove(date); dataTracks.remove(date);
} }
} }
public void startNewSegment() { public void startNewSegment() {
lastTimeUpdated = 0; lastTimeUpdated = 0;
lastPoint = null; lastPoint = null;
execWithClose(updateScript, new Object[] { 0, 0, 0, 0, 0, System.currentTimeMillis(), NO_HEADING}); execWithClose(updateScript, new Object[]{0, 0, 0, 0, 0, System.currentTimeMillis(), NO_HEADING});
addTrackPoint(null, true, System.currentTimeMillis()); addTrackPoint(null, true, System.currentTimeMillis());
} }
public void updateLocation(net.osmand.Location location, Float heading) { public void updateLocation(net.osmand.Location location, Float heading) {
// use because there is a bug on some devices with location.getTime() // use because there is a bug on some devices with location.getTime()
long locationTime = System.currentTimeMillis(); long locationTime = System.currentTimeMillis();
@ -459,12 +471,12 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
ctx.getNotificationHelper().refreshNotification(NotificationType.GPX); ctx.getNotificationHelper().refreshNotification(NotificationType.GPX);
} }
} }
public void insertData(double lat, double lon, double alt, double speed, double hdop, long time, float heading, public void insertData(double lat, double lon, double alt, double speed, double hdop, long time, float heading,
OsmandSettings settings) { OsmandSettings settings) {
// * 1000 in next line seems to be wrong with new IntervalChooseDialog // * 1000 in next line seems to be wrong with new IntervalChooseDialog
// if (time - lastTimeUpdated > settings.SAVE_TRACK_INTERVAL.get() * 1000) { // if (time - lastTimeUpdated > settings.SAVE_TRACK_INTERVAL.get() * 1000) {
execWithClose(updateScript, new Object[] { lat, lon, alt, speed, hdop, time, heading }); execWithClose(updateScript, new Object[]{lat, lon, alt, speed, hdop, time, heading});
boolean newSegment = false; boolean newSegment = false;
if (lastPoint == null || (time - lastTimeUpdated) > 180 * 1000) { if (lastPoint == null || (time - lastTimeUpdated) > 180 * 1000) {
lastPoint = new LatLon(lat, lon); lastPoint = new LatLon(lat, lon);
@ -485,7 +497,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
addTrackPoint(pt, newSegment, time); addTrackPoint(pt, newSegment, time);
trkPoints++; trkPoints++;
} }
private void addTrackPoint(WptPt pt, boolean newSegment, long time) { private void addTrackPoint(WptPt pt, boolean newSegment, long time) {
List<TrkSegment> points = currentTrack.getModifiablePointsToDisplay(); List<TrkSegment> points = currentTrack.getModifiablePointsToDisplay();
Track track = currentTrack.getModifiableGpxFile().tracks.get(0); Track track = currentTrack.getModifiableGpxFile().tracks.get(0);
@ -511,12 +523,12 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
} }
public WptPt insertPointData(double lat, double lon, long time, String description, String name, String category, public WptPt insertPointData(double lat, double lon, long time, String description, String name, String category,
int color) { int color) {
return insertPointData(lat, lon, time, description, name, category, color, null, null); return insertPointData(lat, lon, time, description, name, category, color, null, null);
} }
public WptPt insertPointData(double lat, double lon, long time, String description, String name, String category, public WptPt insertPointData(double lat, double lon, long time, String description, String name, String category,
int color, String iconName, String backgroundName) { int color, String iconName, String backgroundName) {
final WptPt pt = new WptPt(lat, lon, time, Double.NaN, 0, Double.NaN); final WptPt pt = new WptPt(lat, lon, time, Double.NaN, 0, Double.NaN);
pt.name = name; pt.name = name;
pt.category = category; pt.category = category;
@ -529,7 +541,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
ctx.getSelectedGpxHelper().addPoint(pt, currentTrack.getModifiableGpxFile()); ctx.getSelectedGpxHelper().addPoint(pt, currentTrack.getModifiableGpxFile());
currentTrack.getModifiableGpxFile().modifiedTime = time; currentTrack.getModifiableGpxFile().modifiedTime = time;
points++; points++;
execWithClose(insertPointsScript, new Object[] { lat, lon, time, description, name, category, color }); execWithClose(insertPointsScript, new Object[]{lat, lon, time, description, name, category, color, iconName, backgroundName});
return pt; return pt;
} }
@ -538,7 +550,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
} }
public void updatePointData(WptPt pt, double lat, double lon, long time, String description, String name, public void updatePointData(WptPt pt, double lat, double lon, long time, String description, String name,
String category, int color, String iconName, String iconBackground) { String category, int color, String iconName, String iconBackground) {
currentTrack.getModifiableGpxFile().modifiedTime = time; currentTrack.getModifiableGpxFile().modifiedTime = time;
List<Object> params = new ArrayList<>(); List<Object> params = new ArrayList<>();
@ -549,6 +561,8 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
params.add(name); params.add(name);
params.add(category); params.add(category);
params.add(color); params.add(color);
params.add(iconName);
params.add(iconBackground);
params.add(pt.getLatitude()); params.add(pt.getLatitude());
params.add(pt.getLongitude()); params.add(pt.getLongitude());
@ -563,7 +577,9 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
+ POINT_COL_DESCRIPTION + "=?, " + POINT_COL_DESCRIPTION + "=?, "
+ POINT_COL_NAME + "=?, " + POINT_COL_NAME + "=?, "
+ POINT_COL_CATEGORY + "=?, " + POINT_COL_CATEGORY + "=?, "
+ POINT_COL_COLOR + "=? " + POINT_COL_COLOR + "=?, "
+ POINT_COL_ICON + "=?, "
+ POINT_COL_BACKGROUND + "=? "
+ "WHERE " + "WHERE "
+ POINT_COL_LAT + "=? AND " + POINT_COL_LAT + "=? AND "
+ POINT_COL_LON + "=? AND " + POINT_COL_LON + "=? AND "
@ -662,10 +678,10 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
} }
} }
public void loadGpxFromDatabase(){ public void loadGpxFromDatabase() {
Map<String, GPXFile> files = collectRecordedData(); Map<String, GPXFile> files = collectRecordedData();
currentTrack.getModifiableGpxFile().tracks.clear(); currentTrack.getModifiableGpxFile().tracks.clear();
for (Map.Entry<String, GPXFile> entry : files.entrySet()){ for (Map.Entry<String, GPXFile> entry : files.entrySet()) {
ctx.getSelectedGpxHelper().addPoints(entry.getValue().getPoints(), currentTrack.getModifiableGpxFile()); ctx.getSelectedGpxHelper().addPoints(entry.getValue().getPoints(), currentTrack.getModifiableGpxFile());
currentTrack.getModifiableGpxFile().tracks.addAll(entry.getValue().tracks); currentTrack.getModifiableGpxFile().tracks.addAll(entry.getValue().tracks);
} }
@ -679,10 +695,10 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
} }
private void prepareCurrentTrackForRecording() { private void prepareCurrentTrackForRecording() {
if(currentTrack.getModifiableGpxFile().tracks.size() == 0) { if (currentTrack.getModifiableGpxFile().tracks.size() == 0) {
currentTrack.getModifiableGpxFile().tracks.add(new Track()); currentTrack.getModifiableGpxFile().tracks.add(new Track());
} }
while(currentTrack.getPointsToDisplay().size() < currentTrack.getModifiableGpxFile().tracks.size()) { while (currentTrack.getPointsToDisplay().size() < currentTrack.getModifiableGpxFile().tracks.size()) {
TrkSegment trkSegment = new TrkSegment(); TrkSegment trkSegment = new TrkSegment();
currentTrack.getModifiablePointsToDisplay().add(trkSegment); currentTrack.getModifiablePointsToDisplay().add(trkSegment);
} }
@ -705,7 +721,7 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
public int getPoints() { public int getPoints() {
return points; return points;
} }
public int getTrkPoints() { public int getTrkPoints() {
return trkPoints; return trkPoints;
} }
@ -717,11 +733,11 @@ public class SavingTrackHelper extends SQLiteOpenHelper {
public GPXFile getCurrentGpx() { public GPXFile getCurrentGpx() {
return currentTrack.getGpxFile(); return currentTrack.getGpxFile();
} }
public SelectedGpxFile getCurrentTrack() { public SelectedGpxFile getCurrentTrack() {
return currentTrack; return currentTrack;
} }
public class SaveGpxResult { public class SaveGpxResult {
public SaveGpxResult(List<String> warnings, List<String> filenames) { public SaveGpxResult(List<String> warnings, List<String> filenames) {

View file

@ -33,6 +33,7 @@ public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragmen
private int progress; private int progress;
private int maxProgress; private int maxProgress;
private boolean uploadingFinished;
@Override @Override
public void createMenuItems(Bundle savedInstanceState) { public void createMenuItems(Bundle savedInstanceState) {
@ -44,17 +45,12 @@ public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragmen
uploadedPhotosCounter = view.findViewById(R.id.description); uploadedPhotosCounter = view.findViewById(R.id.description);
progressBar = view.findViewById(R.id.progress_bar); progressBar = view.findViewById(R.id.progress_bar);
progressBar.setMax(maxProgress); progressBar.setMax(maxProgress);
String titleProgress = getString(progress == maxProgress? R.string.upload_photo_completed: R.string.upload_photo);
String descriptionProgress; int descriptionId = uploadingFinished ? R.string.uploaded_count : R.string.uploading_count;
if (progress == maxProgress) {
descriptionProgress = getString(R.string.uploaded_count, progress, maxProgress);
} else {
descriptionProgress = getString(R.string.uploading_count, progress, maxProgress);
}
BaseBottomSheetItem descriptionItem = new BottomSheetItemWithDescription.Builder() BaseBottomSheetItem descriptionItem = new BottomSheetItemWithDescription.Builder()
.setDescription(descriptionProgress) .setDescription(getString(descriptionId, progress, maxProgress))
.setTitle(titleProgress) .setTitle(getString(uploadingFinished ? R.string.upload_photo_completed : R.string.upload_photo))
.setCustomView(view) .setCustomView(view)
.create(); .create();
items.add(descriptionItem); items.add(descriptionItem);
@ -74,9 +70,10 @@ public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragmen
} }
private void updateProgress(int progress) { private void updateProgress(int progress) {
int descriptionId = uploadingFinished ? R.string.uploaded_count : R.string.uploading_count;
progressBar.setProgress(progress); progressBar.setProgress(progress);
uploadedPhotosCounter.setText((getString(R.string.uploading_count, progress, maxProgress))); uploadedPhotosCounter.setText(getString(descriptionId, progress, maxProgress));
uploadedPhotosTitle.setText(progress == maxProgress ? R.string.upload_photo_completed : R.string.upload_photo); uploadedPhotosTitle.setText(uploadingFinished ? R.string.upload_photo_completed : R.string.upload_photo);
} }
@Override @Override
@ -87,12 +84,9 @@ public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragmen
@Override @Override
public void uploadPhotosFinished() { public void uploadPhotosFinished() {
updateProgress(maxProgress); uploadingFinished = true;
if (progress == maxProgress) { updateProgress(progress);
uploadedPhotosCounter.setText((getString(R.string.uploaded_count, progress, maxProgress))); UiUtilities.setupDialogButton(nightMode, dismissButton, getDismissButtonType(), getDismissButtonTextId());
setDismissButtonTextId(R.string.shared_string_close);
UiUtilities.setupDialogButton(nightMode, dismissButton, getDismissButtonType(), getDismissButtonTextId());
}
} }
@Override @Override
@ -104,6 +98,11 @@ public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragmen
} }
} }
@Override
protected int getDismissButtonTextId() {
return uploadingFinished ? R.string.shared_string_close : R.string.shared_string_cancel;
}
public static UploadPhotosListener showInstance(@NonNull FragmentManager fragmentManager, int maxProgress, OnDismissListener listener) { public static UploadPhotosListener showInstance(@NonNull FragmentManager fragmentManager, int maxProgress, OnDismissListener listener) {
UploadPhotoProgressBottomSheet fragment = new UploadPhotoProgressBottomSheet(); UploadPhotoProgressBottomSheet fragment = new UploadPhotoProgressBottomSheet();
fragment.setRetainInstance(true); fragment.setRetainInstance(true);

View file

@ -102,7 +102,7 @@ class SettingsImportTask extends BaseLoadAsyncTask<Void, Void, String> {
} }
} else { } else {
Map<ExportSettingsType, List<?>> allSettingsMap = getSettingsToOperate(pluginIndependentItems, false); Map<ExportSettingsType, List<?>> allSettingsMap = getSettingsToOperate(pluginIndependentItems, false);
List<SettingsItem> settingsList = settingsHelper.getFilteredSettingsItems(allSettingsMap, settingsTypes, false); List<SettingsItem> settingsList = settingsHelper.getFilteredSettingsItems(allSettingsMap, settingsTypes, pluginIndependentItems, false);
settingsHelper.checkDuplicates(file, settingsList, settingsList, getDuplicatesListener(file, replace)); settingsHelper.checkDuplicates(file, settingsList, settingsList, getDuplicatesListener(file, replace));
} }
} }

View file

@ -34,6 +34,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.InputStream; import java.io.InputStream;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -45,14 +46,13 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
private final OsmandApplication app; private final OsmandApplication app;
private final WeakReference<MapActivity> activityRef; private final WeakReference<MapActivity> activityRef;
private UploadPhotosListener listener;
private final OpenDBAPI openDBAPI = new OpenDBAPI(); private final OpenDBAPI openDBAPI = new OpenDBAPI();
private final LatLon latLon; private final LatLon latLon;
private final List<Uri> data; private final List<Uri> data;
private final String[] placeId; private final String[] placeId;
private final Map<String, String> params; private final Map<String, String> params;
private final GetImageCardsListener imageCardListener; private final GetImageCardsListener imageCardListener;
private UploadPhotosListener listener;
public UploadPhotosAsyncTask(MapActivity activity, List<Uri> data, LatLon latLon, String[] placeId, public UploadPhotosAsyncTask(MapActivity activity, List<Uri> data, LatLon latLon, String[] placeId,
Map<String, String> params, GetImageCardsListener imageCardListener) { Map<String, String> params, GetImageCardsListener imageCardListener) {
@ -87,13 +87,16 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
} }
protected Void doInBackground(Void... uris) { protected Void doInBackground(Void... uris) {
List<Uri> uploadedPhotoUris = new ArrayList<>();
for (int i = 0; i < data.size(); i++) { for (int i = 0; i < data.size(); i++) {
if (isCancelled()) { if (isCancelled()) {
break; break;
} }
Uri uri = data.get(i); Uri uri = data.get(i);
handleSelectedImage(uri); if (handleSelectedImage(uri)) {
publishProgress(i + 1); uploadedPhotoUris.add(uri);
publishProgress(uploadedPhotoUris.size());
}
} }
return null; return null;
} }
@ -105,12 +108,13 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
} }
} }
private void handleSelectedImage(final Uri uri) { private boolean handleSelectedImage(final Uri uri) {
boolean success = false;
InputStream inputStream = null; InputStream inputStream = null;
try { try {
inputStream = app.getContentResolver().openInputStream(uri); inputStream = app.getContentResolver().openInputStream(uri);
if (inputStream != null) { if (inputStream != null) {
uploadImageToPlace(inputStream); success = uploadImageToPlace(inputStream);
} }
} catch (Exception e) { } catch (Exception e) {
LOG.error(e); LOG.error(e);
@ -118,11 +122,13 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
} finally { } finally {
Algorithms.closeStream(inputStream); Algorithms.closeStream(inputStream);
} }
return success;
} }
private void uploadImageToPlace(InputStream image) { private boolean uploadImageToPlace(InputStream image) {
boolean success = false;
InputStream serverData = new ByteArrayInputStream(compressImageToJpeg(image)); InputStream serverData = new ByteArrayInputStream(compressImageToJpeg(image));
final String baseUrl = OPRConstants.getBaseUrl(app); String baseUrl = OPRConstants.getBaseUrl(app);
// all these should be constant // all these should be constant
String url = baseUrl + "api/ipfs/image"; String url = baseUrl + "api/ipfs/image";
String response = NetworkUtils.sendPostDataRequest(url, "file", "compressed.jpeg", serverData); String response = NetworkUtils.sendPostDataRequest(url, "file", "compressed.jpeg", serverData);
@ -140,8 +146,6 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
response, error); response, error);
if (res != 200) { if (res != 200) {
app.showToastMessage(error.toString()); app.showToastMessage(error.toString());
} else {
//ok, continue
} }
} catch (FailedVerificationException e) { } catch (FailedVerificationException e) {
LOG.error(e); LOG.error(e);
@ -151,6 +155,7 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
//image was uploaded but not added to blockchain //image was uploaded but not added to blockchain
checkTokenAndShowScreen(); checkTokenAndShowScreen();
} else { } else {
success = true;
String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1); String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1);
app.showToastMessage(str); app.showToastMessage(str);
//refresh the image //refresh the image
@ -163,6 +168,7 @@ public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
} else { } else {
checkTokenAndShowScreen(); checkTokenAndShowScreen();
} }
return success;
} }
//This method runs on non main thread //This method runs on non main thread

View file

@ -43,7 +43,9 @@ public class SelectedGpxMenuController extends MenuController {
@Override @Override
public void buttonPressed() { public void buttonPressed() {
mapContextMenu.hide(false); mapContextMenu.hide(false);
TrackMenuFragment.showInstance(mapActivity, selectedGpxPoint.getSelectedGpxFile()); WptPt wptPt = selectedGpxPoint.selectedPoint;
LatLon latLon = new LatLon(wptPt.lat, wptPt.lon);
TrackMenuFragment.showInstance(mapActivity, selectedGpxPoint.getSelectedGpxFile(), latLon);
} }
}; };
leftTitleButtonController.caption = mapActivity.getString(R.string.shared_string_open_track); leftTitleButtonController.caption = mapActivity.getString(R.string.shared_string_open_track);

View file

@ -7,6 +7,7 @@ import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
@ -35,6 +36,7 @@ import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.UiUtilities; import net.osmand.plus.UiUtilities;
import net.osmand.plus.UiUtilities.CustomRadioButtonType;
import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
@ -42,7 +44,6 @@ import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.helpers.GpxUiHelper.LineGraphType; import net.osmand.plus.helpers.GpxUiHelper.LineGraphType;
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
import net.osmand.plus.track.TrackDisplayHelper; import net.osmand.plus.track.TrackDisplayHelper;
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
import net.osmand.plus.views.controls.PagerSlidingTabStrip.CustomTabProvider; import net.osmand.plus.views.controls.PagerSlidingTabStrip.CustomTabProvider;
import net.osmand.plus.views.controls.WrapContentHeightViewPager.ViewAtPositionInterface; import net.osmand.plus.views.controls.WrapContentHeightViewPager.ViewAtPositionInterface;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
@ -51,6 +52,7 @@ import net.osmand.util.MapUtils;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -72,23 +74,23 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid
private GpxDisplayItem gpxItem; private GpxDisplayItem gpxItem;
private GPXTabItemType[] tabTypes; private GPXTabItemType[] tabTypes;
private PagerSlidingTabStrip tabs;
private SparseArray<View> views = new SparseArray<>(); private SparseArray<View> views = new SparseArray<>();
private SegmentActionsListener actionsListener; private SegmentActionsListener actionsListener;
private boolean chartClicked; private boolean chartClicked;
private boolean nightMode;
public GPXItemPagerAdapter(@NonNull PagerSlidingTabStrip tabs, public GPXItemPagerAdapter(@NonNull OsmandApplication app,
@NonNull GpxDisplayItem gpxItem, @NonNull GpxDisplayItem gpxItem,
@NonNull TrackDisplayHelper displayHelper, @NonNull TrackDisplayHelper displayHelper,
@NonNull SegmentActionsListener actionsListener) { boolean nightMode, @NonNull SegmentActionsListener actionsListener) {
super(); super();
this.tabs = tabs; this.app = app;
this.gpxItem = gpxItem; this.gpxItem = gpxItem;
this.nightMode = nightMode;
this.displayHelper = displayHelper; this.displayHelper = displayHelper;
this.actionsListener = actionsListener; this.actionsListener = actionsListener;
app = (OsmandApplication) tabs.getContext().getApplicationContext();
iconsCache = app.getUIUtilities(); iconsCache = app.getUIUtilities();
fetchTabTypes(); fetchTabTypes();
} }
@ -556,40 +558,60 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid
return view == object; return view == object;
} }
int singleTabLayoutId[] = {R.layout.center_button_container};
int doubleTabsLayoutIds[] = {R.layout.left_button_container, R.layout.right_button_container};
int tripleTabsLayoutIds[] = {R.layout.left_button_container, R.layout.center_button_container, R.layout.right_button_container};
@Override @Override
public View getCustomTabView(@NonNull ViewGroup parent, int position) { public View getCustomTabView(@NonNull ViewGroup parent, int position) {
View tab = LayoutInflater.from(parent.getContext()).inflate(R.layout.gpx_tab, parent, false); int layoutId;
int count = getCount();
if (count == 1) {
layoutId = singleTabLayoutId[position];
} else if (count == 2) {
layoutId = doubleTabsLayoutIds[position];
} else {
layoutId = tripleTabsLayoutIds[position];
}
View tab = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
tab.setTag(tabTypes[position].name()); tab.setTag(tabTypes[position].name());
deselect(tab);
return tab; return tab;
} }
@Override @Override
public void select(View tab) { public void select(View tab) {
GPXTabItemType tabType = GPXTabItemType.valueOf((String) tab.getTag()); GPXTabItemType tabType = GPXTabItemType.valueOf((String) tab.getTag());
ImageView img = tab.findViewById(R.id.tab_image); int index = Arrays.asList(tabTypes).indexOf(tabType);
switch (tabs.getTabSelectionType()) { View parent = (View) tab.getParent();
case ALPHA: UiUtilities.updateCustomRadioButtons(app, parent, nightMode, getCustomRadioButtonType(index));
img.setAlpha(tabs.getTabTextSelectedAlpha());
break;
case SOLID_COLOR:
img.setImageDrawable(iconsCache.getPaintedIcon(tabType.getIconId(), tabs.getTextColor()));
break;
}
} }
@Override @Override
public void deselect(View tab) { public void deselect(View tab) {
GPXTabItemType tabType = GPXTabItemType.valueOf((String) tab.getTag());
ImageView img = tab.findViewById(R.id.tab_image); }
switch (tabs.getTabSelectionType()) {
case ALPHA: @Override
img.setAlpha(tabs.getTabTextAlpha()); public void tabStylesUpdated(View tabsContainer, int currentPosition) {
break; ViewGroup.MarginLayoutParams params = (MarginLayoutParams) tabsContainer.getLayoutParams();
case SOLID_COLOR: params.height = app.getResources().getDimensionPixelSize(R.dimen.dialog_button_height);
img.setImageDrawable(iconsCache.getPaintedIcon(tabType.getIconId(), tabs.getTabInactiveTextColor())); tabsContainer.setLayoutParams(params);
break; UiUtilities.updateCustomRadioButtons(app, tabsContainer, nightMode, getCustomRadioButtonType(currentPosition));
}
private CustomRadioButtonType getCustomRadioButtonType(int index) {
int count = getCount();
CustomRadioButtonType type = CustomRadioButtonType.CENTER;
if (count == 2) {
type = index > 0 ? CustomRadioButtonType.END : CustomRadioButtonType.START;
} else if (count == 3) {
if (index == 0) {
type = CustomRadioButtonType.START;
} else if (index == 2) {
type = CustomRadioButtonType.END;
}
} }
return type;
} }
@Override @Override

View file

@ -6,7 +6,6 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
@ -56,7 +55,7 @@ public class SegmentGPXAdapter extends ArrayAdapter<GpxDisplayItem> {
WrapContentHeightViewPager pager = row.findViewById(R.id.pager); WrapContentHeightViewPager pager = row.findViewById(R.id.pager);
PagerSlidingTabStrip tabLayout = row.findViewById(R.id.sliding_tabs); PagerSlidingTabStrip tabLayout = row.findViewById(R.id.sliding_tabs);
pager.setAdapter(new GPXItemPagerAdapter(tabLayout, item, displayHelper, listener)); pager.setAdapter(new GPXItemPagerAdapter(app, item, displayHelper, nightMode, listener));
if (create) { if (create) {
tabLayout.setViewPager(pager); tabLayout.setViewPager(pager);
} else { } else {
@ -72,15 +71,8 @@ public class SegmentGPXAdapter extends ArrayAdapter<GpxDisplayItem> {
View row = UiUtilities.getInflater(context, nightMode).inflate(R.layout.gpx_list_item_tab_content, root, false); View row = UiUtilities.getInflater(context, nightMode).inflate(R.layout.gpx_list_item_tab_content, root, false);
PagerSlidingTabStrip tabLayout = row.findViewById(R.id.sliding_tabs); PagerSlidingTabStrip tabLayout = row.findViewById(R.id.sliding_tabs);
tabLayout.setTabBackground(R.color.color_transparent); tabLayout.setTabBackground(AndroidUtils.resolveAttribute(context, R.attr.btn_bg_border_inactive));
tabLayout.setIndicatorColorResource(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light); tabLayout.setIndicatorHeight(0);
tabLayout.setIndicatorBgColorResource(nightMode ? R.color.divider_color_dark : R.color.divider_color_light);
tabLayout.setIndicatorHeight(AndroidUtils.dpToPx(context, 1f));
if (!nightMode) {
tabLayout.setTextColor(tabLayout.getIndicatorColor());
tabLayout.setTabInactiveTextColor(ContextCompat.getColor(row.getContext(), R.color.text_color_secondary_light));
}
tabLayout.setTextSize(AndroidUtils.spToPx(context, 12f));
tabLayout.setShouldExpand(true); tabLayout.setShouldExpand(true);
WrapContentHeightViewPager pager = row.findViewById(R.id.pager); WrapContentHeightViewPager pager = row.findViewById(R.id.pager);
pager.setSwipeable(false); pager.setSwipeable(false);

View file

@ -82,12 +82,12 @@ public class OnlineRoutingHelper {
} }
@Nullable @Nullable
public OnlineRoutingResponse calculateRouteOnline(@NonNull OnlineRoutingEngine engine, private OnlineRoutingResponse calculateRouteOnline(@NonNull OnlineRoutingEngine engine,
@NonNull List<LatLon> path, @NonNull List<LatLon> path,
boolean leftSideNavigation) throws IOException, JSONException { boolean leftSideNavigation) throws IOException, JSONException {
String url = engine.getFullUrl(path); String url = engine.getFullUrl(path);
String content = makeRequest(url); String content = makeRequest(url);
return engine.parseServerResponse(content, leftSideNavigation); return engine.parseServerResponse(content, app, leftSideNavigation);
} }
@NonNull @NonNull

View file

@ -5,6 +5,7 @@ import androidx.annotation.Nullable;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.EngineParameter; import net.osmand.plus.onlinerouting.EngineParameter;
import net.osmand.plus.onlinerouting.OnlineRoutingResponse; import net.osmand.plus.onlinerouting.OnlineRoutingResponse;
@ -84,6 +85,7 @@ public class GraphhopperEngine extends OnlineRoutingEngine {
@Nullable @Nullable
@Override @Override
public OnlineRoutingResponse parseServerResponse(@NonNull String content, public OnlineRoutingResponse parseServerResponse(@NonNull String content,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException { boolean leftSideNavigation) throws JSONException {
JSONObject obj = new JSONObject(content); JSONObject obj = new JSONObject(content);
JSONObject root = obj.getJSONArray("paths").getJSONObject(0); JSONObject root = obj.getJSONArray("paths").getJSONObject(0);
@ -96,25 +98,20 @@ public class GraphhopperEngine extends OnlineRoutingEngine {
JSONArray instructions = root.getJSONArray("instructions"); JSONArray instructions = root.getJSONArray("instructions");
List<RouteDirectionInfo> directions = new ArrayList<>(); List<RouteDirectionInfo> directions = new ArrayList<>();
for (int i = 0; i < instructions.length(); i++) { for (int i = 0; i < instructions.length(); i++) {
JSONObject item = instructions.getJSONObject(i); JSONObject instruction = instructions.getJSONObject(i);
int sign = Integer.parseInt(item.getString("sign")); int distance = (int) Math.round(instruction.getDouble("distance"));
int distance = (int) Math.round(Double.parseDouble(item.getString("distance"))); String description = instruction.getString("text");
String description = item.getString("text"); String streetName = instruction.getString("street_name");
String streetName = item.getString("street_name"); int timeInSeconds = Math.round(instruction.getInt("time") / 1000f);
int timeInSeconds = (int) Math.round(Integer.parseInt(item.getString("time")) / 1000f); JSONArray interval = instruction.getJSONArray("interval");
JSONArray interval = item.getJSONArray("interval");
int startPointOffset = interval.getInt(0); int startPointOffset = interval.getInt(0);
int endPointOffset = interval.getInt(1); int endPointOffset = interval.getInt(1);
float averageSpeed = (float) distance / timeInSeconds; float averageSpeed = (float) distance / timeInSeconds;
TurnType turnType = identifyTurnType(sign, leftSideNavigation); TurnType turnType = parseTurnType(instruction, leftSideNavigation);
// TODO turnType.setTurnAngle()
RouteDirectionInfo direction = new RouteDirectionInfo(averageSpeed, turnType); RouteDirectionInfo direction = new RouteDirectionInfo(averageSpeed, turnType);
direction.routePointOffset = startPointOffset; direction.routePointOffset = startPointOffset;
if (turnType != null && turnType.isRoundAbout()) {
direction.routeEndPointOffset = endPointOffset;
}
direction.setDescriptionRoute(description); direction.setDescriptionRoute(description);
direction.setStreetName(streetName); direction.setStreetName(streetName);
direction.setDistance(distance); direction.setDistance(distance);
@ -123,27 +120,33 @@ public class GraphhopperEngine extends OnlineRoutingEngine {
return new OnlineRoutingResponse(route, directions); return new OnlineRoutingResponse(route, directions);
} }
@Override @NonNull
public boolean parseServerMessage(@NonNull StringBuilder sb, private TurnType parseTurnType(@NonNull JSONObject instruction,
@NonNull String content) throws JSONException { boolean leftSide) throws JSONException {
JSONObject obj = new JSONObject(content); int sign = instruction.getInt("sign");
if (obj.has("message")) { TurnType turnType = identifyTurnType(sign, leftSide);
String message = obj.getString("message");
sb.append(message); if (turnType == null) {
turnType = TurnType.straight();
} else if (turnType.isRoundAbout()) {
if (instruction.has("exit_number")) {
int exit = instruction.getInt("exit_number");
turnType.setExitOut(exit);
}
if (instruction.has("turn_angle")) {
float angle = (float) instruction.getDouble("turn_angle");
turnType.setTurnAngle(angle);
}
} else {
// TODO turnType.setTurnAngle()
} }
return obj.has("paths");
return turnType;
} }
/**
* @param sign - a number which specifies the turn type to show (Graphhopper API value)
* @return a TurnType object defined in OsmAnd which is equivalent to a value from the Graphhopper API
*
* For future compatibility it is important that all clients
* are able to handle also unknown instruction sign numbers
*/
@Nullable @Nullable
public static TurnType identifyTurnType(int sign, boolean leftSide) { public static TurnType identifyTurnType(int sign, boolean leftSide) {
int id = INVALID_ID; Integer id = null;
if (sign == -98) { if (sign == -98) {
// an U-turn without the knowledge // an U-turn without the knowledge
@ -192,6 +195,7 @@ public class GraphhopperEngine extends OnlineRoutingEngine {
} else if (sign == 4) { } else if (sign == 4) {
// the finish instruction before the last point // the finish instruction before the last point
id = TurnType.C;
} else if (sign == 5) { } else if (sign == 5) {
// the instruction before a via point // the instruction before a via point
@ -209,6 +213,17 @@ public class GraphhopperEngine extends OnlineRoutingEngine {
id = TurnType.TRU; id = TurnType.TRU;
} }
return id != INVALID_ID ? TurnType.valueOf(id, leftSide) : null; return id != null ? TurnType.valueOf(id, leftSide) : null;
}
@Override
public boolean parseServerMessage(@NonNull StringBuilder sb,
@NonNull String content) throws JSONException {
JSONObject obj = new JSONObject(content);
if (obj.has("message")) {
String message = obj.getString("message");
sb.append(message);
}
return obj.has("paths");
} }
} }

View file

@ -8,6 +8,7 @@ import androidx.annotation.Nullable;
import net.osmand.GPXUtilities.WptPt; import net.osmand.GPXUtilities.WptPt;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.EngineParameter; import net.osmand.plus.onlinerouting.EngineParameter;
import net.osmand.plus.onlinerouting.OnlineRoutingFactory; import net.osmand.plus.onlinerouting.OnlineRoutingFactory;
@ -33,7 +34,6 @@ public abstract class OnlineRoutingEngine implements Cloneable {
public final static String ONLINE_ROUTING_ENGINE_PREFIX = "online_routing_engine_"; public final static String ONLINE_ROUTING_ENGINE_PREFIX = "online_routing_engine_";
public final static VehicleType CUSTOM_VEHICLE = new VehicleType("", R.string.shared_string_custom); public final static VehicleType CUSTOM_VEHICLE = new VehicleType("", R.string.shared_string_custom);
public final static int INVALID_ID = -1;
private final Map<String, String> params = new HashMap<>(); private final Map<String, String> params = new HashMap<>();
private final List<VehicleType> allowedVehicles = new ArrayList<>(); private final List<VehicleType> allowedVehicles = new ArrayList<>();
@ -100,6 +100,7 @@ public abstract class OnlineRoutingEngine implements Cloneable {
@Nullable @Nullable
public abstract OnlineRoutingResponse parseServerResponse(@NonNull String content, public abstract OnlineRoutingResponse parseServerResponse(@NonNull String content,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException; boolean leftSideNavigation) throws JSONException;
@NonNull @NonNull

View file

@ -5,6 +5,7 @@ import androidx.annotation.Nullable;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.EngineParameter; import net.osmand.plus.onlinerouting.EngineParameter;
import net.osmand.plus.onlinerouting.OnlineRoutingResponse; import net.osmand.plus.onlinerouting.OnlineRoutingResponse;
@ -81,6 +82,7 @@ public class OrsEngine extends OnlineRoutingEngine {
@Nullable @Nullable
@Override @Override
public OnlineRoutingResponse parseServerResponse(@NonNull String content, public OnlineRoutingResponse parseServerResponse(@NonNull String content,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException { boolean leftSideNavigation) throws JSONException {
JSONObject obj = new JSONObject(content); JSONObject obj = new JSONObject(content);
JSONArray array = obj.getJSONArray("features").getJSONObject(0) JSONArray array = obj.getJSONArray("features").getJSONObject(0)

View file

@ -5,19 +5,27 @@ import androidx.annotation.Nullable;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.EngineParameter; import net.osmand.plus.onlinerouting.EngineParameter;
import net.osmand.plus.onlinerouting.OnlineRoutingResponse; import net.osmand.plus.onlinerouting.OnlineRoutingResponse;
import net.osmand.plus.onlinerouting.VehicleType; import net.osmand.plus.onlinerouting.VehicleType;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.router.TurnType;
import net.osmand.util.GeoPolylineParserUtil; import net.osmand.util.GeoPolylineParserUtil;
import net.osmand.util.MapUtils;
import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static net.osmand.util.Algorithms.isEmpty; import static net.osmand.util.Algorithms.isEmpty;
import static net.osmand.util.Algorithms.objectEquals;
public class OsrmEngine extends OnlineRoutingEngine { public class OsrmEngine extends OnlineRoutingEngine {
@ -70,17 +78,154 @@ public class OsrmEngine extends OnlineRoutingEngine {
@Nullable @Nullable
@Override @Override
public OnlineRoutingResponse parseServerResponse(@NonNull String content, public OnlineRoutingResponse parseServerResponse(@NonNull String content,
@NonNull OsmandApplication app,
boolean leftSideNavigation) throws JSONException { boolean leftSideNavigation) throws JSONException {
JSONObject obj = new JSONObject(content); JSONObject obj = new JSONObject(content);
String encoded = obj.getJSONArray("routes").getJSONObject(0).getString("geometry"); JSONObject routeInfo = obj.getJSONArray("routes").getJSONObject(0);
List<LatLon> points = GeoPolylineParserUtil.parse(encoded, GeoPolylineParserUtil.PRECISION_5); String encodedPoints = routeInfo.getString("geometry");
if (!isEmpty(points)) { List<LatLon> points = GeoPolylineParserUtil.parse(encodedPoints, GeoPolylineParserUtil.PRECISION_5);
List<Location> route = convertRouteToLocationsList(points); if (isEmpty(points)) return null;
return new OnlineRoutingResponse(route, null);
List<Location> route = convertRouteToLocationsList(points);
List<RouteDirectionInfo> directions = new ArrayList<>();
int startSearchingId = 0;
JSONArray legs = routeInfo.getJSONArray("legs");
for (int i = 0; i < legs.length(); i++) {
JSONObject leg = legs.getJSONObject(i);
if (!leg.has("steps")) continue;
JSONArray steps = leg.getJSONArray("steps");
for (int j = 0; j < steps.length(); j++) {
JSONObject instruction = steps.getJSONObject(j);
JSONObject maneuver = instruction.getJSONObject("maneuver");
String maneuverType = maneuver.getString("type");
JSONArray location = maneuver.getJSONArray("location");
double lon = location.getDouble(0);
double lat = location.getDouble(1);
Integer routePointOffset = getLocationIndexInList(route, startSearchingId, lat, lon);
if (routePointOffset == null) continue;
startSearchingId = routePointOffset;
// in meters
int distance = (int) Math.round(instruction.getDouble("distance"));
// in seconds
int duration = (int) Math.round(instruction.getDouble("duration"));
float averageSpeed = (float) distance / duration;
TurnType turnType = parseTurnType(maneuver, leftSideNavigation);
RouteDirectionInfo direction = new RouteDirectionInfo(averageSpeed, turnType);
direction.setDistance(distance);
String streetName = instruction.getString("name");
String description = "";
if (!objectEquals(maneuverType, "arrive")) {
description = RouteCalculationResult.toString(turnType, app, false) + " " + streetName;
}
description = description.trim();
direction.setStreetName(streetName);
direction.setDescriptionRoute(description);
direction.routePointOffset = routePointOffset;
directions.add(direction);
}
}
return new OnlineRoutingResponse(route, directions);
}
@Nullable
private Integer getLocationIndexInList(@NonNull List<Location> locations,
int startIndex, double lat, double lon) {
for (int i = startIndex; i < locations.size(); i++) {
Location l = locations.get(i);
if (MapUtils.areLatLonEqual(l, lat, lon)) {
return i;
}
} }
return null; return null;
} }
@NonNull
private TurnType parseTurnType(@NonNull JSONObject maneuver,
boolean leftSide) throws JSONException {
TurnType turnType = null;
String type = maneuver.getString("type");
String modifier = null;
if (maneuver.has("modifier")) {
modifier = maneuver.getString("modifier");
}
if (objectEquals(type, "roundabout")
|| objectEquals(type, "rotary")
|| objectEquals(type, "roundabout turn")) {
if (maneuver.has("exit")) {
int exit = maneuver.getInt("exit");
turnType = TurnType.getExitTurn(exit, 0.0f, leftSide);
} else if (modifier != null) {
// for simple roundabout turn without "exit" parameter
turnType = identifyTurnType(modifier, leftSide);
}
} else {
// for other maneuver types find TurnType
// like a basic turn into direction of the modifier
if (modifier != null) {
turnType = identifyTurnType(modifier, leftSide);
}
}
if (turnType == null) {
turnType = TurnType.straight();
}
int bearingBefore = maneuver.getInt("bearing_before");
int bearingAfter = maneuver.getInt("bearing_after");
float angle = (float) MapUtils.degreesDiff(bearingAfter, bearingBefore);
turnType.setTurnAngle(angle);
return turnType;
}
@Nullable
private TurnType identifyTurnType(@NonNull String modifier,
boolean leftSide) {
Integer id = null;
switch (modifier) {
case "uturn":
id = TurnType.TU;
break;
case "sharp right":
id = TurnType.TSHR;
break;
case "right":
id = TurnType.TR;
break;
case "slight right":
id = TurnType.TSLR;
break;
case "straight":
id = TurnType.C;
break;
case "slight left":
id = TurnType.TSLL;
break;
case "left":
id = TurnType.TL;
break;
case "sharp left":
id = TurnType.TSHL;
break;
}
return id != null ? TurnType.valueOf(id, leftSide) : null;
}
@Override @Override
public boolean parseServerMessage(@NonNull StringBuilder sb, public boolean parseServerMessage(@NonNull StringBuilder sb,
@NonNull String content) throws JSONException { @NonNull String content) throws JSONException {

View file

@ -711,7 +711,7 @@ public class RouteCalculationResult {
if (directions != null && directions.size() > 1) { if (directions != null && directions.size() > 1) {
for (int i = 1; i < directions.size();) { for (int i = 1; i < directions.size();) {
RouteDirectionInfo r = directions.get(i); RouteDirectionInfo r = directions.get(i);
if (r.getTurnType() != null && r.getTurnType().getValue() == TurnType.C) { if (r.getTurnType().getValue() == TurnType.C) {
RouteDirectionInfo prev = directions.get(i - 1); RouteDirectionInfo prev = directions.get(i - 1);
prev.setAverageSpeed((prev.distance + r.distance) prev.setAverageSpeed((prev.distance + r.distance)
/ (prev.distance / prev.getAverageSpeed() + r.distance / r.getAverageSpeed())); / (prev.distance / prev.getAverageSpeed() + r.distance / r.getAverageSpeed()));

View file

@ -1206,7 +1206,7 @@ public class RouteProvider {
helper.calculateRouteOnline(stringKey, getPathFromParams(params), params.leftSide); helper.calculateRouteOnline(stringKey, getPathFromParams(params), params.leftSide);
if (response != null) { if (response != null) {
params.intermediates = null; params.intermediates = null;
return new RouteCalculationResult(response.getRoute(), response.getDirections(), params, null, true); return new RouteCalculationResult(response.getRoute(), response.getDirections(), params, null, false);
} else { } else {
return new RouteCalculationResult("Route is empty"); return new RouteCalculationResult("Route is empty");
} }

View file

@ -480,19 +480,21 @@ public class SettingsHelper {
typesMap.putAll(getMyPlacesItems()); typesMap.putAll(getMyPlacesItems());
typesMap.putAll(getResourcesItems()); typesMap.putAll(getResourcesItems());
return getFilteredSettingsItems(typesMap, settingsTypes, export); return getFilteredSettingsItems(typesMap, settingsTypes, Collections.<SettingsItem>emptyList(), export);
} }
public List<SettingsItem> getFilteredSettingsItems(Map<ExportSettingsType, List<?>> allSettingsMap, public List<SettingsItem> getFilteredSettingsItems(
List<ExportSettingsType> settingsTypes, boolean export) { Map<ExportSettingsType, List<?>> allSettingsMap, List<ExportSettingsType> settingsTypes,
List<SettingsItem> settingsItems = new ArrayList<>(); @NonNull List<SettingsItem> settingsItems, boolean export
) {
List<SettingsItem> filteredSettingsItems = new ArrayList<>();
for (ExportSettingsType settingsType : settingsTypes) { for (ExportSettingsType settingsType : settingsTypes) {
List<?> settingsDataObjects = allSettingsMap.get(settingsType); List<?> settingsDataObjects = allSettingsMap.get(settingsType);
if (settingsDataObjects != null) { if (settingsDataObjects != null) {
settingsItems.addAll(prepareSettingsItems(settingsDataObjects, export)); filteredSettingsItems.addAll(prepareSettingsItems(settingsDataObjects, settingsItems, export));
} }
} }
return settingsItems; return filteredSettingsItems;
} }
public Map<ExportSettingsCategory, SettingsCategoryItems> getSettingsByCategory(boolean addProfiles) { public Map<ExportSettingsCategory, SettingsCategoryItems> getSettingsByCategory(boolean addProfiles) {
@ -693,8 +695,8 @@ public class SettingsHelper {
return files; return files;
} }
public List<SettingsItem> prepareSettingsItems(List<?> data, boolean export) { public List<SettingsItem> prepareSettingsItems(List<?> data, List<SettingsItem> settingsItems, boolean export) {
List<SettingsItem> settingsItems = new ArrayList<>(); List<SettingsItem> result = new ArrayList<>();
List<QuickAction> quickActions = new ArrayList<>(); List<QuickAction> quickActions = new ArrayList<>();
List<PoiUIFilter> poiUIFilters = new ArrayList<>(); List<PoiUIFilter> poiUIFilters = new ArrayList<>();
List<ITileSource> tileSourceTemplates = new ArrayList<>(); List<ITileSource> tileSourceTemplates = new ArrayList<>();
@ -719,13 +721,15 @@ public class SettingsHelper {
try { try {
File file = (File) object; File file = (File) object;
if (file.getName().endsWith(IndexConstants.GPX_FILE_EXT)) { if (file.getName().endsWith(IndexConstants.GPX_FILE_EXT)) {
settingsItems.add(new GpxSettingsItem(app, file)); result.add(new GpxSettingsItem(app, file));
} else { } else {
settingsItems.add(new FileSettingsItem(app, file)); result.add(new FileSettingsItem(app, file));
} }
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
LOG.warn("Trying to export unsuported file type", e); LOG.warn("Trying to export unsuported file type", e);
} }
} else if (object instanceof FileSettingsItem) {
result.add((FileSettingsItem) object);
} else if (object instanceof AvoidRoadInfo) { } else if (object instanceof AvoidRoadInfo) {
avoidRoads.add((AvoidRoadInfo) object); avoidRoads.add((AvoidRoadInfo) object);
} else if (object instanceof ApplicationModeBean) { } else if (object instanceof ApplicationModeBean) {
@ -746,65 +750,100 @@ public class SettingsHelper {
} else if (object instanceof HistoryEntry) { } else if (object instanceof HistoryEntry) {
historyEntries.add((HistoryEntry) object); historyEntries.add((HistoryEntry) object);
} else if (object instanceof GlobalSettingsItem) { } else if (object instanceof GlobalSettingsItem) {
settingsItems.add((GlobalSettingsItem) object); result.add((GlobalSettingsItem) object);
} else if (object instanceof OnlineRoutingEngine) { } else if (object instanceof OnlineRoutingEngine) {
onlineRoutingEngines.add((OnlineRoutingEngine) object); onlineRoutingEngines.add((OnlineRoutingEngine) object);
} }
} }
if (!quickActions.isEmpty()) { if (!quickActions.isEmpty()) {
settingsItems.add(new QuickActionsSettingsItem(app, quickActions)); QuickActionsSettingsItem baseItem = getBaseItem(SettingsItemType.QUICK_ACTIONS, QuickActionsSettingsItem.class, settingsItems);
result.add(new QuickActionsSettingsItem(app, baseItem, quickActions));
} }
if (!poiUIFilters.isEmpty()) { if (!poiUIFilters.isEmpty()) {
settingsItems.add(new PoiUiFiltersSettingsItem(app, poiUIFilters)); PoiUiFiltersSettingsItem baseItem = getBaseItem(SettingsItemType.POI_UI_FILTERS, PoiUiFiltersSettingsItem.class, settingsItems);
result.add(new PoiUiFiltersSettingsItem(app, baseItem, poiUIFilters));
} }
if (!tileSourceTemplates.isEmpty()) { if (!tileSourceTemplates.isEmpty()) {
settingsItems.add(new MapSourcesSettingsItem(app, tileSourceTemplates)); MapSourcesSettingsItem baseItem = getBaseItem(SettingsItemType.MAP_SOURCES, MapSourcesSettingsItem.class, settingsItems);
result.add(new MapSourcesSettingsItem(app, baseItem, tileSourceTemplates));
} }
if (!avoidRoads.isEmpty()) { if (!avoidRoads.isEmpty()) {
settingsItems.add(new AvoidRoadsSettingsItem(app, avoidRoads)); AvoidRoadsSettingsItem baseItem = getBaseItem(SettingsItemType.AVOID_ROADS, AvoidRoadsSettingsItem.class, settingsItems);
result.add(new AvoidRoadsSettingsItem(app, baseItem, avoidRoads));
} }
if (!appModeBeans.isEmpty()) { if (!appModeBeans.isEmpty()) {
for (ApplicationModeBean modeBean : appModeBeans) { for (ApplicationModeBean modeBean : appModeBeans) {
if (export) { if (export) {
ApplicationMode mode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null); ApplicationMode mode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null);
if (mode != null) { if (mode != null) {
settingsItems.add(new ProfileSettingsItem(app, mode)); result.add(new ProfileSettingsItem(app, mode));
} }
} else { } else {
settingsItems.add(new ProfileSettingsItem(app, null, modeBean)); result.add(new ProfileSettingsItem(app, getBaseProfileSettingsItem(modeBean, settingsItems), modeBean));
} }
} }
} }
if (!osmNotesPointList.isEmpty()) { if (!osmNotesPointList.isEmpty()) {
settingsItems.add(new OsmNotesSettingsItem(app, osmNotesPointList)); OsmNotesSettingsItem baseItem = getBaseItem(SettingsItemType.OSM_NOTES, OsmNotesSettingsItem.class, settingsItems);
result.add(new OsmNotesSettingsItem(app, baseItem, osmNotesPointList));
} }
if (!osmEditsPointList.isEmpty()) { if (!osmEditsPointList.isEmpty()) {
settingsItems.add(new OsmEditsSettingsItem(app, osmEditsPointList)); OsmEditsSettingsItem baseItem = getBaseItem(SettingsItemType.OSM_EDITS, OsmEditsSettingsItem.class, settingsItems);
result.add(new OsmEditsSettingsItem(app, baseItem, osmEditsPointList));
} }
if (!favoriteGroups.isEmpty()) { if (!favoriteGroups.isEmpty()) {
settingsItems.add(new FavoritesSettingsItem(app, favoriteGroups)); FavoritesSettingsItem baseItem = getBaseItem(SettingsItemType.FAVOURITES, FavoritesSettingsItem.class, settingsItems);
result.add(new FavoritesSettingsItem(app, baseItem, favoriteGroups));
} }
if (!markersGroups.isEmpty()) { if (!markersGroups.isEmpty()) {
List<MapMarker> mapMarkers = new ArrayList<>(); List<MapMarker> mapMarkers = new ArrayList<>();
for (MapMarkersGroup group : markersGroups) { for (MapMarkersGroup group : markersGroups) {
mapMarkers.addAll(group.getMarkers()); mapMarkers.addAll(group.getMarkers());
} }
settingsItems.add(new MarkersSettingsItem(app, mapMarkers)); MarkersSettingsItem baseItem = getBaseItem(SettingsItemType.ACTIVE_MARKERS, MarkersSettingsItem.class, settingsItems);
result.add(new MarkersSettingsItem(app, baseItem, mapMarkers));
} }
if (!markersHistoryGroups.isEmpty()) { if (!markersHistoryGroups.isEmpty()) {
List<MapMarker> mapMarkers = new ArrayList<>(); List<MapMarker> mapMarkers = new ArrayList<>();
for (MapMarkersGroup group : markersHistoryGroups) { for (MapMarkersGroup group : markersHistoryGroups) {
mapMarkers.addAll(group.getMarkers()); mapMarkers.addAll(group.getMarkers());
} }
settingsItems.add(new HistoryMarkersSettingsItem(app, mapMarkers)); HistoryMarkersSettingsItem baseItem = getBaseItem(SettingsItemType.HISTORY_MARKERS, HistoryMarkersSettingsItem.class, settingsItems);
result.add(new HistoryMarkersSettingsItem(app, baseItem, mapMarkers));
} }
if (!historyEntries.isEmpty()) { if (!historyEntries.isEmpty()) {
settingsItems.add(new SearchHistorySettingsItem(app, historyEntries)); SearchHistorySettingsItem baseItem = getBaseItem(SettingsItemType.SEARCH_HISTORY, SearchHistorySettingsItem.class, settingsItems);
result.add(new SearchHistorySettingsItem(app, baseItem, historyEntries));
} }
if (!onlineRoutingEngines.isEmpty()) { if (!onlineRoutingEngines.isEmpty()) {
settingsItems.add(new OnlineRoutingSettingsItem(app, onlineRoutingEngines)); OnlineRoutingSettingsItem baseItem = getBaseItem(SettingsItemType.ONLINE_ROUTING_ENGINES, OnlineRoutingSettingsItem.class, settingsItems);
result.add(new OnlineRoutingSettingsItem(app, baseItem, onlineRoutingEngines));
} }
return settingsItems; return result;
}
@Nullable
private ProfileSettingsItem getBaseProfileSettingsItem(ApplicationModeBean modeBean, List<SettingsItem> settingsItems) {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == SettingsItemType.PROFILE) {
ProfileSettingsItem profileItem = (ProfileSettingsItem) settingsItem;
ApplicationModeBean bean = profileItem.getModeBean();
if (Algorithms.objectEquals(bean.stringKey, modeBean.stringKey) && Algorithms.objectEquals(bean.userProfileName, modeBean.userProfileName)) {
return profileItem;
}
}
}
return null;
}
@Nullable
private <T> T getBaseItem(SettingsItemType settingsItemType, Class<T> clazz, List<SettingsItem> settingsItems) {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == settingsItemType && clazz.isInstance(settingsItem)) {
return clazz.cast(settingsItem);
}
}
return null;
} }
public static Map<ExportSettingsCategory, SettingsCategoryItems> getSettingsToOperateByCategory(List<SettingsItem> items, boolean importComplete) { public static Map<ExportSettingsCategory, SettingsCategoryItems> getSettingsToOperateByCategory(List<SettingsItem> items, boolean importComplete) {

View file

@ -36,6 +36,7 @@ import org.apache.commons.logging.Log;
import java.io.File; import java.io.File;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -150,7 +151,7 @@ public class ExportSettingsFragment extends BaseSettingsListFragment {
showExportProgressDialog(); showExportProgressDialog();
File tempDir = FileUtils.getTempDir(app); File tempDir = FileUtils.getTempDir(app);
String fileName = getFileName(); String fileName = getFileName();
List<SettingsItem> items = app.getSettingsHelper().prepareSettingsItems(adapter.getData(), true); List<SettingsItem> items = app.getSettingsHelper().prepareSettingsItems(adapter.getData(), Collections.<SettingsItem>emptyList(), true);
progress.setMax(getMaxProgress(items)); progress.setMax(getMaxProgress(items));
app.getSettingsHelper().exportSettings(tempDir, fileName, getSettingsExportListener(), items, true); app.getSettingsHelper().exportSettings(tempDir, fileName, getSettingsExportListener(), items, true);
} }

View file

@ -18,57 +18,24 @@ import androidx.fragment.app.FragmentManager;
import com.google.android.material.appbar.CollapsingToolbarLayout; import com.google.android.material.appbar.CollapsingToolbarLayout;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.map.ITileSource;
import net.osmand.map.TileSourceManager.TileSourceTemplate;
import net.osmand.plus.AppInitializer; import net.osmand.plus.AppInitializer;
import net.osmand.plus.FavouritesDbHelper.FavoriteGroup;
import net.osmand.plus.OsmandPlugin; import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.SQLiteTileSource;
import net.osmand.plus.UiUtilities; import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.audionotes.AudioVideoNotesPlugin; import net.osmand.plus.audionotes.AudioVideoNotesPlugin;
import net.osmand.plus.download.ReloadIndexesTask; import net.osmand.plus.download.ReloadIndexesTask;
import net.osmand.plus.download.ReloadIndexesTask.ReloadIndexesListener; import net.osmand.plus.download.ReloadIndexesTask.ReloadIndexesListener;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
import net.osmand.plus.mapmarkers.MapMarker;
import net.osmand.plus.mapmarkers.MapMarkersGroup;
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
import net.osmand.plus.osmedit.OpenstreetmapPoint;
import net.osmand.plus.osmedit.OsmNotesPoint;
import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.quickaction.QuickAction;
import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
import net.osmand.plus.settings.backend.ExportSettingsType;
import net.osmand.plus.settings.backend.backup.AvoidRoadsSettingsItem;
import net.osmand.plus.settings.backend.backup.FavoritesSettingsItem;
import net.osmand.plus.settings.backend.backup.FileSettingsItem; import net.osmand.plus.settings.backend.backup.FileSettingsItem;
import net.osmand.plus.settings.backend.backup.GlobalSettingsItem;
import net.osmand.plus.settings.backend.backup.GpxSettingsItem;
import net.osmand.plus.settings.backend.backup.HistoryMarkersSettingsItem;
import net.osmand.plus.settings.backend.backup.MapSourcesSettingsItem;
import net.osmand.plus.settings.backend.backup.MarkersSettingsItem;
import net.osmand.plus.settings.backend.backup.OnlineRoutingSettingsItem;
import net.osmand.plus.settings.backend.backup.OsmEditsSettingsItem;
import net.osmand.plus.settings.backend.backup.OsmNotesSettingsItem;
import net.osmand.plus.settings.backend.backup.PoiUiFiltersSettingsItem;
import net.osmand.plus.settings.backend.backup.ProfileSettingsItem;
import net.osmand.plus.settings.backend.backup.QuickActionsSettingsItem;
import net.osmand.plus.settings.backend.backup.SearchHistorySettingsItem;
import net.osmand.plus.settings.backend.backup.SettingsHelper; import net.osmand.plus.settings.backend.backup.SettingsHelper;
import net.osmand.plus.settings.backend.backup.SettingsHelper.ImportAsyncTask; import net.osmand.plus.settings.backend.backup.SettingsHelper.ImportAsyncTask;
import net.osmand.plus.settings.backend.backup.SettingsItem; import net.osmand.plus.settings.backend.backup.SettingsItem;
import net.osmand.plus.settings.backend.backup.SettingsItemType;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import java.io.File; import java.io.File;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ImportSettingsFragment extends BaseSettingsListFragment { public class ImportSettingsFragment extends BaseSettingsListFragment {
@ -177,7 +144,7 @@ public class ImportSettingsFragment extends BaseSettingsListFragment {
} }
private void importItems() { private void importItems() {
List<SettingsItem> selectedItems = getSettingsItemsFromData(adapter.getData()); List<SettingsItem> selectedItems = settingsHelper.prepareSettingsItems(adapter.getData(), settingsItems, false);
if (file != null && settingsItems != null) { if (file != null && settingsItems != null) {
duplicateStartTime = System.currentTimeMillis(); duplicateStartTime = System.currentTimeMillis();
settingsHelper.checkDuplicates(file, settingsItems, selectedItems, getDuplicatesListener()); settingsHelper.checkDuplicates(file, settingsItems, selectedItems, getDuplicatesListener());
@ -272,181 +239,6 @@ public class ImportSettingsFragment extends BaseSettingsListFragment {
this.settingsItems = settingsItems; this.settingsItems = settingsItems;
} }
@Nullable
private ProfileSettingsItem getBaseProfileSettingsItem(ApplicationModeBean modeBean) {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == SettingsItemType.PROFILE) {
ProfileSettingsItem profileItem = (ProfileSettingsItem) settingsItem;
ApplicationModeBean bean = profileItem.getModeBean();
if (Algorithms.objectEquals(bean.stringKey, modeBean.stringKey) && Algorithms.objectEquals(bean.userProfileName, modeBean.userProfileName)) {
return profileItem;
}
}
}
return null;
}
@Nullable
private QuickActionsSettingsItem getBaseQuickActionsSettingsItem() {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == SettingsItemType.QUICK_ACTIONS) {
return (QuickActionsSettingsItem) settingsItem;
}
}
return null;
}
@Nullable
private PoiUiFiltersSettingsItem getBasePoiUiFiltersSettingsItem() {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == SettingsItemType.POI_UI_FILTERS) {
return (PoiUiFiltersSettingsItem) settingsItem;
}
}
return null;
}
@Nullable
private MapSourcesSettingsItem getBaseMapSourcesSettingsItem() {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == SettingsItemType.MAP_SOURCES) {
return (MapSourcesSettingsItem) settingsItem;
}
}
return null;
}
@Nullable
private AvoidRoadsSettingsItem getBaseAvoidRoadsSettingsItem() {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == SettingsItemType.AVOID_ROADS) {
return (AvoidRoadsSettingsItem) settingsItem;
}
}
return null;
}
@Nullable
private <T> T getBaseItem(SettingsItemType settingsItemType, Class<T> clazz) {
for (SettingsItem settingsItem : settingsItems) {
if (settingsItem.getType() == settingsItemType && clazz.isInstance(settingsItem)) {
return clazz.cast(settingsItem);
}
}
return null;
}
private List<SettingsItem> getSettingsItemsFromData(List<?> data) {
List<SettingsItem> settingsItems = new ArrayList<>();
List<ApplicationModeBean> appModeBeans = new ArrayList<>();
List<QuickAction> quickActions = new ArrayList<>();
List<PoiUIFilter> poiUIFilters = new ArrayList<>();
List<ITileSource> tileSourceTemplates = new ArrayList<>();
List<AvoidRoadInfo> avoidRoads = new ArrayList<>();
List<OsmNotesPoint> osmNotesPointList = new ArrayList<>();
List<OpenstreetmapPoint> osmEditsPointList = new ArrayList<>();
List<FavoriteGroup> favoriteGroups = new ArrayList<>();
List<MapMarkersGroup> markersGroups = new ArrayList<>();
List<MapMarkersGroup> markersHistoryGroups = new ArrayList<>();
List<HistoryEntry> historyEntries = new ArrayList<>();
List<OnlineRoutingEngine> onlineRoutingEngines = new ArrayList<>();
for (Object object : data) {
if (object instanceof ApplicationModeBean) {
appModeBeans.add((ApplicationModeBean) object);
} else if (object instanceof QuickAction) {
quickActions.add((QuickAction) object);
} else if (object instanceof PoiUIFilter) {
poiUIFilters.add((PoiUIFilter) object);
} else if (object instanceof TileSourceTemplate || object instanceof SQLiteTileSource) {
tileSourceTemplates.add((ITileSource) object);
} else if (object instanceof File) {
File file = (File) object;
if (file.getName().endsWith(IndexConstants.GPX_FILE_EXT)) {
settingsItems.add(new GpxSettingsItem(app, file));
} else {
settingsItems.add(new FileSettingsItem(app, file));
}
} else if (object instanceof FileSettingsItem) {
settingsItems.add((FileSettingsItem) object);
} else if (object instanceof AvoidRoadInfo) {
avoidRoads.add((AvoidRoadInfo) object);
} else if (object instanceof OsmNotesPoint) {
osmNotesPointList.add((OsmNotesPoint) object);
} else if (object instanceof OpenstreetmapPoint) {
osmEditsPointList.add((OpenstreetmapPoint) object);
} else if (object instanceof FavoriteGroup) {
favoriteGroups.add((FavoriteGroup) object);
} else if (object instanceof GlobalSettingsItem) {
settingsItems.add((GlobalSettingsItem) object);
} else if (object instanceof MapMarkersGroup) {
MapMarkersGroup markersGroup = (MapMarkersGroup) object;
if (ExportSettingsType.ACTIVE_MARKERS.name().equals(markersGroup.getId())) {
markersGroups.add((MapMarkersGroup) object);
} else if (ExportSettingsType.HISTORY_MARKERS.name().equals(markersGroup.getId())) {
markersHistoryGroups.add((MapMarkersGroup) object);
}
} else if (object instanceof HistoryEntry) {
historyEntries.add((HistoryEntry) object);
} else if (object instanceof OnlineRoutingEngine) {
onlineRoutingEngines.add((OnlineRoutingEngine) object);
}
}
if (!appModeBeans.isEmpty()) {
for (ApplicationModeBean modeBean : appModeBeans) {
settingsItems.add(new ProfileSettingsItem(app, getBaseProfileSettingsItem(modeBean), modeBean));
}
}
if (!quickActions.isEmpty()) {
settingsItems.add(new QuickActionsSettingsItem(app, getBaseQuickActionsSettingsItem(), quickActions));
}
if (!poiUIFilters.isEmpty()) {
settingsItems.add(new PoiUiFiltersSettingsItem(app, getBasePoiUiFiltersSettingsItem(), poiUIFilters));
}
if (!tileSourceTemplates.isEmpty()) {
settingsItems.add(new MapSourcesSettingsItem(app, getBaseMapSourcesSettingsItem(), tileSourceTemplates));
}
if (!avoidRoads.isEmpty()) {
settingsItems.add(new AvoidRoadsSettingsItem(app, getBaseAvoidRoadsSettingsItem(), avoidRoads));
}
if (!osmNotesPointList.isEmpty()) {
OsmNotesSettingsItem baseItem = getBaseItem(SettingsItemType.OSM_NOTES, OsmNotesSettingsItem.class);
settingsItems.add(new OsmNotesSettingsItem(app, baseItem, osmNotesPointList));
}
if (!osmEditsPointList.isEmpty()) {
OsmEditsSettingsItem baseItem = getBaseItem(SettingsItemType.OSM_EDITS, OsmEditsSettingsItem.class);
settingsItems.add(new OsmEditsSettingsItem(app, baseItem, osmEditsPointList));
}
if (!favoriteGroups.isEmpty()) {
FavoritesSettingsItem baseItem = getBaseItem(SettingsItemType.FAVOURITES, FavoritesSettingsItem.class);
settingsItems.add(new FavoritesSettingsItem(app, baseItem, favoriteGroups));
}
if (!markersGroups.isEmpty()) {
List<MapMarker> mapMarkers = new ArrayList<>();
for (MapMarkersGroup group : markersGroups) {
mapMarkers.addAll(group.getMarkers());
}
MarkersSettingsItem baseItem = getBaseItem(SettingsItemType.ACTIVE_MARKERS, MarkersSettingsItem.class);
settingsItems.add(new MarkersSettingsItem(app, baseItem, mapMarkers));
}
if (!markersHistoryGroups.isEmpty()) {
List<MapMarker> mapMarkers = new ArrayList<>();
for (MapMarkersGroup group : markersHistoryGroups) {
mapMarkers.addAll(group.getMarkers());
}
HistoryMarkersSettingsItem baseItem = getBaseItem(SettingsItemType.HISTORY_MARKERS, HistoryMarkersSettingsItem.class);
settingsItems.add(new HistoryMarkersSettingsItem(app, baseItem, mapMarkers));
}
if (!historyEntries.isEmpty()) {
SearchHistorySettingsItem baseItem = getBaseItem(SettingsItemType.SEARCH_HISTORY, SearchHistorySettingsItem.class);
settingsItems.add(new SearchHistorySettingsItem(app, baseItem, historyEntries));
}
if (!onlineRoutingEngines.isEmpty()) {
OnlineRoutingSettingsItem baseItem = getBaseItem(SettingsItemType.ONLINE_ROUTING_ENGINES, OnlineRoutingSettingsItem.class);
settingsItems.add(new OnlineRoutingSettingsItem(app, baseItem, onlineRoutingEngines));
}
return settingsItems;
}
public void setFile(File file) { public void setFile(File file) {
this.file = file; this.file = file;
} }

View file

@ -47,7 +47,7 @@ public class SegmentsCard extends BaseCard {
WrapContentHeightViewPager pager = segmentView.findViewById(R.id.pager); WrapContentHeightViewPager pager = segmentView.findViewById(R.id.pager);
PagerSlidingTabStrip tabLayout = segmentView.findViewById(R.id.sliding_tabs); PagerSlidingTabStrip tabLayout = segmentView.findViewById(R.id.sliding_tabs);
pager.setAdapter(new GPXItemPagerAdapter(tabLayout, displayItem, displayHelper, listener)); pager.setAdapter(new GPXItemPagerAdapter(app, displayItem, displayHelper, nightMode, listener));
tabLayout.setViewPager(pager); tabLayout.setViewPager(pager);
container.addView(segmentView); container.addView(segmentView);

View file

@ -149,6 +149,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
private Location lastLocation; private Location lastLocation;
private UpdateLocationViewCache updateLocationViewCache; private UpdateLocationViewCache updateLocationViewCache;
private boolean locationUpdateStarted; private boolean locationUpdateStarted;
private LatLon latLon;
private int menuTitleHeight; private int menuTitleHeight;
private int toolbarHeightPx; private int toolbarHeightPx;
@ -259,6 +260,10 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
this.selectedGpxFile = selectedGpxFile; this.selectedGpxFile = selectedGpxFile;
} }
public void setLatLon(LatLon latLon) {
this.latLon = latLon;
}
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState); View view = super.onCreateView(inflater, container, savedInstanceState);
@ -556,10 +561,9 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
MapActivity mapActivity = getMapActivity(); MapActivity mapActivity = getMapActivity();
View view = overviewCard.getView(); View view = overviewCard.getView();
if (mapActivity != null && view != null) { if (mapActivity != null && view != null) {
MapContextMenu menu = mapActivity.getContextMenu();
TextView distanceText = (TextView) view.findViewById(R.id.distance); TextView distanceText = (TextView) view.findViewById(R.id.distance);
ImageView direction = (ImageView) view.findViewById(R.id.direction); ImageView direction = (ImageView) view.findViewById(R.id.direction);
app.getUIUtilities().updateLocationView(updateLocationViewCache, direction, distanceText, menu.getLatLon()); app.getUIUtilities().updateLocationView(updateLocationViewCache, direction, distanceText, latLon);
} }
} }
@ -1113,7 +1117,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(path); selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(path);
} }
if (selectedGpxFile != null) { if (selectedGpxFile != null) {
showInstance(mapActivity, selectedGpxFile); showInstance(mapActivity, selectedGpxFile, null);
} else if (!Algorithms.isEmpty(path)) { } else if (!Algorithms.isEmpty(path)) {
String title = app.getString(R.string.loading_smth, ""); String title = app.getString(R.string.loading_smth, "");
final ProgressDialog progress = ProgressDialog.show(mapActivity, title, app.getString(R.string.loading_data)); final ProgressDialog progress = ProgressDialog.show(mapActivity, title, app.getString(R.string.loading_data));
@ -1126,7 +1130,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
if (mapActivity != null) { if (mapActivity != null) {
OsmandApplication app = mapActivity.getMyApplication(); OsmandApplication app = mapActivity.getMyApplication();
SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().selectGpxFile(result, true, false); SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().selectGpxFile(result, true, false);
showInstance(mapActivity, selectedGpxFile); showInstance(mapActivity, selectedGpxFile, null);
} }
if (progress != null && AndroidUtils.isActivityNotDestroyed(mapActivity)) { if (progress != null && AndroidUtils.isActivityNotDestroyed(mapActivity)) {
progress.dismiss(); progress.dismiss();
@ -1138,7 +1142,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
} }
} }
public static boolean showInstance(@NonNull MapActivity mapActivity, SelectedGpxFile selectedGpxFile) { public static boolean showInstance(@NonNull MapActivity mapActivity, SelectedGpxFile selectedGpxFile, @Nullable LatLon latLon) {
try { try {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putInt(ContextMenuFragment.MENU_STATE_KEY, MenuState.HEADER_ONLY); args.putInt(ContextMenuFragment.MENU_STATE_KEY, MenuState.HEADER_ONLY);
@ -1148,6 +1152,14 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
fragment.setRetainInstance(true); fragment.setRetainInstance(true);
fragment.setSelectedGpxFile(selectedGpxFile); fragment.setSelectedGpxFile(selectedGpxFile);
if (latLon != null) {
fragment.setLatLon(latLon);
} else {
QuadRect rect = selectedGpxFile.getGpxFile().getRect();
LatLon latLonRect = new LatLon(rect.centerY(), rect.centerX());
fragment.setLatLon(latLonRect);
}
mapActivity.getSupportFragmentManager() mapActivity.getSupportFragmentManager()
.beginTransaction() .beginTransaction()
.replace(R.id.fragmentContainer, fragment, TAG) .replace(R.id.fragmentContainer, fragment, TAG)

View file

@ -68,6 +68,7 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
public View getCustomTabView(@NonNull ViewGroup parent, int position); public View getCustomTabView(@NonNull ViewGroup parent, int position);
public void select(View tab); public void select(View tab);
public void deselect(View tab); public void deselect(View tab);
public void tabStylesUpdated(View tabsContainer, int currentPosition);
} }
public interface OnTabReselectedListener { public interface OnTabReselectedListener {
@ -307,6 +308,10 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
} }
} }
public int getCurrentPosition() {
return currentPosition;
}
private void addTab(final int position, CharSequence title, View tabView) { private void addTab(final int position, CharSequence title, View tabView) {
TextView textView = (TextView) tabView.findViewById(R.id.tab_title); TextView textView = (TextView) tabView.findViewById(R.id.tab_title);
if (textView != null) { if (textView != null) {
@ -332,41 +337,31 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
private void updateTabStyles() { private void updateTabStyles() {
tabsContainer.setBackgroundResource(tabBackgroundResId); tabsContainer.setBackgroundResource(tabBackgroundResId);
for (int i = 0; i < tabCount; i++) { if (pager.getAdapter() instanceof CustomTabProvider) {
View v = tabsContainer.getChildAt(i); ((CustomTabProvider) pager.getAdapter()).tabStylesUpdated(tabsContainer, currentPosition);
v.setBackgroundResource(tabBackgroundResId); } else {
v.setPadding(tabPadding, v.getPaddingTop(), tabPadding, v.getPaddingBottom()); for (int i = 0; i < tabCount; i++) {
TextView tab_title = (TextView) v.findViewById(R.id.tab_title); View v = tabsContainer.getChildAt(i);
v.setBackgroundResource(tabBackgroundResId);
v.setPadding(tabPadding, v.getPaddingTop(), tabPadding, v.getPaddingBottom());
if (tab_title != null) { TextView tabTitle = v.findViewById(R.id.tab_title);
tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabTextSize); if (tabTitle != null) {
tab_title.setTypeface(tabTypeface, pager.getCurrentItem() == i ? tabTypefaceSelectedStyle : tabTypefaceStyle); tabTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabTextSize);
switch (tabSelectionType) { tabTitle.setTypeface(tabTypeface, pager.getCurrentItem() == i ? tabTypefaceSelectedStyle : tabTypefaceStyle);
case ALPHA: switch (tabSelectionType) {
float alpha = pager.getCurrentItem() == i ? tabTextSelectedAlpha : tabTextAlpha; case ALPHA:
tab_title.setAlpha(alpha); float alpha = pager.getCurrentItem() == i ? tabTextSelectedAlpha : tabTextAlpha;
tab_title.setTextColor(tabTextColor); tabTitle.setAlpha(alpha);
break; tabTitle.setTextColor(tabTextColor);
case SOLID_COLOR: break;
tab_title.setAlpha(OPAQUE); case SOLID_COLOR:
tab_title.setTextColor(pager.getCurrentItem() == i ? tabTextColor : tabInactiveTextColor); tabTitle.setAlpha(OPAQUE);
break; tabTitle.setTextColor(pager.getCurrentItem() == i ? tabTextColor : tabInactiveTextColor);
} break;
if (pager.getAdapter() instanceof CustomTabProvider) {
if (pager.getCurrentItem() == i) {
((CustomTabProvider) pager.getAdapter()).select(v);
} else {
((CustomTabProvider) pager.getAdapter()).deselect(v);
} }
} if (textAllCaps) {
tabTitle.setAllCaps(true);
// setAllCaps() is only available from API 14, so the upper case is made manually if we are on a
// pre-ICS-build
if (textAllCaps) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
tab_title.setAllCaps(true);
} else {
tab_title.setText(tab_title.getText().toString().toUpperCase(locale));
} }
} }
} }
@ -558,39 +553,41 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
private void notSelected(View tab) { private void notSelected(View tab) {
if (tab != null) { if (tab != null) {
TextView title = (TextView) tab.findViewById(R.id.tab_title);
if (title != null) {
title.setTypeface(tabTypeface, tabTypefaceStyle);
switch (tabSelectionType) {
case ALPHA:
title.setAlpha(tabTextAlpha);
break;
case SOLID_COLOR:
title.setTextColor(tabInactiveTextColor);
break;
}
}
if (pager.getAdapter() instanceof CustomTabProvider) { if (pager.getAdapter() instanceof CustomTabProvider) {
((CustomTabProvider) pager.getAdapter()).deselect(tab); ((CustomTabProvider) pager.getAdapter()).deselect(tab);
} else {
TextView title = tab.findViewById(R.id.tab_title);
if (title != null) {
title.setTypeface(tabTypeface, tabTypefaceStyle);
switch (tabSelectionType) {
case ALPHA:
title.setAlpha(tabTextAlpha);
break;
case SOLID_COLOR:
title.setTextColor(tabInactiveTextColor);
break;
}
}
} }
} }
} }
private void selected(View tab) { private void selected(View tab) {
if (tab != null) { if (tab != null) {
TextView title = (TextView) tab.findViewById(R.id.tab_title); if (pager.getAdapter() instanceof CustomTabProvider) {
if (title != null) { ((CustomTabProvider) pager.getAdapter()).select(tab);
title.setTypeface(tabTypeface, tabTypefaceSelectedStyle); } else {
switch (tabSelectionType) { TextView title = tab.findViewById(R.id.tab_title);
case ALPHA: if (title != null) {
title.setAlpha(tabTextSelectedAlpha); title.setTypeface(tabTypeface, tabTypefaceSelectedStyle);
break; switch (tabSelectionType) {
case SOLID_COLOR: case ALPHA:
title.setTextColor(tabTextColor); title.setAlpha(tabTextSelectedAlpha);
break; break;
} case SOLID_COLOR:
if (pager.getAdapter() instanceof CustomTabProvider) { title.setTextColor(tabTextColor);
((CustomTabProvider) pager.getAdapter()).select(tab); break;
}
} }
} }
} }

View file

@ -1,8 +1,12 @@
package net.osmand.plus.wikipedia; package net.osmand.plus.wikipedia;
import android.app.Activity;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.text.SpannableString;
import android.text.style.StyleSpan;
import android.view.View; import android.view.View;
import android.widget.CompoundButton; import android.widget.CompoundButton;
@ -12,6 +16,8 @@ import androidx.core.content.ContextCompat;
import androidx.core.os.ConfigurationCompat; import androidx.core.os.ConfigurationCompat;
import androidx.core.os.LocaleListCompat; import androidx.core.os.LocaleListCompat;
import com.google.android.material.snackbar.Snackbar;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin; import net.osmand.plus.OsmandPlugin;
@ -124,6 +130,12 @@ public class SelectWikiLanguagesBottomSheet extends MenuBottomSheetDialogFragmen
} }
} }
@Nullable
public MapActivity getMapActivity() {
Activity activity = getActivity();
return (MapActivity) activity;
}
private void initLanguagesData() { private void initLanguagesData() {
languages = new ArrayList<>(); languages = new ArrayList<>();
@ -188,12 +200,44 @@ public class SelectWikiLanguagesBottomSheet extends MenuBottomSheetDialogFragmen
localesForSaving.add(language.getLocale()); localesForSaving.add(language.getLocale());
} }
} }
wikiPlugin.setLanguagesToShow(localesForSaving); applyPreferenceWithSnackBar(localesForSaving, isGlobalWikiPoiEnabled);
wikiPlugin.setShowAllLanguages(isGlobalWikiPoiEnabled);
wikiPlugin.updateWikipediaState();
dismiss(); dismiss();
} }
protected final void applyPreference(boolean applyToAllProfiles, List<String> localesForSaving, boolean global) {
if (applyToAllProfiles) {
for (ApplicationMode mode : ApplicationMode.allPossibleValues()) {
wikiPlugin.setLanguagesToShow(mode, localesForSaving);
wikiPlugin.setShowAllLanguages(mode, global);
}
} else {
wikiPlugin.setLanguagesToShow(localesForSaving);
wikiPlugin.setShowAllLanguages(global);
}
wikiPlugin.updateWikipediaState();
}
protected void applyPreferenceWithSnackBar(final List<String> localesForSaving, final boolean global) {
applyPreference(false, localesForSaving, global);
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
String modeName = appMode.toHumanString();
String text = app.getString(R.string.changes_applied_to_profile, modeName);
SpannableString message = UiUtilities.createSpannableString(text, new StyleSpan(Typeface.BOLD), modeName);
Snackbar snackbar = Snackbar.make(mapActivity.getLayout(), message, Snackbar.LENGTH_LONG)
.setAction(R.string.apply_to_all_profiles, new View.OnClickListener() {
@Override
public void onClick(View view) {
applyPreference(true, localesForSaving, global);
}
});
UiUtilities.setupSnackbarVerticalLayout(snackbar);
UiUtilities.setupSnackbar(snackbar, nightMode);
snackbar.show();
}
}
private View getCustomButtonView() { private View getCustomButtonView() {
OsmandApplication app = getMyApplication(); OsmandApplication app = getMyApplication();
if (app == null) { if (app == null) {
@ -265,7 +309,7 @@ public class SelectWikiLanguagesBottomSheet extends MenuBottomSheetDialogFragmen
} }
public static void showInstance(@NonNull MapActivity mapActivity, public static void showInstance(@NonNull MapActivity mapActivity,
boolean usedOnMap) { boolean usedOnMap) {
SelectWikiLanguagesBottomSheet fragment = new SelectWikiLanguagesBottomSheet(); SelectWikiLanguagesBottomSheet fragment = new SelectWikiLanguagesBottomSheet();
fragment.setUsedOnMap(usedOnMap); fragment.setUsedOnMap(usedOnMap);
fragment.show(mapActivity.getSupportFragmentManager(), SelectWikiLanguagesBottomSheet.TAG); fragment.show(mapActivity.getSupportFragmentManager(), SelectWikiLanguagesBottomSheet.TAG);

View file

@ -30,6 +30,7 @@ import net.osmand.plus.search.QuickSearchDialogFragment;
import net.osmand.plus.search.QuickSearchListAdapter; import net.osmand.plus.search.QuickSearchListAdapter;
import net.osmand.plus.search.listitems.QuickSearchBannerListItem; import net.osmand.plus.search.listitems.QuickSearchBannerListItem;
import net.osmand.plus.search.listitems.QuickSearchFreeBannerListItem; import net.osmand.plus.search.listitems.QuickSearchFreeBannerListItem;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.views.layers.DownloadedRegionsLayer; import net.osmand.plus.views.layers.DownloadedRegionsLayer;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
@ -97,8 +98,8 @@ public class WikipediaPlugin extends OsmandPlugin {
@Override @Override
protected void registerLayerContextMenuActions(OsmandMapTileView mapView, protected void registerLayerContextMenuActions(OsmandMapTileView mapView,
ContextMenuAdapter adapter, ContextMenuAdapter adapter,
final MapActivity mapActivity) { final MapActivity mapActivity) {
ContextMenuAdapter.ItemClickListener listener = new ContextMenuAdapter.OnRowItemClick() { ContextMenuAdapter.ItemClickListener listener = new ContextMenuAdapter.OnRowItemClick() {
@Override @Override
@ -113,7 +114,7 @@ public class WikipediaPlugin extends OsmandPlugin {
@Override @Override
public boolean onContextMenuClick(final ArrayAdapter<ContextMenuItem> adapter, int itemId, public boolean onContextMenuClick(final ArrayAdapter<ContextMenuItem> adapter, int itemId,
final int pos, boolean isChecked, int[] viewCoordinates) { final int pos, boolean isChecked, int[] viewCoordinates) {
if (itemId == R.string.shared_string_wikipedia) { if (itemId == R.string.shared_string_wikipedia) {
toggleWikipediaPoi(isChecked, new CallbackWithObject<Boolean>() { toggleWikipediaPoi(isChecked, new CallbackWithObject<Boolean>() {
@Override @Override
@ -189,26 +190,50 @@ public class WikipediaPlugin extends OsmandPlugin {
return !isShowAllLanguages() && getLanguagesToShow() != null; return !isShowAllLanguages() && getLanguagesToShow() != null;
} }
public boolean hasCustomSettings(ApplicationMode profile) {
return !isShowAllLanguages(profile) && getLanguagesToShow(profile) != null;
}
public boolean hasLanguagesFilter() { public boolean hasLanguagesFilter() {
return settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.get() != null; return settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.get() != null;
} }
public boolean hasLanguagesFilter(ApplicationMode profile) {
return settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.getModeValue(profile) != null;
}
public boolean isShowAllLanguages() { public boolean isShowAllLanguages() {
return settings.GLOBAL_WIKIPEDIA_POI_ENABLED.get(); return settings.GLOBAL_WIKIPEDIA_POI_ENABLED.get();
} }
public boolean isShowAllLanguages(ApplicationMode mode) {
return settings.GLOBAL_WIKIPEDIA_POI_ENABLED.getModeValue(mode);
}
public void setShowAllLanguages(boolean showAllLanguages) { public void setShowAllLanguages(boolean showAllLanguages) {
settings.GLOBAL_WIKIPEDIA_POI_ENABLED.set(showAllLanguages); settings.GLOBAL_WIKIPEDIA_POI_ENABLED.set(showAllLanguages);
} }
public void setShowAllLanguages(ApplicationMode mode, boolean showAllLanguages) {
settings.GLOBAL_WIKIPEDIA_POI_ENABLED.setModeValue(mode, showAllLanguages);
}
public List<String> getLanguagesToShow() { public List<String> getLanguagesToShow() {
return settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.getStringsList(); return settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.getStringsList();
} }
public List<String> getLanguagesToShow(ApplicationMode mode) {
return settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.getStringsListForProfile(mode);
}
public void setLanguagesToShow(List<String> languagesToShow) { public void setLanguagesToShow(List<String> languagesToShow) {
settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.setStringsList(languagesToShow); settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.setStringsList(languagesToShow);
} }
public void setLanguagesToShow(ApplicationMode mode, List<String> languagesToShow) {
settings.WIKIPEDIA_POI_ENABLED_LANGUAGES.setStringsListForProfile(mode, languagesToShow);
}
public void toggleWikipediaPoi(boolean enable, CallbackWithObject<Boolean> callback) { public void toggleWikipediaPoi(boolean enable, CallbackWithObject<Boolean> callback) {
if (enable) { if (enable) {
showWikiOnMap(); showWikiOnMap();